Coverage Report

Created: 2026-09-01 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/njs/src/njs_parser.c
Line
Count
Source
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) Alexander Borisov
5
 * Copyright (C) NGINX, Inc.
6
 */
7
8
9
#include <njs_main.h>
10
11
12
static njs_int_t njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type,
13
    njs_bool_t init_this);
14
static void njs_parser_scope_end(njs_parser_t *parser);
15
16
static njs_int_t njs_parser_check_error_state(njs_parser_t *parser,
17
    njs_lexer_token_t *token, njs_queue_link_t *current);
18
19
static njs_int_t njs_parser_primary_expression_test(njs_parser_t *parser,
20
    njs_lexer_token_t *token, njs_queue_link_t *current);
21
static njs_int_t njs_parser_regexp_literal(njs_parser_t *parser,
22
    njs_lexer_token_t *token, njs_queue_link_t *current);
23
static njs_int_t njs_parser_template_literal(njs_parser_t *parser,
24
    njs_lexer_token_t *token, njs_queue_link_t *current);
25
static njs_int_t njs_parser_template_literal_string(njs_parser_t *parser,
26
    njs_lexer_token_t *token, njs_queue_link_t *current);
27
static njs_int_t njs_parser_template_literal_expression(
28
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
29
static njs_int_t njs_parser_cover_parenthesized_expression(
30
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
31
static njs_int_t njs_parser_binding_identifier_pattern(njs_parser_t *parser,
32
    njs_lexer_token_t *token, njs_queue_link_t *current);
33
static njs_int_t njs_parser_cover_parenthesized_expression_after(
34
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
35
static njs_int_t njs_parser_cover_parenthesized_expression_end(
36
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
37
38
static njs_int_t njs_parser_array_literal(njs_parser_t *parser,
39
    njs_lexer_token_t *token, njs_queue_link_t *current);
40
static njs_int_t njs_parser_array_element_list(njs_parser_t *parser,
41
    njs_lexer_token_t *token, njs_queue_link_t *current);
42
static njs_int_t njs_parser_array_after(njs_parser_t *parser,
43
    njs_lexer_token_t *token, njs_queue_link_t *current);
44
static njs_int_t njs_parser_array_spread_element(njs_parser_t *parser,
45
    njs_lexer_token_t *token, njs_queue_link_t *current);
46
47
static njs_int_t njs_parser_object_literal(njs_parser_t *parser,
48
    njs_lexer_token_t *token, njs_queue_link_t *current);
49
static njs_int_t njs_parser_object_literal_after(njs_parser_t *parser,
50
    njs_lexer_token_t *token, njs_queue_link_t *current);
51
static njs_parser_node_t *njs_parser_object_value(njs_parser_t *parser,
52
    njs_parser_node_t *parent, uint32_t token_line);
53
static njs_int_t njs_parser_property_definition_list(njs_parser_t *parser,
54
    njs_lexer_token_t *token, njs_queue_link_t *current);
55
static njs_int_t njs_parser_property_definition_list_after(
56
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
57
static njs_int_t njs_parser_property_definition(njs_parser_t *parser,
58
    njs_lexer_token_t *token, njs_queue_link_t *current);
59
static njs_int_t njs_parser_property_definition_after(njs_parser_t *parser,
60
    njs_lexer_token_t *token, njs_queue_link_t *current);
61
static njs_int_t njs_parser_computed_property_name_after(njs_parser_t *parser,
62
    njs_lexer_token_t *token, njs_queue_link_t *current);
63
static njs_int_t njs_parser_computed_property_async_after(njs_parser_t *parser,
64
    njs_lexer_token_t *token, njs_queue_link_t *current);
65
static njs_int_t njs_parser_computed_property_name_handler(njs_parser_t *parser,
66
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async);
67
68
static njs_int_t njs_parser_initializer(njs_parser_t *parser,
69
    njs_lexer_token_t *token, njs_queue_link_t *current);
70
static njs_int_t njs_parser_initializer_after(njs_parser_t *parser,
71
    njs_lexer_token_t *token, njs_queue_link_t *current);
72
static njs_int_t njs_parser_initializer_assign(njs_parser_t *parser,
73
    njs_token_type_t type);
74
75
static njs_int_t njs_parser_member_expression(njs_parser_t *parser,
76
    njs_lexer_token_t *token, njs_queue_link_t *current);
77
static njs_int_t njs_parser_member_expression_next(njs_parser_t *parser,
78
    njs_lexer_token_t *token, njs_queue_link_t *current);
79
static njs_int_t njs_parser_member_expression_bracket(njs_parser_t *parser,
80
    njs_lexer_token_t *token, njs_queue_link_t *current);
81
static njs_int_t njs_parser_member_expression_new_next(njs_parser_t *parser,
82
    njs_lexer_token_t *token, njs_queue_link_t *current);
83
static njs_int_t njs_parser_super_property(njs_parser_t *parser,
84
    njs_lexer_token_t *token, njs_queue_link_t *current);
85
static njs_int_t njs_parser_member_expression_import(njs_parser_t *parser,
86
    njs_lexer_token_t *token, njs_queue_link_t *current);
87
static njs_int_t njs_parser_member_expression_new(njs_parser_t *parser,
88
    njs_lexer_token_t *token, njs_queue_link_t *current);
89
static njs_int_t njs_parser_member_expression_new_after(njs_parser_t *parser,
90
    njs_lexer_token_t *token, njs_queue_link_t *current);
91
static njs_int_t njs_parser_member_expression_new_args(njs_parser_t *parser,
92
    njs_lexer_token_t *token, njs_queue_link_t *current);
93
94
static njs_parser_node_t *njs_parser_create_call(njs_parser_t *parser,
95
    njs_parser_node_t *node, uint8_t ctor);
96
static njs_int_t njs_parser_call_arguments(njs_parser_t *parser,
97
    njs_lexer_token_t *token, njs_queue_link_t *current,
98
    njs_parser_node_t *func, njs_parser_state_func_t after);
99
100
static njs_int_t njs_parser_right_link_pop(njs_parser_t *parser);
101
static njs_parser_node_t *njs_parser_property_ref(njs_parser_node_t *node);
102
static njs_parser_node_t *njs_parser_lvalue_ref(njs_parser_node_t *node);
103
static njs_parser_node_t *njs_parser_call_receiver(njs_parser_node_t *node);
104
static njs_parser_node_t *njs_parser_optional_chain_preserve(
105
    njs_parser_t *parser, njs_parser_node_t *node, uint32_t token_line);
106
static njs_parser_node_t *njs_parser_optional_chain_source(
107
    njs_parser_node_t *node);
108
static njs_parser_node_t *njs_parser_optional_chain_receiver(
109
    njs_parser_node_t *node);
110
static njs_parser_node_t *njs_parser_optional_chain_call_this(
111
    njs_parser_node_t *node);
112
static void njs_parser_set_call_this(njs_parser_node_t *node,
113
    njs_parser_node_t *this_object);
114
static void njs_parser_set_optional_method_call_preserve(
115
    njs_parser_node_t *node, njs_parser_node_t *preserve);
116
static njs_parser_node_t *njs_parser_optional_chain_target_property(
117
    njs_parser_node_t *node);
118
static njs_parser_node_t *njs_parser_optional_chain_method_call(
119
    njs_parser_t *parser, njs_parser_node_t *node, uint32_t token_line);
120
static njs_parser_node_t *njs_parser_optional_chain_call(
121
    njs_parser_t *parser, njs_parser_node_t *node,
122
    njs_parser_node_t *fallback, uint32_t token_line);
123
static njs_int_t njs_parser_call_expression(njs_parser_t *parser,
124
    njs_lexer_token_t *token, njs_queue_link_t *current);
125
static njs_int_t njs_parser_call_expression_args(njs_parser_t *parser,
126
    njs_lexer_token_t *token, njs_queue_link_t *current);
127
static njs_int_t njs_parser_call_or_property_after(njs_parser_t *parser,
128
    njs_lexer_token_t *token, njs_queue_link_t *current,
129
    njs_parser_state_func_t after);
130
static njs_int_t njs_parser_call_expression_after(njs_parser_t *parser,
131
    njs_lexer_token_t *token, njs_queue_link_t *current);
132
static njs_int_t njs_parser_arguments(njs_parser_t *parser,
133
    njs_lexer_token_t *token, njs_queue_link_t *current);
134
static njs_int_t njs_parser_parenthesis_or_comma(njs_parser_t *parser,
135
    njs_lexer_token_t *token, njs_queue_link_t *current);
136
static njs_int_t njs_parser_argument_list(njs_parser_t *parser,
137
    njs_lexer_token_t *token, njs_queue_link_t *current);
138
static njs_int_t njs_parser_argument_list_after(njs_parser_t *parser,
139
    njs_lexer_token_t *token, njs_queue_link_t *current);
140
static njs_int_t njs_parser_optional_expression_after(njs_parser_t *parser,
141
    njs_lexer_token_t *token, njs_queue_link_t *current);
142
static njs_int_t njs_parser_optional_chain(njs_parser_t *parser,
143
    njs_lexer_token_t *token, njs_queue_link_t *current);
144
static njs_int_t njs_parser_optional_chain_after(njs_parser_t *parser,
145
    njs_lexer_token_t *token, njs_queue_link_t *current);
146
static njs_int_t njs_parser_new_expression(njs_parser_t *parser,
147
    njs_lexer_token_t *token, njs_queue_link_t *current);
148
static njs_int_t njs_parser_new_expression_after(njs_parser_t *parser,
149
    njs_lexer_token_t *token, njs_queue_link_t *current);
150
static njs_int_t njs_parser_left_hand_side_expression(njs_parser_t *parser,
151
    njs_lexer_token_t *token, njs_queue_link_t *current);
152
static njs_int_t njs_parser_left_hand_side_expression_after(
153
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
154
static njs_int_t njs_parser_left_hand_side_expression_node(
155
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
156
static njs_int_t njs_parser_left_hand_side_expression_optional(
157
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
158
static njs_int_t njs_parser_update_expression(njs_parser_t *parser,
159
    njs_lexer_token_t *token, njs_queue_link_t *current);
160
static njs_int_t njs_parser_update_expression_post(njs_parser_t *parser,
161
    njs_lexer_token_t *token, njs_queue_link_t *current);
162
static njs_int_t njs_parser_update_expression_unary(njs_parser_t *parser,
163
    njs_lexer_token_t *token, njs_queue_link_t *current);
164
165
static njs_int_t njs_parser_unary_expression(njs_parser_t *parser,
166
    njs_lexer_token_t *token, njs_queue_link_t *current);
167
static njs_int_t njs_parser_unary_expression_after(njs_parser_t *parser,
168
    njs_lexer_token_t *token, njs_queue_link_t *current);
169
static njs_int_t njs_parser_unary_expression_next(njs_parser_t *parser,
170
    njs_lexer_token_t *token, njs_queue_link_t *current);
171
static njs_int_t njs_parser_await(njs_parser_t *parser,
172
    njs_lexer_token_t *token, njs_queue_link_t *current);
173
static njs_int_t njs_parser_await_after(njs_parser_t *parser,
174
    njs_lexer_token_t *token, njs_queue_link_t *current);
175
176
static njs_int_t njs_parser_exponentiation_expression(njs_parser_t *parser,
177
    njs_lexer_token_t *token, njs_queue_link_t *current);
178
static njs_int_t njs_parser_exponentiation_expression_match(
179
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
180
181
static njs_int_t njs_parser_multiplicative_expression(njs_parser_t *parser,
182
    njs_lexer_token_t *token, njs_queue_link_t *current);
183
static njs_int_t njs_parser_multiplicative_expression_match(
184
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
185
186
static njs_int_t njs_parser_additive_expression(njs_parser_t *parser,
187
    njs_lexer_token_t *token, njs_queue_link_t *current);
188
static njs_int_t njs_parser_additive_expression_match(njs_parser_t *parser,
189
    njs_lexer_token_t *token, njs_queue_link_t *current);
190
191
static njs_int_t njs_parser_shift_expression(njs_parser_t *parser,
192
    njs_lexer_token_t *token, njs_queue_link_t *current);
193
static njs_int_t njs_parser_shift_expression_match(njs_parser_t *parser,
194
    njs_lexer_token_t *token, njs_queue_link_t *current);
195
196
static njs_int_t njs_parser_relational_expression(njs_parser_t *parser,
197
    njs_lexer_token_t *token, njs_queue_link_t *current);
198
static njs_int_t njs_parser_relational_expression_match(njs_parser_t *parser,
199
    njs_lexer_token_t *token, njs_queue_link_t *current);
200
201
static njs_int_t njs_parser_equality_expression(njs_parser_t *parser,
202
    njs_lexer_token_t *token, njs_queue_link_t *current);
203
static njs_int_t njs_parser_equality_expression_match(njs_parser_t *parser,
204
    njs_lexer_token_t *token, njs_queue_link_t *current);
205
206
static njs_int_t njs_parser_bitwise_AND_expression(njs_parser_t *parser,
207
    njs_lexer_token_t *token, njs_queue_link_t *current);
208
static njs_int_t njs_parser_bitwise_AND_expression_and(njs_parser_t *parser,
209
    njs_lexer_token_t *token, njs_queue_link_t *current);
210
static njs_int_t njs_parser_bitwise_XOR_expression(njs_parser_t *parser,
211
    njs_lexer_token_t *token, njs_queue_link_t *current);
212
static njs_int_t njs_parser_bitwise_XOR_expression_xor(njs_parser_t *parser,
213
    njs_lexer_token_t *token, njs_queue_link_t *current);
214
static njs_int_t njs_parser_bitwise_OR_expression(njs_parser_t *parser,
215
    njs_lexer_token_t *token, njs_queue_link_t *current);
216
static njs_int_t njs_parser_bitwise_OR_expression_or(njs_parser_t *parser,
217
    njs_lexer_token_t *token, njs_queue_link_t *current);
218
219
static njs_int_t njs_parser_logical_AND_expression(njs_parser_t *parser,
220
    njs_lexer_token_t *token, njs_queue_link_t *current);
221
static njs_int_t njs_parser_logical_AND_expression_and(njs_parser_t *parser,
222
    njs_lexer_token_t *token, njs_queue_link_t *current);
223
static njs_int_t njs_parser_logical_OR_expression(njs_parser_t *parser,
224
    njs_lexer_token_t *token, njs_queue_link_t *current);
225
static njs_int_t njs_parser_logical_OR_expression_or(njs_parser_t *parser,
226
    njs_lexer_token_t *token, njs_queue_link_t *current);
227
static njs_int_t njs_parser_coalesce_expression(njs_parser_t *parser,
228
    njs_lexer_token_t *token, njs_queue_link_t *current);
229
static njs_int_t njs_parser_short_circuit_expression(njs_parser_t *parser,
230
    njs_lexer_token_t *token, njs_queue_link_t *current);
231
232
static njs_int_t njs_parser_conditional_expression(njs_parser_t *parser,
233
    njs_lexer_token_t *token, njs_queue_link_t *current);
234
static njs_int_t njs_parser_conditional_question_mark(njs_parser_t *parser,
235
    njs_lexer_token_t *token, njs_queue_link_t *current);
236
static njs_int_t njs_parser_conditional_colon(njs_parser_t *parser,
237
    njs_lexer_token_t *token, njs_queue_link_t *current);
238
static njs_int_t njs_parser_conditional_colon_after(njs_parser_t *parser,
239
    njs_lexer_token_t *token, njs_queue_link_t *current);
240
241
static njs_int_t njs_parser_assignment_expression(njs_parser_t *parser,
242
    njs_lexer_token_t *token, njs_queue_link_t *current);
243
static njs_int_t njs_parser_match_arrow_expression(njs_parser_t *parser,
244
    njs_lexer_token_t *token);
245
static njs_int_t njs_parser_assignment_expression_after(njs_parser_t *parser,
246
    njs_lexer_token_t *token, njs_queue_link_t *current);
247
static njs_int_t njs_parser_assignment_operator(njs_parser_t *parser,
248
    njs_lexer_token_t *token, njs_queue_link_t *current);
249
static njs_int_t njs_parser_assignment_operator_after(njs_parser_t *parser,
250
    njs_lexer_token_t *token, njs_queue_link_t *current);
251
252
static njs_int_t njs_parser_expression(njs_parser_t *parser,
253
    njs_lexer_token_t *token, njs_queue_link_t *current);
254
static njs_int_t njs_parser_expression_comma(njs_parser_t *parser,
255
    njs_lexer_token_t *token, njs_queue_link_t *current);
256
257
static njs_int_t njs_parser_statement(njs_parser_t *parser,
258
    njs_lexer_token_t *token, njs_queue_link_t *current);
259
static njs_int_t njs_parser_statement_wo_node(njs_parser_t *parser,
260
    njs_lexer_token_t *token, njs_queue_link_t *current);
261
static njs_int_t njs_parser_statement_after(njs_parser_t *parser,
262
    njs_lexer_token_t *token, njs_queue_link_t *current);
263
static njs_int_t njs_parser_declaration(njs_parser_t *parser,
264
    njs_lexer_token_t *token, njs_queue_link_t *current);
265
static njs_int_t njs_parser_hoistable_declaration(njs_parser_t *parser,
266
    njs_lexer_token_t *token, njs_queue_link_t *current);
267
268
static njs_int_t njs_parser_block_statement(njs_parser_t *parser,
269
    njs_lexer_token_t *token, njs_queue_link_t *current);
270
static njs_int_t njs_parser_block_statement_open_brace(njs_parser_t *parser,
271
    njs_lexer_token_t *token, njs_queue_link_t *current);
272
static njs_int_t njs_parser_block_statement_close_brace(njs_parser_t *parser,
273
    njs_lexer_token_t *token, njs_queue_link_t *current);
274
static njs_int_t njs_parser_statement_list(njs_parser_t *parser,
275
    njs_lexer_token_t *token, njs_queue_link_t *current);
276
static njs_int_t njs_parser_statement_list_next(njs_parser_t *parser,
277
    njs_lexer_token_t *token, njs_queue_link_t *current);
278
static njs_int_t njs_parser_statement_list_item(njs_parser_t *parser,
279
    njs_lexer_token_t *token, njs_queue_link_t *current);
280
281
static njs_int_t njs_parser_lexical_declaration(njs_parser_t *parser,
282
    njs_lexer_token_t *token, njs_queue_link_t *current);
283
static njs_int_t njs_parser_variable_statement(njs_parser_t *parser,
284
    njs_lexer_token_t *token, njs_queue_link_t *current);
285
static njs_int_t njs_parser_variable_declaration_list(njs_parser_t *parser,
286
    njs_lexer_token_t *token, njs_queue_link_t *current);
287
static njs_int_t njs_parser_variable_declaration_list_next(
288
    njs_parser_t *parser, njs_lexer_token_t *token, njs_queue_link_t *current);
289
static njs_int_t njs_parser_variable_declaration(njs_parser_t *parser,
290
    njs_lexer_token_t *token, njs_queue_link_t *current);
291
292
static njs_int_t njs_parser_binding_pattern(njs_parser_t *parser,
293
    njs_lexer_token_t *token, njs_queue_link_t *current);
294
static njs_int_t njs_parser_object_binding_pattern(njs_parser_t *parser,
295
    njs_lexer_token_t *token, njs_queue_link_t *current);
296
static njs_int_t njs_parser_array_binding_pattern(njs_parser_t *parser,
297
    njs_lexer_token_t *token, njs_queue_link_t *current);
298
299
static njs_int_t njs_parser_expression_statement(njs_parser_t *parser,
300
    njs_lexer_token_t *token, njs_queue_link_t *current);
301
static njs_int_t njs_parser_expression_statement_after(njs_parser_t *parser,
302
    njs_lexer_token_t *token, njs_queue_link_t *current);
303
304
static njs_int_t njs_parser_if_statement(njs_parser_t *parser,
305
    njs_lexer_token_t *token, njs_queue_link_t *current);
306
static njs_int_t njs_parser_if_close_parenthesis(njs_parser_t *parser,
307
    njs_lexer_token_t *token, njs_queue_link_t *current);
308
static njs_int_t njs_parser_else_statement(njs_parser_t *parser,
309
    njs_lexer_token_t *token, njs_queue_link_t *current);
310
static njs_int_t njs_parser_else_statement_after(njs_parser_t *parser,
311
    njs_lexer_token_t *token, njs_queue_link_t *current);
312
313
static njs_int_t njs_parser_iteration_statement_do(njs_parser_t *parser,
314
    njs_lexer_token_t *token, njs_queue_link_t *current);
315
static njs_int_t njs_parser_iteration_statement_do_while(njs_parser_t *parser,
316
    njs_lexer_token_t *token, njs_queue_link_t *current);
317
static njs_int_t njs_parser_do_while_semicolon(njs_parser_t *parser,
318
    njs_lexer_token_t *token, njs_queue_link_t *current);
319
320
static njs_int_t njs_parser_iteration_statement_while(njs_parser_t *parser,
321
    njs_lexer_token_t *token, njs_queue_link_t *current);
322
static njs_int_t njs_parser_while_statement(njs_parser_t *parser,
323
    njs_lexer_token_t *token, njs_queue_link_t *current);
324
static njs_int_t njs_parser_while_after(njs_parser_t *parser,
325
    njs_lexer_token_t *token, njs_queue_link_t *current);
326
327
static njs_int_t njs_parser_iteration_statement_for(njs_parser_t *parser,
328
    njs_lexer_token_t *token, njs_queue_link_t *current);
329
static njs_int_t njs_parser_for_expression_map_continue(
330
    njs_parser_t *parser, njs_lexer_token_t *token,
331
    njs_queue_link_t *current);
332
static njs_int_t njs_parser_for_expression_map_reparse(
333
    njs_parser_t *parser, njs_lexer_token_t *token,
334
    njs_queue_link_t *current);
335
static njs_int_t njs_parser_expression_continue_op(njs_parser_t *parser,
336
    njs_lexer_token_t *token, njs_queue_link_t *current);
337
static njs_int_t njs_parser_expression_continue_assign_comma(
338
    njs_parser_t *parser, njs_lexer_token_t *token,
339
    njs_queue_link_t *current);
340
static njs_int_t njs_parser_for_in_statement_statement(njs_parser_t *parser,
341
    njs_lexer_token_t *token, njs_queue_link_t *current);
342
static njs_int_t njs_parser_iteration_statement_for_map(njs_parser_t *parser,
343
    njs_lexer_token_t *token, njs_queue_link_t *current);
344
static njs_int_t njs_parser_for_var_binding_or_var_list(njs_parser_t *parser,
345
    njs_lexer_token_t *token, njs_queue_link_t *current,
346
    njs_token_type_t token_type);
347
static njs_int_t njs_parser_for_var_in_statement(njs_parser_t *parser,
348
    njs_lexer_token_t *token, njs_queue_link_t *current);
349
static njs_int_t njs_parser_for_var_in_statement_after(njs_parser_t *parser,
350
    njs_lexer_token_t *token, njs_queue_link_t *current);
351
static njs_int_t njs_parser_for_var_in_of_expression(njs_parser_t *parser,
352
    njs_lexer_token_t *token, njs_queue_link_t *current);
353
static njs_int_t njs_parser_for_in_statement(njs_parser_t *parser,
354
    njs_lexer_token_t *token, njs_queue_link_t *current);
355
static njs_int_t njs_parser_for_in_statement_after(njs_parser_t *parser,
356
    njs_lexer_token_t *token, njs_queue_link_t *current);
357
static njs_int_t njs_parser_for_expression(njs_parser_t *parser,
358
    njs_lexer_token_t *token, njs_queue_link_t *current);
359
static njs_int_t njs_parser_for_expression_end(njs_parser_t *parser,
360
    njs_lexer_token_t *token, njs_queue_link_t *current);
361
static njs_int_t njs_parser_for_end(njs_parser_t *parser,
362
    njs_lexer_token_t *token, njs_queue_link_t *current);
363
364
static njs_int_t njs_parser_switch_statement(njs_parser_t *parser,
365
    njs_lexer_token_t *token, njs_queue_link_t *current);
366
static njs_int_t njs_parser_switch_statement_after(njs_parser_t *parser,
367
    njs_lexer_token_t *token, njs_queue_link_t *current);
368
static njs_int_t njs_parser_switch_block(njs_parser_t *parser,
369
    njs_lexer_token_t *token, njs_queue_link_t *current);
370
static njs_int_t njs_parser_switch_block_after(njs_parser_t *parser,
371
    njs_lexer_token_t *token, njs_queue_link_t *current);
372
static njs_int_t njs_parser_switch_case(njs_parser_t *parser,
373
    njs_lexer_token_t *token, njs_queue_link_t *current);
374
static njs_int_t njs_parser_switch_case_wo_def(njs_parser_t *parser,
375
    njs_lexer_token_t *token, njs_queue_link_t *current);
376
static njs_int_t njs_parser_switch_case_def(njs_parser_t *parser,
377
    njs_lexer_token_t *token, njs_queue_link_t *current,
378
    njs_bool_t with_default);
379
static njs_int_t njs_parser_switch_case_after(njs_parser_t *parser,
380
    njs_lexer_token_t *token, njs_queue_link_t *current);
381
static njs_int_t njs_parser_switch_case_block(njs_parser_t *parser,
382
    njs_lexer_token_t *token, njs_queue_link_t *current);
383
static njs_int_t njs_parser_switch_case_after_wo_def(njs_parser_t *parser,
384
    njs_lexer_token_t *token, njs_queue_link_t *current);
385
static njs_int_t njs_parser_switch_case_block_wo_def(njs_parser_t *parser,
386
    njs_lexer_token_t *token, njs_queue_link_t *current);
387
388
static njs_int_t njs_parser_continue_statement(njs_parser_t *parser,
389
    njs_lexer_token_t *token, njs_queue_link_t *current);
390
391
static njs_int_t njs_parser_break_statement(njs_parser_t *parser,
392
    njs_lexer_token_t *token, njs_queue_link_t *current);
393
394
static njs_int_t njs_parser_break_continue(njs_parser_t *parser,
395
    njs_lexer_token_t *token, njs_token_type_t type);
396
397
static njs_int_t njs_parser_return_statement(njs_parser_t *parser,
398
    njs_lexer_token_t *token, njs_queue_link_t *current);
399
static njs_int_t njs_parser_return_statement_after(njs_parser_t *parser,
400
    njs_lexer_token_t *token, njs_queue_link_t *current);
401
402
static njs_int_t njs_parser_with_statement(njs_parser_t *parser,
403
    njs_lexer_token_t *token, njs_queue_link_t *current);
404
405
static njs_int_t njs_parser_labelled_statement(njs_parser_t *parser,
406
    njs_lexer_token_t *token, njs_queue_link_t *current);
407
static njs_int_t njs_parser_labelled_statement_after(njs_parser_t *parser,
408
    njs_lexer_token_t *token, njs_queue_link_t *current);
409
410
static njs_int_t njs_parser_throw_statement(njs_parser_t *parser,
411
    njs_lexer_token_t *token, njs_queue_link_t *current);
412
static njs_int_t njs_parser_throw_statement_after(njs_parser_t *parser,
413
    njs_lexer_token_t *token, njs_queue_link_t *current);
414
415
static njs_int_t njs_parser_try_statement(njs_parser_t *parser,
416
    njs_lexer_token_t *token, njs_queue_link_t *current);
417
static njs_int_t njs_parser_catch_or_finally(njs_parser_t *parser,
418
    njs_lexer_token_t *token, njs_queue_link_t *current);
419
static njs_int_t njs_parser_catch_after(njs_parser_t *parser,
420
    njs_lexer_token_t *token, njs_queue_link_t *current);
421
static njs_int_t njs_parser_catch_parenthesis(njs_parser_t *parser,
422
    njs_lexer_token_t *token, njs_queue_link_t *current);
423
static njs_int_t njs_parser_catch_statement_open_brace(njs_parser_t *parser,
424
    njs_lexer_token_t *token, njs_queue_link_t *current);
425
static njs_int_t njs_parser_catch_finally(njs_parser_t *parser,
426
    njs_lexer_token_t *token, njs_queue_link_t *current);
427
428
static njs_int_t njs_parser_debugger_statement(njs_parser_t *parser,
429
    njs_lexer_token_t *token, njs_queue_link_t *current);
430
431
static njs_int_t njs_parser_function_declaration(njs_parser_t *parser,
432
    njs_lexer_token_t *token, njs_queue_link_t *current);
433
static njs_int_t njs_parser_function_declaration_after(njs_parser_t *parser,
434
    njs_lexer_token_t *token, njs_queue_link_t *current);
435
static njs_int_t njs_parser_function_parse(njs_parser_t *parser,
436
    njs_lexer_token_t *token, njs_queue_link_t *current);
437
static njs_int_t njs_parser_function_expression(njs_parser_t *parser,
438
    njs_lexer_token_t *token, njs_queue_link_t *current);
439
static njs_int_t njs_parser_function_expression_after(njs_parser_t *parser,
440
    njs_lexer_token_t *token, njs_queue_link_t *current);
441
static njs_int_t njs_parser_unique_formal_parameters(njs_parser_t *parser,
442
    njs_lexer_token_t *token, njs_queue_link_t *current);
443
static njs_int_t njs_parser_formal_parameters(njs_parser_t *parser,
444
    njs_lexer_token_t *token, njs_queue_link_t *current);
445
static njs_int_t njs_parser_formal_parameters_after(njs_parser_t *parser,
446
    njs_lexer_token_t *token, njs_queue_link_t *current);
447
448
static njs_int_t njs_parser_arrow_function(njs_parser_t *parser,
449
    njs_lexer_token_t *token, njs_queue_link_t *current);
450
static njs_int_t njs_parser_arrow_function_args_after(njs_parser_t *parser,
451
    njs_lexer_token_t *token, njs_queue_link_t *current);
452
static njs_int_t njs_parser_arrow_function_arrow(njs_parser_t *parser,
453
    njs_lexer_token_t *token, njs_queue_link_t *current);
454
static njs_int_t njs_parser_arrow_function_body_after(njs_parser_t *parser,
455
    njs_lexer_token_t *token, njs_queue_link_t *current);
456
457
static njs_int_t njs_parser_method_definition(njs_parser_t *parser,
458
    njs_lexer_token_t *token, njs_queue_link_t *current);
459
static njs_int_t njs_parser_get_set(njs_parser_t *parser,
460
    njs_lexer_token_t *token, njs_queue_link_t *current);
461
static njs_int_t njs_parser_get_set_after(njs_parser_t *parser,
462
    njs_lexer_token_t *token, njs_queue_link_t *current);
463
static njs_int_t njs_parser_get_after(njs_parser_t *parser,
464
    njs_lexer_token_t *token, njs_queue_link_t *current);
465
static njs_int_t njs_parser_set_after(njs_parser_t *parser,
466
    njs_lexer_token_t *token, njs_queue_link_t *current);
467
static njs_int_t njs_parser_function_lambda(njs_parser_t *parser,
468
    njs_lexer_token_t *token, njs_queue_link_t *current);
469
static njs_int_t njs_parser_function_lambda_args_after(njs_parser_t *parser,
470
    njs_lexer_token_t *token, njs_queue_link_t *current);
471
static njs_int_t njs_parser_function_lambda_body_after(njs_parser_t *parser,
472
    njs_lexer_token_t *token, njs_queue_link_t *current);
473
474
static njs_int_t njs_parser_export(njs_parser_t *parser,
475
    njs_lexer_token_t *token, njs_queue_link_t *current);
476
static njs_int_t njs_parser_export_after(njs_parser_t *parser,
477
    njs_lexer_token_t *token, njs_queue_link_t *current);
478
479
static njs_int_t njs_parser_import(njs_parser_t *parser,
480
    njs_lexer_token_t *token, njs_queue_link_t *current);
481
static njs_int_t njs_parser_export_sink(njs_parser_t *parser);
482
483
static njs_parser_node_t *njs_parser_return_set(njs_parser_t *parser,
484
    njs_parser_node_t *expr);
485
static njs_parser_node_t *njs_parser_variable_node(njs_parser_t *parser,
486
    uintptr_t atom_id, njs_variable_type_t type, njs_variable_t  **retvar);
487
488
static njs_parser_node_t *njs_parser_reference(njs_parser_t *parser,
489
    njs_lexer_token_t *token);
490
491
static njs_parser_node_t *njs_parser_argument(njs_parser_t *parser,
492
    njs_parser_node_t *expr, njs_index_t index);
493
494
static njs_int_t njs_parser_object_property(njs_parser_t *parser,
495
    njs_parser_node_t *parent, njs_parser_node_t *property,
496
    njs_parser_node_t *value, njs_bool_t proto_init);
497
static njs_int_t njs_parser_property_accessor(njs_parser_t *parser,
498
    njs_parser_node_t *parent, njs_parser_node_t *property,
499
    njs_parser_node_t *value, njs_token_type_t accessor);
500
static njs_int_t njs_parser_array_item(njs_parser_t *parser,
501
    njs_parser_node_t *array, njs_parser_node_t *value);
502
static njs_int_t njs_parser_template_string(njs_parser_t *parser,
503
    njs_lexer_token_t *token);
504
static njs_token_type_t njs_parser_escape_string_create(njs_parser_t *parser,
505
    njs_lexer_token_t *token, njs_value_t *value);
506
static njs_int_t njs_parser_escape_string_calc_length(njs_parser_t *parser,
507
    njs_lexer_token_t *token, size_t *out_size, size_t *out_length);
508
509
static void njs_parser_serialize_tree(njs_chb_t *chain,
510
    njs_parser_node_t *node, njs_int_t *ret, size_t indent);
511
static njs_int_t njs_parser_serialize_node(njs_chb_t *chain,
512
    njs_parser_node_t *node);
513
514
515
#define njs_parser_chain_top(parser)                                          \
516
634k
    ((parser)->scope->top)
517
518
519
#define njs_parser_chain_top_set(parser, node)                                \
520
2.16M
    (parser)->scope->top = node
521
522
523
njs_inline njs_int_t
524
njs_parser_not_supported(njs_parser_t *parser, njs_lexer_token_t *token)
525
8.35k
{
526
8.35k
    if (token->type != NJS_TOKEN_END) {
527
8.35k
        njs_parser_syntax_error(parser, "Token \"%V\" not supported "
528
8.35k
                                "in this version", &token->text);
529
8.35k
    } else {
530
0
        njs_parser_syntax_error(parser, "Not supported in this version");
531
0
    }
532
533
8.35k
    return NJS_DONE;
534
8.35k
}
535
536
537
njs_inline njs_int_t
538
njs_parser_reject(njs_parser_t *parser)
539
28.2k
{
540
28.2k
    njs_queue_link_t          *link;
541
28.2k
    njs_parser_stack_entry_t  *entry;
542
543
737k
    while (!njs_queue_is_empty(&parser->stack)) {
544
737k
        entry = njs_queue_link_data(njs_queue_first(&parser->stack),
545
737k
                                    njs_parser_stack_entry_t, link);
546
547
737k
        link = njs_queue_first(&parser->stack);
548
737k
        njs_queue_remove(link);
549
550
737k
        if (!entry->optional) {
551
28.2k
            njs_parser_next(parser, entry->state);
552
28.2k
            parser->target = entry->node;
553
554
28.2k
            return NJS_DECLINED;
555
28.2k
        }
556
737k
    }
557
558
0
    return njs_parser_failed(parser);
559
28.2k
}
560
561
562
njs_int_t
563
njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope,
564
    njs_str_t *file, u_char *start, u_char *end)
565
263k
{
566
263k
    njs_lexer_t  *lexer;
567
568
263k
    njs_memzero(parser, sizeof(njs_parser_t));
569
570
263k
    parser->scope = scope;
571
572
263k
    lexer = &parser->lexer0;
573
263k
    parser->lexer = lexer;
574
575
263k
    parser->use_lhs = 0;
576
577
263k
    return njs_lexer_init(vm, lexer, file, start, end);
578
263k
}
579
580
581
njs_int_t
582
njs_parser(njs_vm_t *vm, njs_parser_t *parser)
583
263k
{
584
263k
    njs_int_t          ret;
585
263k
    njs_lexer_token_t  *token;
586
587
263k
    parser->vm = vm;
588
589
263k
    njs_set_invalid(&vm->exception);
590
591
263k
    if (parser->scope == NULL) {
592
263k
        ret = njs_parser_scope_begin(parser,
593
263k
                                     parser->module ? NJS_SCOPE_FUNCTION
594
263k
                                                    : NJS_SCOPE_GLOBAL, 1);
595
263k
        if (njs_slow_path(ret != NJS_OK)) {
596
0
            return NJS_ERROR;
597
0
        }
598
599
263k
    } else {
600
0
        parser->scope->top = NULL;
601
0
        parser->node = NULL;
602
0
        parser->ret = NJS_OK;
603
0
    }
604
605
263k
    njs_queue_init(&parser->stack);
606
607
263k
    parser->target = NULL;
608
263k
    njs_parser_next(parser, njs_parser_statement_list);
609
610
263k
    ret = njs_parser_after(parser, njs_queue_first(&parser->stack),
611
263k
                           NULL, 0, njs_parser_check_error_state);
612
263k
    if (ret != NJS_OK) {
613
0
        return ret;
614
0
    }
615
616
169M
    do {
617
169M
        token = njs_lexer_token(parser->lexer, 0);
618
169M
        if (njs_slow_path(token == NULL)) {
619
0
            return NJS_ERROR;
620
0
        }
621
622
169M
        parser->ret = parser->state(parser, token,
623
169M
                                    njs_queue_first(&parser->stack));
624
625
169M
    } while (parser->ret != NJS_DONE && parser->ret != NJS_ERROR);
626
627
263k
    if (parser->ret != NJS_DONE) {
628
4.06k
        return NJS_ERROR;
629
4.06k
    }
630
631
258k
    if (njs_is_error(&vm->exception)) {
632
120k
        return NJS_ERROR;
633
120k
    }
634
635
138k
    if (parser->node == NULL) {
636
        /* Empty string, just semicolons or variables declarations. */
637
638
1
        parser->node = njs_parser_node_new(parser, 0);
639
1
        if (njs_slow_path(parser->node == NULL)) {
640
0
            return NJS_ERROR;
641
0
        }
642
1
    }
643
644
138k
    if (parser->module) {
645
0
        ret = njs_parser_export_sink(parser);
646
0
        if (ret != NJS_OK) {
647
0
            return NJS_ERROR;
648
0
        }
649
650
138k
    } else {
651
138k
        parser->node->token_type = NJS_TOKEN_END;
652
138k
        parser->node->token_line = parser->lexer->line;
653
654
138k
        njs_parser_chain_top_set(parser, parser->node);
655
138k
    }
656
657
138k
    return NJS_OK;
658
138k
}
659
660
661
static njs_int_t
662
njs_parser_check_error_state(njs_parser_t *parser, njs_lexer_token_t *token,
663
    njs_queue_link_t *current)
664
158
{
665
158
    return njs_parser_failed(parser);
666
158
}
667
668
669
njs_int_t
670
njs_parser_failed_state(njs_parser_t *parser, njs_lexer_token_t *token,
671
    njs_queue_link_t *current)
672
92.1k
{
673
92.1k
    if (token->type != NJS_TOKEN_END) {
674
90.9k
        njs_parser_syntax_error(parser, "Unexpected token \"%V\"",
675
90.9k
                                &token->text);
676
90.9k
    } else {
677
1.20k
        njs_parser_syntax_error(parser, "Unexpected end of input");
678
1.20k
    }
679
680
92.1k
    return NJS_DONE;
681
92.1k
}
682
683
684
static njs_int_t
685
njs_parser_scope_begin(njs_parser_t *parser, njs_scope_t type,
686
    njs_bool_t init_this)
687
1.20M
{
688
1.20M
    njs_variable_t      *var;
689
1.20M
    njs_parser_scope_t  *scope, *parent;
690
691
1.20M
    scope = njs_mp_zalloc(parser->vm->mem_pool, sizeof(njs_parser_scope_t));
692
1.20M
    if (njs_slow_path(scope == NULL)) {
693
0
        return NJS_ERROR;
694
0
    }
695
696
1.20M
    scope->type = type;
697
698
1.20M
    njs_rbtree_init(&scope->variables, njs_parser_scope_rbtree_compare);
699
1.20M
    njs_rbtree_init(&scope->labels, njs_parser_scope_rbtree_compare);
700
1.20M
    njs_rbtree_init(&scope->references, njs_parser_scope_rbtree_compare);
701
702
1.20M
    parent = parser->scope;
703
1.20M
    scope->parent = parent;
704
1.20M
    parser->scope = scope;
705
706
1.20M
    if (type == NJS_SCOPE_FUNCTION || type == NJS_SCOPE_GLOBAL) {
707
909k
        if (init_this) {
708
            /* Add this as first variable. */
709
538k
            var = njs_variable_add(parser, scope, NJS_ATOM_STRING_this,
710
538k
                                   NJS_VARIABLE_VAR);
711
538k
            if (njs_slow_path(var == NULL)) {
712
0
                return NJS_ERROR;
713
0
            }
714
715
538k
            var->index = njs_scope_index(type, 0, NJS_LEVEL_LOCAL,
716
538k
                                         NJS_VARIABLE_VAR);
717
538k
        }
718
909k
    }
719
720
1.20M
    scope->items = 1;
721
722
1.20M
    return NJS_OK;
723
1.20M
}
724
725
726
static void
727
njs_parser_scope_end(njs_parser_t *parser)
728
698k
{
729
698k
    njs_parser_scope_t  *scope, *parent;
730
731
698k
    scope = parser->scope;
732
733
698k
    parent = scope->parent;
734
698k
    parser->scope = parent;
735
698k
}
736
737
738
intptr_t
739
njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1,
740
    njs_rbtree_node_t *node2)
741
26.9M
{
742
26.9M
    njs_variable_node_t  *lex_node1, *lex_node2;
743
744
26.9M
    lex_node1 = (njs_variable_node_t *) node1;
745
26.9M
    lex_node2 = (njs_variable_node_t *) node2;
746
747
26.9M
    if (lex_node1->key < lex_node2->key) {
748
3.44M
        return -1;
749
3.44M
    }
750
751
23.4M
    if (lex_node1->key > lex_node2->key) {
752
21.7M
        return 1;
753
21.7M
    }
754
755
1.77M
    return 0;
756
23.4M
}
757
758
759
static njs_int_t
760
njs_parser_generator_expression(njs_parser_t *parser, njs_lexer_token_t *token,
761
    njs_queue_link_t *current)
762
195
{
763
195
    return njs_parser_not_supported(parser, token);
764
195
}
765
766
767
static njs_int_t
768
njs_parser_class_expression(njs_parser_t *parser, njs_lexer_token_t *token,
769
    njs_queue_link_t *current)
770
156
{
771
156
    return njs_parser_not_supported(parser, token);
772
156
}
773
774
775
static njs_int_t
776
njs_parser_async_generator_expression(njs_parser_t *parser,
777
    njs_lexer_token_t *token, njs_queue_link_t *current)
778
670
{
779
670
    return njs_parser_not_supported(parser, token);
780
670
}
781
782
783
static njs_int_t
784
njs_parser_generator_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
785
    njs_queue_link_t *current)
786
0
{
787
0
    return njs_parser_not_supported(parser, token);
788
0
}
789
790
791
static njs_int_t
792
njs_parser_class_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
793
    njs_queue_link_t *current)
794
168
{
795
168
    return njs_parser_not_supported(parser, token);
796
168
}
797
798
799
static njs_int_t
800
njs_parser_function_or_generator_handler(njs_parser_t *parser,
801
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t is_async)
802
8.47k
{
803
8.47k
    njs_parser_node_t  *node, *cur;
804
805
8.47k
    cur = parser->node;
806
807
8.47k
    if (token->type == NJS_TOKEN_MULTIPLICATION) {
808
0
        njs_lexer_consume_token(parser->lexer, 1);
809
0
        njs_parser_next(parser, njs_parser_generator_declaration);
810
811
8.47k
    } else {
812
8.47k
        if (is_async) {
813
2.70k
            node = njs_parser_node_new(parser,
814
2.70k
                                       NJS_TOKEN_ASYNC_FUNCTION_DECLARATION);
815
5.77k
        } else {
816
5.77k
            node = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_DECLARATION);
817
5.77k
        }
818
819
8.47k
        if (node == NULL) {
820
0
            return NJS_ERROR;
821
0
        }
822
823
8.47k
        node->token_line = token->line;
824
8.47k
        parser->node = node;
825
826
8.47k
        njs_lexer_consume_token(parser->lexer, 1);
827
8.47k
        njs_parser_next(parser, njs_parser_function_declaration);
828
8.47k
    }
829
830
8.47k
    return njs_parser_after(parser, current, cur, 1,
831
8.47k
                            njs_parser_statement_after);
832
8.47k
}
833
834
835
static njs_int_t
836
njs_parser_function_or_generator(njs_parser_t *parser,
837
    njs_lexer_token_t *token, njs_queue_link_t *current)
838
2.08M
{
839
2.08M
    if (token->type != NJS_TOKEN_FUNCTION) {
840
2.07M
        return NJS_DECLINED;
841
2.07M
    }
842
843
5.77k
    return njs_parser_function_or_generator_handler(parser, token, current, 0);
844
2.08M
}
845
846
847
static njs_int_t
848
njs_parser_async_function_or_generator(njs_parser_t *parser,
849
    njs_lexer_token_t *token, njs_queue_link_t *current)
850
2.07M
{
851
2.07M
    if (token->type != NJS_TOKEN_ASYNC) {
852
2.07M
        return NJS_DECLINED;
853
2.07M
    }
854
855
4.38k
    token = njs_lexer_peek_token(parser->lexer, token, 1);
856
4.38k
    if (token == NULL) {
857
0
        return NJS_ERROR;
858
0
    }
859
860
4.38k
    if (token->type != NJS_TOKEN_FUNCTION) {
861
1.68k
        return NJS_DECLINED;
862
1.68k
    }
863
864
2.70k
    njs_lexer_consume_token(parser->lexer, 1);
865
866
2.70k
    return njs_parser_function_or_generator_handler(parser, token, current, 1);
867
4.38k
}
868
869
870
njs_inline njs_int_t
871
njs_parser_expect_semicolon(njs_parser_t *parser, njs_lexer_token_t *token)
872
1.36M
{
873
1.36M
    if (token->type != NJS_TOKEN_SEMICOLON) {
874
1.18M
        if (token->type != NJS_TOKEN_END
875
1.04M
            && token->type != NJS_TOKEN_CLOSE_BRACE
876
832k
            && parser->lexer->prev_type != NJS_TOKEN_LINE_END)
877
5.91k
        {
878
5.91k
            return NJS_DECLINED;
879
5.91k
        }
880
881
1.17M
        return NJS_OK;
882
1.18M
    }
883
884
183k
    njs_lexer_consume_token(parser->lexer, 1);
885
886
183k
    return NJS_OK;
887
1.36M
}
888
889
890
static njs_int_t
891
njs_parser_semicolon(njs_parser_t *parser, njs_lexer_token_t *token,
892
    njs_queue_link_t *current)
893
45.3k
{
894
45.3k
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
895
809
        return njs_parser_failed(parser);
896
809
    }
897
898
44.5k
    return njs_parser_stack_pop(parser);
899
45.3k
}
900
901
902
static njs_int_t
903
njs_parser_close_bracked(njs_parser_t *parser, njs_lexer_token_t *token,
904
    njs_queue_link_t *current)
905
0
{
906
0
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
907
0
        return njs_parser_failed(parser);
908
0
    }
909
910
0
    njs_lexer_consume_token(parser->lexer, 1);
911
912
0
    return njs_parser_stack_pop(parser);
913
0
}
914
915
916
static njs_int_t
917
njs_parser_close_parenthesis(njs_parser_t *parser, njs_lexer_token_t *token,
918
    njs_queue_link_t *current)
919
185k
{
920
185k
    if (parser->ret != NJS_OK) {
921
6.18k
        return njs_parser_failed(parser);
922
6.18k
    }
923
924
178k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
925
1.87k
        return njs_parser_failed(parser);
926
1.87k
    }
927
928
177k
    njs_lexer_consume_token(parser->lexer, 1);
929
930
177k
    return njs_parser_stack_pop(parser);
931
178k
}
932
933
934
static njs_int_t
935
njs_parser_expression_parenthesis(njs_parser_t *parser,
936
    njs_lexer_token_t *token, njs_queue_link_t *current)
937
33.3k
{
938
33.3k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
939
204
        return njs_parser_failed(parser);
940
204
    }
941
942
33.1k
    njs_lexer_consume_token(parser->lexer, 1);
943
944
33.1k
    parser->node = NULL;
945
946
33.1k
    njs_parser_next(parser, njs_parser_expression);
947
948
33.1k
    return njs_parser_after(parser, current, NULL, 0,
949
33.3k
                            njs_parser_close_parenthesis);
950
33.3k
}
951
952
953
static njs_int_t
954
njs_parser_iteration_statement_for_end(njs_parser_t *parser,
955
    njs_lexer_token_t *token, njs_queue_link_t *current)
956
45.0k
{
957
45.0k
    parser->node->token_line = (uint32_t) (uintptr_t) parser->target;
958
45.0k
    parser->target = NULL;
959
960
45.0k
    njs_parser_scope_end(parser);
961
962
45.0k
    return njs_parser_stack_pop(parser);
963
45.0k
}
964
965
966
/*
967
 * 12.2 Primary Expression.
968
 */
969
static njs_int_t
970
njs_parser_primary_expression_test(njs_parser_t *parser,
971
    njs_lexer_token_t *token, njs_queue_link_t *current)
972
4.54M
{
973
4.54M
    njs_int_t          ret;
974
4.54M
    njs_lexer_token_t  *next;
975
4.54M
    njs_parser_node_t  *node;
976
977
4.54M
    switch (token->type) {
978
    /* IdentifierReference */
979
5.41k
    case NJS_TOKEN_THIS:
980
6.56k
    case NJS_TOKEN_NULL:
981
2.47M
    case NJS_TOKEN_NAME:
982
2.47M
    case NJS_TOKEN_YIELD:
983
2.47M
    case NJS_TOKEN_AWAIT:
984
2.47M
        goto reference;
985
986
722
    case NJS_TOKEN_TRUE:
987
722
        node = njs_parser_node_new(parser, token->type);
988
722
        if (node == NULL) {
989
0
            return NJS_ERROR;
990
0
        }
991
992
722
        node->u.value = njs_value_true;
993
722
        node->token_line = token->line;
994
995
722
        parser->node = node;
996
722
        goto done;
997
998
3.21k
    case NJS_TOKEN_FALSE:
999
3.21k
        node = njs_parser_node_new(parser, token->type);
1000
3.21k
        if (node == NULL) {
1001
0
            return NJS_ERROR;
1002
0
        }
1003
1004
3.21k
        node->u.value = njs_value_false;
1005
3.21k
        node->token_line = token->line;
1006
1007
3.21k
        parser->node = node;
1008
3.21k
        goto done;
1009
1010
1.16M
    case NJS_TOKEN_NUMBER:
1011
1.16M
        node = njs_parser_node_new(parser, NJS_TOKEN_NUMBER);
1012
1.16M
        if (node == NULL) {
1013
0
            return NJS_ERROR;
1014
0
        }
1015
1016
1.16M
        njs_set_number(&node->u.value, token->number);
1017
1018
1.16M
        if (njs_number_is_integer_index(token->number)
1019
1.14M
            && token->number < 0x80000000)
1020
1.14M
        {
1021
1.14M
            node->u.value.atom_id = njs_number_atom((uint32_t) token->number);
1022
1.14M
        }
1023
1024
1.16M
        node->token_line = token->line;
1025
1026
1.16M
        parser->node = node;
1027
1.16M
        goto done;
1028
1029
6.55k
    case NJS_TOKEN_STRING:
1030
6.55k
        node = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1031
6.55k
        if (node == NULL) {
1032
0
            return NJS_ERROR;
1033
0
        }
1034
1035
6.55k
        node->token_line = token->line;
1036
1037
6.55k
        ret = njs_parser_string_create(parser->vm, token, &node->u.value);
1038
6.55k
        if (ret != NJS_OK) {
1039
0
            return NJS_ERROR;
1040
0
        }
1041
1042
6.55k
        parser->node = node;
1043
6.55k
        goto done;
1044
1045
2.00k
    case NJS_TOKEN_ESCAPE_STRING:
1046
        /* Internal optimization. This is not in the specification. */
1047
1048
2.00k
        node = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1049
2.00k
        if (node == NULL) {
1050
0
            return NJS_ERROR;
1051
0
        }
1052
1053
2.00k
        node->token_line = token->line;
1054
1055
2.00k
        ret = njs_parser_escape_string_create(parser, token, &node->u.value);
1056
2.00k
        if (ret != NJS_TOKEN_STRING) {
1057
279
            return NJS_ERROR;
1058
279
        }
1059
1060
1.73k
        parser->node = node;
1061
1.73k
        goto done;
1062
1063
1.11k
    case NJS_TOKEN_UNTERMINATED_STRING:
1064
        /* Internal optimization. This is not in the specification. */
1065
1066
1.11k
        njs_parser_syntax_error(parser, "Unterminated string \"%V\"",
1067
1.11k
                                &token->text);
1068
1.11k
        return NJS_ERROR;
1069
1070
    /* ArrayLiteral */
1071
104k
    case NJS_TOKEN_OPEN_BRACKET:
1072
104k
        node = njs_parser_node_new(parser, NJS_TOKEN_ARRAY);
1073
104k
        if (node == NULL) {
1074
0
            return NJS_ERROR;
1075
0
        }
1076
1077
104k
        node->token_line = token->line;
1078
104k
        parser->node = node;
1079
1080
104k
        njs_parser_next(parser, njs_parser_array_literal);
1081
104k
        break;
1082
1083
    /* ObjectLiteral */
1084
27.4k
    case NJS_TOKEN_OPEN_BRACE:
1085
27.4k
        node = njs_parser_node_new(parser, NJS_TOKEN_OBJECT);
1086
27.4k
        if (node == NULL) {
1087
0
            return NJS_ERROR;
1088
0
        }
1089
1090
27.4k
        node->token_line = token->line;
1091
27.4k
        parser->node = node;
1092
1093
27.4k
        njs_parser_next(parser, njs_parser_object_literal);
1094
27.4k
        break;
1095
1096
    /* FunctionExpression */
1097
257k
    case NJS_TOKEN_FUNCTION:
1098
257k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
1099
257k
        if (token == NULL) {
1100
0
            return NJS_ERROR;
1101
0
        }
1102
1103
        /* GeneratorExpression */
1104
257k
        if (token->type == NJS_TOKEN_MULTIPLICATION) {
1105
195
            njs_parser_next(parser, njs_parser_generator_expression);
1106
1107
257k
        } else {
1108
257k
            node = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_EXPRESSION);
1109
257k
            if (node == NULL) {
1110
0
                return NJS_ERROR;
1111
0
            }
1112
1113
257k
            node->token_line = token->line;
1114
257k
            parser->node = node;
1115
1116
257k
            njs_parser_next(parser, njs_parser_function_expression);
1117
257k
        }
1118
1119
257k
        break;
1120
1121
    /* ClassExpression */
1122
257k
    case NJS_TOKEN_CLASS:
1123
156
        njs_parser_next(parser, njs_parser_class_expression);
1124
156
        return NJS_OK;
1125
1126
    /* AsyncFunctionExpression */
1127
6.78k
    case NJS_TOKEN_ASYNC:
1128
6.78k
        next = njs_lexer_peek_token(parser->lexer, token, 1);
1129
6.78k
        if (next == NULL) {
1130
0
            return NJS_ERROR;
1131
0
        }
1132
1133
6.78k
        if (next->type != NJS_TOKEN_FUNCTION) {
1134
2.95k
            goto reference;
1135
2.95k
        }
1136
1137
3.83k
        njs_lexer_consume_token(parser->lexer, 1);
1138
1139
3.83k
        next = njs_lexer_peek_token(parser->lexer, next, 0);
1140
3.83k
        if (njs_slow_path(next == NULL)) {
1141
0
            return NJS_ERROR;
1142
0
        }
1143
1144
        /* GeneratorExpression */
1145
3.83k
        if (next->type == NJS_TOKEN_MULTIPLICATION) {
1146
670
            njs_parser_next(parser, njs_parser_async_generator_expression);
1147
1148
3.16k
        } else {
1149
3.16k
            node = njs_parser_node_new(parser,
1150
3.16k
                                       NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION);
1151
3.16k
            if (node == NULL) {
1152
0
                return NJS_ERROR;
1153
0
            }
1154
1155
3.16k
            node->token_line = next->line;
1156
3.16k
            parser->node = node;
1157
1158
3.16k
            njs_parser_next(parser, njs_parser_function_expression);
1159
3.16k
        }
1160
1161
3.83k
        break;
1162
1163
    /* RegularExpressionLiteral */
1164
56.3k
    case NJS_TOKEN_DIVISION:
1165
56.4k
    case NJS_TOKEN_DIVISION_ASSIGNMENT:
1166
56.4k
        node = njs_parser_node_new(parser, NJS_TOKEN_REGEXP);
1167
56.4k
        if (node == NULL) {
1168
0
            return NJS_ERROR;
1169
0
        }
1170
1171
56.4k
        node->token_line = token->line;
1172
56.4k
        parser->node = node;
1173
1174
56.4k
        ret = njs_parser_regexp_literal(parser, token, current);
1175
56.4k
        if (ret != NJS_OK) {
1176
3.33k
            return NJS_ERROR;
1177
3.33k
        }
1178
1179
53.1k
        goto done;
1180
1181
    /* TemplateLiteral */
1182
53.1k
    case NJS_TOKEN_GRAVE:
1183
20.1k
        node = njs_parser_node_new(parser, NJS_TOKEN_TEMPLATE_LITERAL);
1184
20.1k
        if (node == NULL) {
1185
0
            return NJS_ERROR;
1186
0
        }
1187
1188
20.1k
        node->token_line = token->line;
1189
20.1k
        parser->node = node;
1190
1191
20.1k
        njs_parser_next(parser, njs_parser_template_literal);
1192
20.1k
        return NJS_OK;
1193
1194
    /* CoverParenthesizedExpressionAndArrowParameterList */
1195
377k
    case NJS_TOKEN_OPEN_PARENTHESIS:
1196
377k
        njs_lexer_consume_token(parser->lexer, 1);
1197
1198
        /* TODO: By specification. */
1199
377k
        (void) njs_parser_cover_parenthesized_expression;
1200
1201
377k
        parser->node = NULL;
1202
1203
377k
        njs_parser_next(parser, njs_parser_expression);
1204
1205
377k
        return njs_parser_after(parser, current, NULL, 0,
1206
20.1k
                                njs_parser_close_parenthesis);
1207
1208
32.2k
    default:
1209
32.2k
        if (njs_lexer_token_is_identifier_reference(token)) {
1210
6.68k
            goto reference;
1211
6.68k
        }
1212
1213
25.5k
        return njs_parser_reject(parser);
1214
4.54M
    }
1215
1216
393k
    njs_lexer_consume_token(parser->lexer, 1);
1217
1218
393k
    return NJS_OK;
1219
1220
2.48M
reference:
1221
1222
2.48M
    node = njs_parser_reference(parser, token);
1223
2.48M
    if (node == NULL) {
1224
130
        return NJS_ERROR;
1225
130
    }
1226
1227
2.48M
    node->u.value.atom_id = token->atom_id;
1228
1229
2.48M
    node->token_line = token->line;
1230
2.48M
    parser->node = node;
1231
1232
3.71M
done:
1233
1234
3.71M
    njs_lexer_consume_token(parser->lexer, 1);
1235
1236
3.71M
    return NJS_DONE;
1237
2.48M
}
1238
1239
1240
static njs_int_t
1241
njs_parser_regexp_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1242
    njs_queue_link_t *current)
1243
56.4k
{
1244
56.4k
    u_char                *p;
1245
56.4k
    njs_str_t             text;
1246
56.4k
    njs_int_t             ret;
1247
56.4k
    njs_lexer_t           *lexer;
1248
56.4k
    njs_value_t           *value, retval;
1249
56.4k
    njs_regex_flags_t     flags;
1250
56.4k
    njs_regexp_pattern_t  *pattern;
1251
1252
56.4k
    value = &parser->node->u.value;
1253
56.4k
    lexer = parser->lexer;
1254
1255
56.4k
    if (token->type == NJS_TOKEN_DIVISION_ASSIGNMENT) {
1256
144
        lexer->start--;
1257
144
    }
1258
1259
1.69M
    for (p = lexer->start; p < lexer->end; p++) {
1260
1261
1.69M
        switch (*p) {
1262
227
        case '\n':
1263
369
        case '\r':
1264
369
            goto failed;
1265
1266
13.7k
        case '[':
1267
121k
            while (1) {
1268
121k
                if (++p >= lexer->end) {
1269
3
                    goto failed;
1270
3
                }
1271
1272
121k
                if (*p == ']') {
1273
12.6k
                    break;
1274
12.6k
                }
1275
1276
109k
                switch (*p) {
1277
252
                case '\n':
1278
581
                case '\r':
1279
581
                    goto failed;
1280
1281
1.44k
                case '\\':
1282
1.44k
                    if (++p >= lexer->end || *p == '\n' || *p == '\r') {
1283
529
                        goto failed;
1284
529
                    }
1285
1286
915
                    break;
1287
109k
                }
1288
109k
            }
1289
1290
12.6k
            break;
1291
1292
12.6k
        case '\\':
1293
9.36k
            if (++p >= lexer->end || *p == '\n' || *p == '\r') {
1294
677
                goto failed;
1295
677
            }
1296
1297
8.68k
            break;
1298
1299
54.2k
        case '/':
1300
54.2k
            text.start = lexer->start;
1301
54.2k
            text.length = p - text.start;
1302
54.2k
            p++;
1303
54.2k
            lexer->start = p;
1304
1305
54.2k
            flags = njs_regexp_flags(&p, lexer->end);
1306
1307
54.2k
            if (njs_slow_path(flags < 0)) {
1308
839
                njs_parser_syntax_error(parser, "Invalid RegExp flags \"%*s\"",
1309
839
                                        p - lexer->start, lexer->start);
1310
1311
839
                return NJS_ERROR;
1312
839
            }
1313
1314
53.4k
            lexer->start = p;
1315
1316
53.4k
            pattern = njs_regexp_pattern_create(parser->vm, text.start,
1317
53.4k
                                                text.length, flags);
1318
1319
53.4k
            if (njs_slow_path(pattern == NULL)) {
1320
298
                retval = njs_vm_exception(parser->vm);
1321
298
                ret = njs_value_property(parser->vm, &retval,
1322
298
                                         NJS_ATOM_STRING_message, &retval);
1323
298
                if (njs_slow_path(ret != NJS_OK)) {
1324
0
                    return NJS_ERROR;
1325
0
                }
1326
1327
298
                njs_string_get(parser->vm, &retval, &text);
1328
1329
298
                njs_parser_syntax_error(parser, "%V", &text);
1330
1331
298
                return NJS_ERROR;
1332
298
            }
1333
1334
53.1k
            value->data.u.data = pattern;
1335
1336
53.1k
            return NJS_OK;
1337
1.69M
        }
1338
1.69M
    }
1339
1340
2.19k
failed:
1341
1342
2.19k
    njs_parser_syntax_error(parser, "Unterminated RegExp \"%*s\"",
1343
2.19k
                            p - (lexer->start - 1), lexer->start - 1);
1344
2.19k
    return NJS_ERROR;
1345
56.4k
}
1346
1347
1348
static njs_int_t
1349
njs_parser_template_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1350
    njs_queue_link_t *current)
1351
1.01M
{
1352
1.01M
    njs_index_t        index;
1353
1.01M
    njs_parser_node_t  *node, *array, *template, *temp;
1354
1355
1.01M
    temp = njs_parser_node_new(parser, 0);
1356
1.01M
    if (temp == NULL) {
1357
0
        return NJS_ERROR;
1358
0
    }
1359
1360
1.01M
    array = njs_parser_node_new(parser, NJS_TOKEN_ARRAY);
1361
1.01M
    if (array == NULL) {
1362
0
        return NJS_ERROR;
1363
0
    }
1364
1365
1.01M
    array->token_line = token->line;
1366
1367
1.01M
    template = parser->node;
1368
1369
1.01M
    index = njs_scope_temp_index(template->scope);
1370
1.01M
    if (njs_slow_path(index == NJS_INDEX_ERROR)) {
1371
0
        return NJS_ERROR;
1372
0
    }
1373
1374
1.01M
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1375
991k
        node = njs_parser_argument(parser, array, index);
1376
991k
        if (node == NULL) {
1377
0
            return NJS_ERROR;
1378
0
        }
1379
1380
991k
        node->temporary = 1;
1381
1382
991k
        template->right = node;
1383
991k
        temp->right = node;
1384
1385
991k
        index = njs_scope_temp_index(template->scope);
1386
991k
        if (njs_slow_path(index == NJS_INDEX_ERROR)) {
1387
0
            return NJS_ERROR;
1388
0
        }
1389
1390
991k
    } else {
1391
20.1k
        template->left = array;
1392
20.1k
        temp->right = template;
1393
20.1k
    }
1394
1395
1.01M
    temp->temporary = 1;
1396
1.01M
    temp->left = template;
1397
1.01M
    temp->index = index;
1398
1399
1.01M
    parser->target = temp;
1400
1401
1.01M
    token->text.start++;
1402
1.01M
    token->text.length = 0;
1403
1404
1.01M
    njs_parser_next(parser, njs_parser_template_literal_string);
1405
1406
1.01M
    return NJS_OK;
1407
1.01M
}
1408
1409
1410
static njs_int_t
1411
njs_parser_template_literal_string(njs_parser_t *parser,
1412
    njs_lexer_token_t *token, njs_queue_link_t *current)
1413
1.03M
{
1414
1.03M
    njs_int_t          ret, ret_item;
1415
1.03M
    njs_parser_node_t  *template;
1416
1417
1.03M
    template = parser->target->left;
1418
1419
1.03M
    ret = njs_parser_template_string(parser, token);
1420
1.03M
    if (ret == NJS_ERROR) {
1421
2.39k
        njs_parser_syntax_error(parser, "Unterminated template literal");
1422
2.39k
        return NJS_DONE;
1423
2.39k
    }
1424
1425
1.03M
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1426
997k
        ret_item = njs_parser_array_item(parser, template->right->left,
1427
997k
                                         parser->node);
1428
1429
997k
    } else {
1430
33.0k
        ret_item = njs_parser_array_item(parser, template->left, parser->node);
1431
33.0k
    }
1432
1433
1.03M
    if (ret_item != NJS_OK) {
1434
0
        return NJS_ERROR;
1435
0
    }
1436
1437
1.03M
    if (ret == NJS_DONE) {
1438
1.00M
        parser->node = template;
1439
1440
1.00M
        njs_parser_node_free(parser, parser->target);
1441
1.00M
        njs_lexer_consume_token(parser->lexer, 1);
1442
1443
1.00M
        return njs_parser_stack_pop(parser);
1444
1.00M
    }
1445
1446
21.7k
    parser->node = NULL;
1447
1448
21.7k
    njs_parser_next(parser, njs_parser_expression);
1449
1450
21.7k
    njs_lexer_consume_token(parser->lexer, 1);
1451
1452
21.7k
    return njs_parser_after(parser, current, parser->target, 0,
1453
1.03M
                            njs_parser_template_literal_expression);
1454
1.03M
}
1455
1456
1457
static njs_int_t
1458
njs_parser_template_literal_expression(njs_parser_t *parser,
1459
    njs_lexer_token_t *token, njs_queue_link_t *current)
1460
21.7k
{
1461
21.7k
    njs_int_t          ret;
1462
21.7k
    njs_parser_node_t  *template, *node, *parent;
1463
1464
21.7k
    if (parser->ret != NJS_OK) {
1465
216
        return njs_parser_failed(parser);
1466
216
    }
1467
1468
21.5k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
1469
242
        njs_parser_syntax_error(parser, "Missing \"}\" in template expression");
1470
242
        return NJS_DONE;
1471
242
    }
1472
1473
21.2k
    parent = parser->target->right;
1474
21.2k
    template = parser->target->left;
1475
1476
21.2k
    if (template->token_type != NJS_TOKEN_TEMPLATE_LITERAL) {
1477
8.30k
        node = njs_parser_argument(parser, parser->node, parser->target->index);
1478
8.30k
        if (node == NULL) {
1479
0
            return NJS_ERROR;
1480
0
        }
1481
1482
8.30k
        parent->right = node;
1483
8.30k
        parent = node;
1484
1485
8.30k
        parser->target->index = njs_scope_temp_index(node->scope);
1486
8.30k
        if (njs_slow_path(parser->target->index == NJS_INDEX_ERROR)) {
1487
0
            return NJS_ERROR;
1488
0
        }
1489
1490
12.9k
    } else {
1491
12.9k
        ret = njs_parser_array_item(parser, template->left, parser->node);
1492
12.9k
        if (ret != NJS_OK) {
1493
0
            return NJS_ERROR;
1494
0
        }
1495
12.9k
    }
1496
1497
21.2k
    parser->target->right = parent;
1498
1499
21.2k
    parser->node = NULL;
1500
1501
21.2k
    njs_parser_next(parser, njs_parser_template_literal_string);
1502
1503
21.2k
    token->text.length = 0;
1504
21.2k
    token->text.start += 1;
1505
1506
21.2k
    return NJS_OK;
1507
21.2k
}
1508
1509
1510
static njs_int_t
1511
njs_parser_cover_parenthesized_expression(njs_parser_t *parser,
1512
    njs_lexer_token_t *token, njs_queue_link_t *current)
1513
0
{
1514
0
    switch (token->type) {
1515
0
    case NJS_TOKEN_CLOSE_PARENTHESIS:
1516
0
        (void) njs_parser_stack_pop(parser);
1517
0
        break;
1518
1519
0
    case NJS_TOKEN_ELLIPSIS:
1520
0
        njs_parser_next(parser, njs_parser_binding_identifier_pattern);
1521
0
        break;
1522
1523
0
    default:
1524
0
        parser->node = NULL;
1525
1526
0
        njs_parser_next(parser, njs_parser_expression);
1527
1528
0
        return njs_parser_after(parser, current, NULL, 0,
1529
0
                               njs_parser_cover_parenthesized_expression_after);
1530
0
    }
1531
1532
0
    njs_lexer_consume_token(parser->lexer, 1);
1533
1534
0
    return NJS_OK;
1535
0
}
1536
1537
1538
static njs_int_t
1539
njs_parser_binding_identifier_pattern(njs_parser_t *parser,
1540
    njs_lexer_token_t *token, njs_queue_link_t *current)
1541
0
{
1542
    /*
1543
     * BindingIdentifier )
1544
     * BindingPattern )
1545
     */
1546
1547
0
    switch (token->type) {
1548
1549
    /* BindingIdentifier */
1550
0
    case NJS_TOKEN_NAME:
1551
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1552
0
        break;
1553
1554
0
    case NJS_TOKEN_YIELD:
1555
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1556
0
        break;
1557
1558
0
    case NJS_TOKEN_AWAIT:
1559
0
        njs_parser_next(parser, njs_parser_cover_parenthesized_expression_end);
1560
0
        break;
1561
1562
    /* BindingPattern */
1563
0
    case NJS_TOKEN_OPEN_BRACKET:
1564
0
        njs_parser_next(parser, njs_parser_array_binding_pattern);
1565
1566
0
        njs_lexer_consume_token(parser->lexer, 1);
1567
0
        return njs_parser_after(parser, current, NULL, 0,
1568
0
                                njs_parser_cover_parenthesized_expression_end);
1569
1570
0
    case NJS_TOKEN_OPEN_BRACE:
1571
0
        njs_parser_next(parser, njs_parser_object_binding_pattern);
1572
1573
0
        njs_lexer_consume_token(parser->lexer, 1);
1574
0
        return njs_parser_after(parser, current, NULL, 0,
1575
0
                                njs_parser_cover_parenthesized_expression_end);
1576
1577
0
    default:
1578
0
        return NJS_ERROR;
1579
0
    }
1580
1581
0
    njs_lexer_consume_token(parser->lexer, 1);
1582
1583
0
    return NJS_OK;
1584
0
}
1585
1586
1587
static njs_int_t
1588
njs_parser_cover_parenthesized_expression_after(njs_parser_t *parser,
1589
    njs_lexer_token_t *token, njs_queue_link_t *current)
1590
0
{
1591
    /*
1592
     * )
1593
     * ,)
1594
     * , ... BindingIdentifier )
1595
     * , ... BindingPattern )
1596
     */
1597
1598
0
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
1599
0
        goto shift_stack;
1600
0
    }
1601
1602
0
    if (token->type != NJS_TOKEN_COMMA) {
1603
0
        return njs_parser_failed(parser);
1604
0
    }
1605
1606
0
    njs_lexer_consume_token(parser->lexer, 1);
1607
1608
0
    token = njs_lexer_token(parser->lexer, 0);
1609
0
    if (njs_slow_path(token == NULL)) {
1610
0
        return NJS_ERROR;
1611
0
    }
1612
1613
0
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
1614
0
        goto shift_stack;
1615
0
    }
1616
1617
0
    if(token->type != NJS_TOKEN_ELLIPSIS) {
1618
0
        return njs_parser_failed(parser);
1619
0
    }
1620
1621
0
    njs_lexer_consume_token(parser->lexer, 1);
1622
1623
0
    njs_parser_next(parser, njs_parser_binding_identifier_pattern);
1624
1625
0
    return NJS_OK;
1626
1627
0
shift_stack:
1628
1629
0
    njs_lexer_consume_token(parser->lexer, 1);
1630
1631
0
    return njs_parser_stack_pop(parser);
1632
0
}
1633
1634
1635
static njs_int_t
1636
njs_parser_cover_parenthesized_expression_end(njs_parser_t *parser,
1637
    njs_lexer_token_t *token, njs_queue_link_t *current)
1638
0
{
1639
0
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
1640
0
        return njs_parser_failed(parser);
1641
0
    }
1642
1643
0
    njs_lexer_consume_token(parser->lexer, 1);
1644
1645
0
    return njs_parser_stack_pop(parser);
1646
0
}
1647
1648
1649
/*
1650
 * 12.2.5 Array Initializer.
1651
 */
1652
static njs_int_t
1653
njs_parser_array_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1654
    njs_queue_link_t *current)
1655
104k
{
1656
104k
    parser->target = parser->node;
1657
104k
    parser->node = NULL;
1658
1659
104k
    njs_parser_next(parser, njs_parser_array_element_list);
1660
1661
104k
    return NJS_OK;
1662
104k
}
1663
1664
1665
static njs_int_t
1666
njs_parser_array_element_list(njs_parser_t *parser, njs_lexer_token_t *token,
1667
    njs_queue_link_t *current)
1668
1.13M
{
1669
1.13M
    njs_parser_node_t  *array;
1670
1671
1.13M
    array = parser->target;
1672
1673
1.13M
    switch (token->type) {
1674
21.2k
    case NJS_TOKEN_CLOSE_BRACKET:
1675
21.2k
        njs_lexer_consume_token(parser->lexer, 1);
1676
1677
21.2k
        parser->node = array;
1678
1679
21.2k
        return njs_parser_stack_pop(parser);
1680
1681
121k
    case NJS_TOKEN_COMMA:
1682
121k
        njs_lexer_consume_token(parser->lexer, 1);
1683
1684
121k
        array->ctor = 1;
1685
121k
        array->u.length++;
1686
1687
121k
        return NJS_OK;
1688
1689
3.23k
    case NJS_TOKEN_ELLIPSIS:
1690
#if 0
1691
        njs_lexer_consume_token(parser->lexer, 1);
1692
1693
        njs_parser_next(parser, njs_parser_assignment_expression);
1694
1695
        return njs_parser_after(parser, current, array, 0,
1696
                                njs_parser_array_spread_element);
1697
#else
1698
3.23k
        (void) njs_parser_array_spread_element;
1699
3.23k
        return njs_parser_failed(parser);
1700
0
#endif
1701
1702
984k
    default:
1703
984k
        break;
1704
1.13M
    }
1705
1706
984k
    njs_parser_next(parser, njs_parser_assignment_expression);
1707
1708
984k
    return njs_parser_after(parser, current, array, 0, njs_parser_array_after);
1709
1.13M
}
1710
1711
1712
static njs_int_t
1713
njs_parser_array_after(njs_parser_t *parser, njs_lexer_token_t *token,
1714
    njs_queue_link_t *current)
1715
909k
{
1716
909k
    njs_int_t  ret;
1717
1718
909k
    if (parser->ret != NJS_OK) {
1719
4.21k
        return njs_parser_failed(parser);
1720
4.21k
    }
1721
1722
905k
    ret = njs_parser_array_item(parser, parser->target, parser->node);
1723
905k
    if (ret != NJS_OK) {
1724
0
        return NJS_ERROR;
1725
0
    }
1726
1727
905k
    switch (token->type) {
1728
891k
    case NJS_TOKEN_COMMA:
1729
891k
        njs_lexer_consume_token(parser->lexer, 1);
1730
1731
        /* Fall through. */
1732
1733
904k
    case NJS_TOKEN_CLOSE_BRACKET:
1734
904k
        njs_parser_next(parser, njs_parser_array_element_list);
1735
904k
        break;
1736
1737
1.07k
    default:
1738
1.07k
        return njs_parser_failed(parser);
1739
905k
    }
1740
1741
904k
    return NJS_OK;
1742
905k
}
1743
1744
1745
static njs_int_t
1746
njs_parser_array_spread_element(njs_parser_t *parser, njs_lexer_token_t *token,
1747
    njs_queue_link_t *current)
1748
0
{
1749
0
    if (parser->ret != NJS_OK || token->type != NJS_TOKEN_CLOSE_BRACKET) {
1750
0
        return njs_parser_failed(parser);
1751
0
    }
1752
1753
0
    njs_lexer_consume_token(parser->lexer, 1);
1754
1755
0
    parser->node = parser->target;
1756
1757
0
    return njs_parser_stack_pop(parser);
1758
0
}
1759
1760
1761
/*
1762
 * 12.2.6 Object Initializer.
1763
 */
1764
static njs_int_t
1765
njs_parser_object_literal(njs_parser_t *parser, njs_lexer_token_t *token,
1766
    njs_queue_link_t *current)
1767
27.4k
{
1768
27.4k
    njs_parser_node_t *node;
1769
1770
27.4k
    node = njs_parser_node_new(parser, 0);
1771
27.4k
    if (node == NULL) {
1772
0
        return NJS_ERROR;
1773
0
    }
1774
1775
27.4k
    node->left = parser->node;
1776
1777
27.4k
    parser->node = NULL;
1778
27.4k
    parser->target = node;
1779
1780
27.4k
    njs_parser_next(parser, njs_parser_property_definition_list);
1781
1782
27.4k
    return njs_parser_after(parser, current, node, 1,
1783
27.4k
                            njs_parser_object_literal_after);
1784
27.4k
}
1785
1786
1787
static njs_int_t
1788
njs_parser_object_literal_after(njs_parser_t *parser, njs_lexer_token_t *token,
1789
    njs_queue_link_t *current)
1790
13.6k
{
1791
13.6k
    if (token->type == NJS_TOKEN_COMMA) {
1792
0
        njs_lexer_consume_token(parser->lexer, 1);
1793
1794
0
        token = njs_lexer_token(parser->lexer, 1);
1795
0
        if (token == NULL) {
1796
0
            return NJS_ERROR;
1797
0
        }
1798
0
    }
1799
1800
13.6k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
1801
1.27k
        return njs_parser_failed(parser);
1802
1.27k
    }
1803
1804
12.3k
    njs_lexer_consume_token(parser->lexer, 1);
1805
1806
12.3k
    parser->node = parser->target->left;
1807
1808
12.3k
    njs_parser_node_free(parser, parser->target);
1809
12.3k
    parser->target = NULL;
1810
1811
12.3k
    return njs_parser_stack_pop(parser);
1812
13.6k
}
1813
1814
1815
static njs_int_t
1816
njs_parser_property_definition_list(njs_parser_t *parser,
1817
    njs_lexer_token_t *token, njs_queue_link_t *current)
1818
27.4k
{
1819
27.4k
    njs_parser_next(parser, njs_parser_property_definition);
1820
1821
27.4k
    return njs_parser_after(parser, current, parser->target, 1,
1822
27.4k
                            njs_parser_property_definition_list_after);
1823
27.4k
}
1824
1825
1826
static njs_int_t
1827
njs_parser_property_definition_list_after(njs_parser_t *parser,
1828
    njs_lexer_token_t *token, njs_queue_link_t *current)
1829
19.5k
{
1830
19.5k
    if (token->type != NJS_TOKEN_COMMA) {
1831
13.6k
        return njs_parser_stack_pop(parser);
1832
13.6k
    }
1833
1834
5.89k
    njs_lexer_consume_token(parser->lexer, 1);
1835
1836
5.89k
    njs_parser_next(parser, njs_parser_property_definition);
1837
1838
5.89k
    return njs_parser_after(parser, current, parser->target, 1,
1839
19.5k
                            njs_parser_property_definition_list_after);
1840
19.5k
}
1841
1842
1843
njs_inline njs_parser_node_t *
1844
njs_parser_property_name_node(njs_parser_t *parser, njs_lexer_token_t *token)
1845
18.4k
{
1846
18.4k
    njs_int_t          ret;
1847
18.4k
    njs_parser_node_t  *property;
1848
1849
18.4k
    if (token->type == NJS_TOKEN_NUMBER) {
1850
1.84k
        property = njs_parser_node_new(parser, NJS_TOKEN_NUMBER);
1851
1.84k
        if (property != NULL) {
1852
1.84k
             njs_set_number(&property->u.value, token->number);
1853
1.84k
        }
1854
1855
16.6k
    } else if (token->type == NJS_TOKEN_ESCAPE_STRING) {
1856
2.52k
        property = njs_parser_node_new(parser, NJS_TOKEN_STRING);
1857
1858
2.52k
        if (property != NULL) {
1859
2.52k
            ret = njs_parser_escape_string_create(parser, token,
1860
2.52k
                                                  &property->u.value);
1861
2.52k
            if (ret != NJS_TOKEN_STRING) {
1862
1.08k
                return NULL;
1863
1.08k
            }
1864
2.52k
        }
1865
1866
14.1k
    } else {
1867
14.1k
        property = njs_parser_node_string(parser->vm, token, parser);
1868
14.1k
    }
1869
1870
17.3k
    if (property != NULL) {
1871
17.3k
        property->token_line = token->line;
1872
17.3k
    }
1873
1874
17.3k
    return property;
1875
18.4k
}
1876
1877
1878
njs_inline njs_int_t
1879
njs_parser_property_name(njs_parser_t *parser, njs_queue_link_t *current,
1880
    unsigned consume)
1881
8.05k
{
1882
8.05k
    njs_lexer_token_t  *token;
1883
8.05k
    njs_parser_node_t  *property;
1884
1885
8.05k
    if (consume > 1) {
1886
7.43k
        token = njs_lexer_token(parser->lexer, 0);
1887
7.43k
        if (token == NULL) {
1888
0
            return NJS_ERROR;
1889
0
        }
1890
1891
7.43k
        property = njs_parser_property_name_node(parser, token);
1892
7.43k
        if (property == NULL) {
1893
0
            return NJS_ERROR;
1894
0
        }
1895
1896
7.43k
        parser->target->right = property;
1897
7.43k
        parser->target->index = (token->type == NJS_TOKEN_NAME);
1898
7.43k
    }
1899
1900
8.05k
    njs_lexer_consume_token(parser->lexer, consume);
1901
1902
8.05k
    parser->node = NULL;
1903
1904
8.05k
    njs_parser_next(parser, njs_parser_assignment_expression);
1905
1906
8.05k
    return njs_parser_after(parser, current, parser->target, 1,
1907
8.05k
                            njs_parser_property_definition_after);
1908
8.05k
}
1909
1910
1911
static njs_int_t
1912
njs_parser_property_definition_ident(njs_parser_t *parser,
1913
    njs_lexer_token_t *token, njs_parser_node_t *temp)
1914
5.43k
{
1915
5.43k
    temp->right = njs_parser_node_string(parser->vm, token, parser);
1916
5.43k
    if (temp->right == NULL) {
1917
0
        return NJS_ERROR;
1918
0
    }
1919
1920
5.43k
    temp->right->index = NJS_TOKEN_OPEN_BRACKET;
1921
1922
5.43k
    parser->node = njs_parser_reference(parser, token);
1923
5.43k
    if (parser->node == NULL) {
1924
0
        return NJS_ERROR;
1925
0
    }
1926
1927
5.43k
    njs_lexer_consume_token(parser->lexer, 1);
1928
1929
5.43k
    token = njs_lexer_token(parser->lexer, 0);
1930
5.43k
    if (token == NULL) {
1931
0
        return NJS_ERROR;
1932
0
    }
1933
1934
    /* CoverInitializedName */
1935
5.43k
    if (token->type == NJS_TOKEN_ASSIGNMENT) {
1936
159
        return njs_parser_not_supported(parser, token);
1937
159
    }
1938
1939
5.27k
    njs_parser_next(parser, njs_parser_property_definition_after);
1940
1941
5.27k
    return NJS_OK;
1942
5.43k
}
1943
1944
1945
static njs_int_t
1946
njs_parser_property_definition(njs_parser_t *parser, njs_lexer_token_t *token,
1947
    njs_queue_link_t *current)
1948
33.3k
{
1949
33.3k
    njs_str_t          *name;
1950
33.3k
    njs_token_type_t   accessor;
1951
33.3k
    njs_lexer_token_t  *next;
1952
33.3k
    njs_parser_node_t  *temp, *property;
1953
1954
33.3k
    temp = parser->target;
1955
1956
33.3k
    switch (token->type) {
1957
5.06k
    case NJS_TOKEN_CLOSE_BRACE:
1958
5.06k
        return njs_parser_stack_pop(parser);
1959
1960
    /* PropertyName */
1961
3.41k
    case NJS_TOKEN_STRING:
1962
4.80k
    case NJS_TOKEN_ESCAPE_STRING:
1963
6.65k
    case NJS_TOKEN_NUMBER:
1964
6.65k
        next = njs_lexer_peek_token(parser->lexer, token, 0);
1965
6.65k
        if (next == NULL) {
1966
0
            return NJS_ERROR;
1967
0
        }
1968
1969
6.65k
        if (next->type == NJS_TOKEN_COLON) {
1970
4.54k
            return njs_parser_property_name(parser, current, 2);
1971
1972
4.54k
        } else if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
1973
1.95k
            goto method_definition;
1974
1.95k
        }
1975
1976
157
        njs_lexer_consume_token(parser->lexer, 1);
1977
1978
157
        return njs_parser_failed(parser);
1979
1980
    /* ComputedPropertyName */
1981
1.01k
    case NJS_TOKEN_OPEN_BRACKET:
1982
1.01k
        njs_lexer_consume_token(parser->lexer, 1);
1983
1984
1.01k
        njs_parser_next(parser, njs_parser_assignment_expression);
1985
1986
1.01k
        return njs_parser_after(parser, current, temp, 1,
1987
6.65k
                                njs_parser_computed_property_name_after);
1988
1989
0
    case NJS_TOKEN_ELLIPSIS:
1990
0
        return njs_parser_not_supported(parser, token);
1991
1992
1.78k
    case NJS_TOKEN_ASYNC:
1993
1.78k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
1994
1.78k
        if (token == NULL) {
1995
0
            return NJS_ERROR;
1996
0
        }
1997
1998
1.78k
        if (token->type == NJS_TOKEN_OPEN_BRACKET) {
1999
560
            njs_lexer_consume_token(parser->lexer, 2);
2000
2001
560
            njs_parser_next(parser, njs_parser_assignment_expression);
2002
2003
560
            return njs_parser_after(parser, current, temp, 1,
2004
560
                                    njs_parser_computed_property_async_after);
2005
560
        }
2006
2007
1.22k
        if (token->type == NJS_TOKEN_COLON) {
2008
1.06k
            return njs_parser_property_name(parser, current, 2);
2009
1.06k
        }
2010
2011
152
        if (!njs_lexer_token_is_identifier_name(token)) {
2012
0
            return njs_parser_failed(parser);
2013
0
        }
2014
2015
152
        next = njs_lexer_peek_token(parser->lexer, token, 0);
2016
152
        if (next == NULL) {
2017
0
            return NJS_ERROR;
2018
0
        }
2019
2020
152
        if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2021
151
            goto method_definition;
2022
151
        }
2023
2024
1
        njs_lexer_consume_token(parser->lexer, 1);
2025
2026
1
        return njs_parser_failed(parser);
2027
2028
18.8k
    default:
2029
18.8k
        if (!njs_lexer_token_is_identifier_name(token)) {
2030
1.61k
            return njs_parser_reject(parser);
2031
1.61k
        }
2032
2033
17.2k
        next = njs_lexer_peek_token(parser->lexer, token, 0);
2034
17.2k
        if (next == NULL) {
2035
0
            return NJS_ERROR;
2036
0
        }
2037
2038
        /* PropertyName */
2039
17.2k
        if (next->type == NJS_TOKEN_COLON) {
2040
1.82k
            return njs_parser_property_name(parser, current, 2);
2041
2042
        /* MethodDefinition */
2043
15.4k
        } else if (next->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2044
2.20k
            goto method_definition;
2045
2046
13.2k
        } else if (njs_lexer_token_is_reserved(token)) {
2047
552
            njs_lexer_consume_token(parser->lexer, 1);
2048
2049
552
            return njs_parser_failed(parser);
2050
552
        }
2051
2052
12.6k
        name = &token->text;
2053
2054
12.6k
        if (name->length == 3 && (memcmp(name->start, "get", 3) == 0
2055
4.51k
                                  || memcmp(name->start, "set", 3) == 0))
2056
7.38k
        {
2057
7.38k
            accessor = (name->start[0] == 'g') ? NJS_TOKEN_PROPERTY_GETTER
2058
7.38k
                                               : NJS_TOKEN_PROPERTY_SETTER;
2059
2060
7.38k
            temp->right = (njs_parser_node_t *) (uintptr_t) accessor;
2061
2062
7.38k
            njs_parser_next(parser, njs_parser_get_set);
2063
2064
7.38k
            return NJS_OK;
2065
7.38k
        }
2066
2067
5.27k
        return njs_parser_property_definition_ident(parser, token, temp);
2068
33.3k
    }
2069
2070
4.31k
method_definition:
2071
2072
4.31k
    property = njs_parser_property_name_node(parser, token);
2073
4.31k
    if (property == NULL) {
2074
143
        return NJS_ERROR;
2075
143
    }
2076
2077
4.17k
    temp->right = property;
2078
4.17k
    temp->right->index = NJS_TOKEN_OPEN_BRACKET;
2079
2080
4.17k
    njs_parser_next(parser, njs_parser_method_definition);
2081
2082
4.17k
    return njs_parser_after(parser, current, temp, 1,
2083
4.31k
                            njs_parser_property_definition_after);
2084
4.31k
}
2085
2086
2087
static njs_int_t
2088
njs_parser_property_definition_after(njs_parser_t *parser,
2089
    njs_lexer_token_t *token, njs_queue_link_t *current)
2090
13.7k
{
2091
13.7k
    njs_int_t          ret;
2092
13.7k
    njs_str_t          name;
2093
13.7k
    njs_bool_t         proto_init;
2094
13.7k
    njs_parser_node_t  *property, *temp;
2095
2096
13.7k
    static const njs_str_t  proto_string = njs_str("__proto__");
2097
2098
13.7k
    temp = parser->target;
2099
13.7k
    property = temp->right;
2100
2101
13.7k
    proto_init = 0;
2102
2103
13.7k
    if (property->index != NJS_TOKEN_OPEN_BRACKET
2104
6.10k
        && njs_is_string(&property->u.value))
2105
6.09k
    {
2106
6.09k
        njs_string_get(parser->vm, &property->u.value, &name);
2107
2108
6.09k
        if (njs_slow_path(njs_strstr_eq(&name, &proto_string))) {
2109
306
            if (temp->token_type == NJS_TOKEN_PROTO_INIT) {
2110
0
                njs_parser_syntax_error(parser,
2111
0
                                   "Duplicate __proto__ fields are not allowed "
2112
0
                                   "in object literals");
2113
0
                return NJS_ERROR;
2114
0
            }
2115
2116
306
            temp->token_type = NJS_TOKEN_PROTO_INIT;
2117
306
            proto_init = 1;
2118
306
        }
2119
6.09k
    }
2120
2121
13.7k
    if (property->index != 0) {
2122
7.65k
        property->index = 0;
2123
7.65k
    }
2124
2125
13.7k
    ret = njs_parser_object_property(parser, temp->left, property,
2126
13.7k
                                     parser->node, proto_init);
2127
13.7k
    if (ret != NJS_OK) {
2128
0
        return NJS_ERROR;
2129
0
    }
2130
2131
13.7k
    temp->right = NULL;
2132
2133
13.7k
    return njs_parser_stack_pop(parser);
2134
13.7k
}
2135
2136
2137
static njs_int_t
2138
njs_parser_computed_property_name_after(njs_parser_t *parser,
2139
    njs_lexer_token_t *token, njs_queue_link_t *current)
2140
1.01k
{
2141
1.01k
    return njs_parser_computed_property_name_handler(parser, token, current, 0);
2142
1.01k
}
2143
2144
2145
static njs_int_t
2146
njs_parser_computed_property_async_after(njs_parser_t *parser,
2147
    njs_lexer_token_t *token, njs_queue_link_t *current)
2148
560
{
2149
560
    return njs_parser_computed_property_name_handler(parser, token, current, 1);
2150
560
}
2151
2152
2153
static njs_int_t
2154
njs_parser_computed_property_name_handler(njs_parser_t *parser,
2155
    njs_lexer_token_t *token, njs_queue_link_t *current, njs_bool_t async)
2156
1.57k
{
2157
1.57k
    njs_token_type_t   type;
2158
1.57k
    njs_parser_node_t  *expr, *target;
2159
2160
1.57k
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
2161
164
        return njs_parser_failed(parser);
2162
164
    }
2163
2164
1.41k
    njs_lexer_consume_token(parser->lexer, 1);
2165
2166
1.41k
    token = njs_lexer_token(parser->lexer, 0);
2167
1.41k
    if (token == NULL) {
2168
0
        return NJS_ERROR;
2169
0
    }
2170
2171
1.41k
    target = parser->target;
2172
2173
    /*
2174
     * For further identification.
2175
     * In njs_parser_property_definition_after() index will be reset to zero.
2176
     */
2177
1.41k
    parser->node->index = NJS_TOKEN_OPEN_BRACKET;
2178
2179
1.41k
    target->right = parser->node;
2180
2181
1.41k
    if (!async && token->type == NJS_TOKEN_COLON) {
2182
616
        return njs_parser_property_name(parser, current, 1);
2183
2184
    /* MethodDefinition */
2185
796
    } else if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
2186
664
        type = (async) ? NJS_TOKEN_ASYNC_FUNCTION : NJS_TOKEN_FUNCTION;
2187
2188
664
        expr = njs_parser_node_new(parser, type);
2189
664
        if (expr == NULL) {
2190
0
            return NJS_ERROR;
2191
0
        }
2192
2193
664
        expr->token_line = token->line;
2194
2195
664
        parser->node = expr;
2196
2197
664
        njs_lexer_consume_token(parser->lexer, 1);
2198
664
        njs_parser_next(parser, njs_parser_function_lambda);
2199
2200
664
        return njs_parser_after(parser, current, parser->target, 1,
2201
664
                                njs_parser_property_definition_after);
2202
664
    }
2203
2204
132
    return njs_parser_failed(parser);
2205
1.41k
}
2206
2207
2208
static njs_int_t
2209
njs_parser_initializer(njs_parser_t *parser, njs_lexer_token_t *token,
2210
    njs_queue_link_t *current)
2211
63.7k
{
2212
63.7k
    njs_parser_node_t  *node;
2213
2214
63.7k
    if (token->type != NJS_TOKEN_ASSIGNMENT) {
2215
0
        return njs_parser_failed(parser);
2216
0
    }
2217
2218
63.7k
    njs_lexer_consume_token(parser->lexer, 1);
2219
2220
63.7k
    node = parser->node;
2221
2222
63.7k
    parser->node = NULL;
2223
2224
63.7k
    njs_parser_next(parser, njs_parser_assignment_expression);
2225
2226
63.7k
    return njs_parser_after(parser, current, node, 1,
2227
63.7k
                            njs_parser_initializer_after);
2228
63.7k
}
2229
2230
2231
static njs_int_t
2232
njs_parser_initializer_after(njs_parser_t *parser, njs_lexer_token_t *token,
2233
    njs_queue_link_t *current)
2234
65.6k
{
2235
65.6k
    njs_parser_node_t  *stmt;
2236
2237
65.6k
    stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
2238
65.6k
    if (stmt == NULL) {
2239
0
        return NJS_ERROR;
2240
0
    }
2241
2242
65.6k
    stmt->left = NULL;
2243
65.6k
    stmt->right = parser->target;
2244
2245
65.6k
    parser->target->right = parser->node;
2246
65.6k
    parser->node = stmt;
2247
2248
65.6k
    return njs_parser_stack_pop(parser);
2249
65.6k
}
2250
2251
2252
static njs_int_t
2253
njs_parser_initializer_assign(njs_parser_t *parser, njs_token_type_t type)
2254
77.2k
{
2255
77.2k
    njs_parser_node_t  *assign;
2256
2257
77.2k
    assign = njs_parser_node_new(parser, type);
2258
77.2k
    if (assign == NULL) {
2259
0
        return NJS_ERROR;
2260
0
    }
2261
2262
77.2k
    assign->u.operation = NJS_VMCODE_MOVE;
2263
77.2k
    assign->left = parser->node;
2264
2265
    /* assign->right in njs_parser_initializer_after. */
2266
2267
77.2k
    parser->node = assign;
2268
2269
77.2k
    return NJS_OK;
2270
77.2k
}
2271
2272
2273
static njs_int_t
2274
njs_parser_tagged_template_literal_after(njs_parser_t *parser,
2275
    njs_lexer_token_t *token, njs_queue_link_t *current)
2276
988k
{
2277
988k
    return njs_parser_stack_pop(parser);
2278
988k
}
2279
2280
/*
2281
 * 12.3 Left-Hand-Side Expressions.
2282
 */
2283
static njs_int_t
2284
njs_parser_property(njs_parser_t *parser, njs_lexer_token_t *token,
2285
    njs_queue_link_t *current)
2286
5.51M
{
2287
5.51M
    njs_parser_node_t  *node, *prop_node;
2288
2289
    /*
2290
     * [ Expression ]
2291
     * . IdentifierName
2292
     * TemplateLiteral
2293
     */
2294
2295
5.51M
    switch (token->type) {
2296
178k
    case NJS_TOKEN_OPEN_BRACKET:
2297
178k
        node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
2298
178k
        if (node == NULL) {
2299
0
            return NJS_ERROR;
2300
0
        }
2301
2302
178k
        node->u.operation = NJS_VMCODE_PROPERTY_GET;
2303
178k
        node->left = parser->node;
2304
178k
        node->token_line = token->line;
2305
2306
178k
        parser->node = NULL;
2307
2308
178k
        njs_lexer_consume_token(parser->lexer, 1);
2309
2310
178k
        njs_parser_next(parser, njs_parser_expression);
2311
2312
178k
        return njs_parser_after(parser, current, node, 1,
2313
178k
                                njs_parser_member_expression_bracket);
2314
2315
223k
    case NJS_TOKEN_DOT:
2316
223k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
2317
223k
        if (token == NULL) {
2318
0
            return NJS_ERROR;
2319
0
        }
2320
2321
223k
        if (njs_lexer_token_is_identifier_name(token)) {
2322
223k
            node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
2323
223k
            if (node == NULL) {
2324
0
                return NJS_ERROR;
2325
0
            }
2326
2327
223k
            node->u.operation = NJS_VMCODE_PROPERTY_ATOM_GET;
2328
223k
            node->token_line = token->line;
2329
2330
223k
            prop_node = njs_parser_node_string(parser->vm, token, parser);
2331
223k
            if (prop_node == NULL) {
2332
0
                return NJS_ERROR;
2333
0
            }
2334
2335
223k
            prop_node->token_line = token->line;
2336
2337
223k
            node->left = parser->node;
2338
223k
            node->right = prop_node;
2339
2340
223k
            parser->node = node;
2341
2342
223k
            njs_lexer_consume_token(parser->lexer, 2);
2343
223k
            return NJS_AGAIN;
2344
223k
        }
2345
2346
532
        njs_lexer_consume_token(parser->lexer, 1);
2347
2348
532
        return NJS_DECLINED;
2349
2350
991k
    case NJS_TOKEN_GRAVE:
2351
991k
        node = njs_parser_create_call(parser, parser->node, 0);
2352
991k
        if (node == NULL) {
2353
0
            return NJS_ERROR;
2354
0
        }
2355
2356
991k
        node->token_line = token->line;
2357
2358
991k
        parser->node = node;
2359
2360
991k
        njs_parser_next(parser, njs_parser_template_literal);
2361
2362
991k
        return njs_parser_after(parser, current, node, 1,
2363
991k
                                njs_parser_tagged_template_literal_after);
2364
2365
4.12M
    default:
2366
4.12M
        return NJS_DONE;
2367
5.51M
    }
2368
2369
0
    return NJS_OK;
2370
5.51M
}
2371
2372
2373
static njs_int_t
2374
njs_parser_member_expression(njs_parser_t *parser, njs_lexer_token_t *token,
2375
    njs_queue_link_t *current)
2376
4.54M
{
2377
4.54M
    njs_int_t  ret;
2378
2379
    /*
2380
     * PrimaryExpression
2381
     * MemberExpression [ Expression ]
2382
     * MemberExpression . IdentifierName
2383
     * MemberExpression TemplateLiteral
2384
     * SuperProperty
2385
     * MetaProperty
2386
     * new MemberExpression Arguments
2387
     */
2388
2389
4.54M
    switch (token->type) {
2390
    /* SuperProperty */
2391
534
    case NJS_TOKEN_SUPER:
2392
        /* TODO: By specification. */
2393
534
        (void) njs_parser_super_property;
2394
534
        return njs_parser_not_supported(parser, token);
2395
2396
    /* MetaProperty */
2397
250
    case NJS_TOKEN_IMPORT:
2398
        /* TODO: By specification. */
2399
250
        (void) njs_parser_member_expression_import;
2400
250
        return njs_parser_not_supported(parser, token);
2401
2402
8.39k
    case NJS_TOKEN_NEW:
2403
8.39k
        njs_lexer_consume_token(parser->lexer, 1);
2404
2405
8.39k
        njs_parser_next(parser, njs_parser_member_expression_new);
2406
8.39k
        break;
2407
2408
4.53M
    default:
2409
4.53M
        ret = njs_parser_primary_expression_test(parser, token, current);
2410
2411
4.53M
        if (ret != NJS_OK) {
2412
3.74M
            if (ret == NJS_DONE) {
2413
3.71M
                njs_parser_next(parser, njs_parser_member_expression_next);
2414
3.71M
                return NJS_OK;
2415
3.71M
            }
2416
2417
30.2k
            if (njs_is_error(&parser->vm->exception)) {
2418
4.86k
                return NJS_DONE;
2419
4.86k
            }
2420
2421
25.3k
            return ret;
2422
30.2k
        }
2423
2424
791k
        break;
2425
4.54M
    }
2426
2427
799k
    return njs_parser_after(parser, current, NULL, 1,
2428
4.54M
                            njs_parser_member_expression_next);
2429
4.54M
}
2430
2431
2432
static njs_int_t
2433
njs_parser_member_expression_next(njs_parser_t *parser,
2434
    njs_lexer_token_t *token, njs_queue_link_t *current)
2435
5.41M
{
2436
5.41M
    njs_int_t  ret;
2437
2438
    /*
2439
     * [ Expression ]
2440
     * . IdentifierName
2441
     * TemplateLiteral
2442
     */
2443
2444
5.41M
    ret = njs_parser_property(parser, token, current);
2445
2446
5.41M
    switch (ret) {
2447
218k
    case NJS_AGAIN:
2448
218k
        return NJS_OK;
2449
2450
4.03M
    case NJS_DONE:
2451
4.03M
        return njs_parser_stack_pop(parser);
2452
2453
276
    case NJS_DECLINED:
2454
276
        return njs_parser_failed(parser);
2455
2456
1.16M
    default:
2457
1.16M
        break;
2458
5.41M
    }
2459
2460
1.16M
    return njs_parser_after(parser, current, NULL, 1,
2461
5.41M
                            njs_parser_member_expression_next);
2462
5.41M
}
2463
2464
2465
static njs_int_t
2466
njs_parser_member_expression_bracket(njs_parser_t *parser,
2467
    njs_lexer_token_t *token, njs_queue_link_t *current)
2468
162k
{
2469
162k
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
2470
9.01k
        return njs_parser_failed(parser);
2471
9.01k
    }
2472
2473
153k
    njs_lexer_consume_token(parser->lexer, 1);
2474
2475
153k
    return njs_parser_right_link_pop(parser);
2476
162k
}
2477
2478
2479
static njs_int_t
2480
njs_parser_member_expression_new_next(njs_parser_t *parser,
2481
    njs_lexer_token_t *token, njs_queue_link_t *current)
2482
7.95k
{
2483
7.95k
    njs_int_t  ret;
2484
2485
    /*
2486
     * PrimaryExpression
2487
     * SuperProperty
2488
     * MetaProperty
2489
     * Arguments
2490
     */
2491
2492
7.95k
    switch (token->type) {
2493
    /* SuperProperty */
2494
1.24k
    case NJS_TOKEN_SUPER:
2495
1.24k
        (void) njs_parser_super_property;
2496
1.24k
        return njs_parser_not_supported(parser, token);
2497
2498
    /* MetaProperty */
2499
0
    case NJS_TOKEN_IMPORT:
2500
0
        (void) njs_parser_member_expression_import;
2501
0
        return njs_parser_not_supported(parser, token);
2502
2503
6.70k
    default:
2504
6.70k
        ret = njs_parser_primary_expression_test(parser, token, current);
2505
2506
6.70k
        if (ret != NJS_OK) {
2507
6.40k
            if (ret == NJS_DONE) {
2508
6.27k
                njs_parser_next(parser, njs_parser_member_expression_next);
2509
6.27k
                return NJS_OK;
2510
6.27k
            }
2511
2512
137
            return ret;
2513
6.40k
        }
2514
2515
301
        return njs_parser_after(parser, current, NULL, 1,
2516
7.95k
                                njs_parser_member_expression_next);
2517
7.95k
    }
2518
7.95k
}
2519
2520
2521
static njs_int_t
2522
njs_parser_super_property(njs_parser_t *parser, njs_lexer_token_t *token,
2523
    njs_queue_link_t *current)
2524
0
{
2525
    /*
2526
     * [ Expression ]
2527
     * . IdentifierName
2528
     */
2529
2530
0
    if (token->type == NJS_TOKEN_OPEN_BRACKET) {
2531
0
        parser->node = NULL;
2532
2533
0
        njs_parser_next(parser, njs_parser_expression);
2534
2535
0
        return njs_parser_after(parser, current, NULL, 1,
2536
0
                                njs_parser_close_bracked);
2537
0
    }
2538
2539
0
    if (token->type != NJS_TOKEN_DOT) {
2540
0
        return njs_parser_failed(parser);
2541
0
    }
2542
2543
0
    njs_lexer_consume_token(parser->lexer, 1);
2544
2545
0
    token = njs_lexer_token(parser->lexer, 0);
2546
0
    if (token == NULL) {
2547
0
        return NJS_ERROR;
2548
0
    }
2549
2550
0
    if (!njs_lexer_token_is_identifier_name(token)) {
2551
0
        return njs_parser_failed(parser);
2552
0
    }
2553
2554
0
    return njs_parser_stack_pop(parser);
2555
0
}
2556
2557
2558
static njs_int_t
2559
njs_parser_member_expression_import(njs_parser_t *parser,
2560
    njs_lexer_token_t *token, njs_queue_link_t *current)
2561
0
{
2562
    /*
2563
     * import . meta
2564
     */
2565
2566
0
    if (token->type != NJS_TOKEN_DOT) {
2567
0
        return njs_parser_failed(parser);
2568
0
    }
2569
2570
0
    njs_lexer_consume_token(parser->lexer, 1);
2571
2572
0
    token = njs_lexer_token(parser->lexer, 0);
2573
0
    if (token == NULL) {
2574
0
        return NJS_ERROR;
2575
0
    }
2576
2577
0
    if (token->type != NJS_TOKEN_META) {
2578
0
        return njs_parser_failed(parser);
2579
0
    }
2580
2581
0
    njs_lexer_consume_token(parser->lexer, 1);
2582
2583
0
    return njs_parser_stack_pop(parser);
2584
0
}
2585
2586
2587
static njs_int_t
2588
njs_parser_member_expression_new(njs_parser_t *parser,
2589
    njs_lexer_token_t *token, njs_queue_link_t *current)
2590
9.50k
{
2591
    /*
2592
     * new MemberExpression Arguments
2593
     * new . target
2594
     */
2595
2596
9.50k
    if (token->type != NJS_TOKEN_DOT) {
2597
7.95k
        njs_parser_next(parser, njs_parser_member_expression_new_next);
2598
2599
7.95k
        return njs_parser_after(parser, current, NULL, 1,
2600
7.95k
                                njs_parser_member_expression_new_after);
2601
7.95k
    }
2602
2603
    /* njs_lexer_consume_token(parser->lexer, 1); */
2604
2605
1.54k
    token = njs_lexer_token(parser->lexer, 0);
2606
1.54k
    if (token == NULL) {
2607
0
        return NJS_ERROR;
2608
0
    }
2609
2610
1.54k
    if (token->type != NJS_TOKEN_TARGET) {
2611
1.54k
        return njs_parser_failed(parser);
2612
1.54k
    }
2613
2614
    /* njs_lexer_consume_token(parser->lexer, 1); */
2615
2616
    /* return njs_parser_stack_pop(parser); */
2617
0
    return njs_parser_not_supported(parser, token);
2618
1.54k
}
2619
2620
2621
static njs_int_t
2622
njs_parser_member_expression_new_after(njs_parser_t *parser,
2623
    njs_lexer_token_t *token, njs_queue_link_t *current)
2624
6.70k
{
2625
6.70k
    njs_parser_node_t  *func;
2626
2627
6.70k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
2628
3.21k
        parser->node = njs_parser_create_call(parser, parser->node, 1);
2629
3.21k
        if (parser->node == NULL) {
2630
0
            return NJS_ERROR;
2631
0
        }
2632
2633
3.21k
        parser->node->token_line = token->line;
2634
2635
3.21k
        return njs_parser_stack_pop(parser);
2636
3.21k
    }
2637
2638
3.48k
    func = njs_parser_create_call(parser, parser->node, 1);
2639
3.48k
    if (func == NULL) {
2640
0
        return NJS_ERROR;
2641
0
    }
2642
2643
3.48k
    return njs_parser_call_arguments(parser, token, current, func,
2644
3.48k
                                     njs_parser_member_expression_new_args);
2645
3.48k
}
2646
2647
2648
static njs_int_t
2649
njs_parser_member_expression_new_args(njs_parser_t *parser,
2650
    njs_lexer_token_t *token, njs_queue_link_t *current)
2651
3.35k
{
2652
3.35k
    parser->node = parser->target;
2653
2654
3.35k
    return njs_parser_stack_pop(parser);
2655
3.35k
}
2656
2657
2658
static njs_parser_node_t *
2659
njs_parser_property_ref(njs_parser_node_t *node)
2660
2.39M
{
2661
2.39M
    if (node == NULL) {
2662
0
        return NULL;
2663
0
    }
2664
2665
2.39M
    if (node->token_type == NJS_TOKEN_PROPERTY) {
2666
234k
        node->token_type = NJS_TOKEN_PROPERTY_REF;
2667
234k
    }
2668
2669
2.39M
    if (node->token_type == NJS_TOKEN_PROPERTY_REF) {
2670
236k
        return node;
2671
236k
    }
2672
2673
2.15M
    return NULL;
2674
2.39M
}
2675
2676
2677
static njs_parser_node_t *
2678
njs_parser_lvalue_ref(njs_parser_node_t *node)
2679
586k
{
2680
586k
    if (node == NULL) {
2681
0
        return NULL;
2682
0
    }
2683
2684
586k
    if (node->token_type == NJS_TOKEN_NAME) {
2685
379k
        return node;
2686
379k
    }
2687
2688
207k
    return njs_parser_property_ref(node);
2689
586k
}
2690
2691
2692
static njs_parser_node_t *
2693
njs_parser_call_receiver(njs_parser_node_t *node)
2694
2.18M
{
2695
2.18M
    return njs_parser_property_ref(node);
2696
2.18M
}
2697
2698
2699
static njs_parser_node_t *
2700
njs_parser_optional_chain_preserve(njs_parser_t *parser,
2701
    njs_parser_node_t *node, uint32_t token_line)
2702
15.9k
{
2703
15.9k
    njs_parser_node_t  *ref;
2704
2705
15.9k
    ref = njs_parser_node_new(parser, NJS_TOKEN_OPTIONAL_PRESERVE);
2706
15.9k
    if (ref == NULL) {
2707
0
        return NULL;
2708
0
    }
2709
2710
15.9k
    ref->token_line = token_line;
2711
15.9k
    ref->u.object = node;
2712
2713
15.9k
    return ref;
2714
15.9k
}
2715
2716
2717
static void
2718
njs_parser_set_optional_chain_preserve(njs_parser_node_t *node,
2719
    njs_parser_node_t *preserve)
2720
15.9k
{
2721
15.9k
    njs_assert(node->token_type == NJS_TOKEN_OPTIONAL_CHAIN);
2722
15.9k
    njs_assert(preserve->token_type == NJS_TOKEN_OPTIONAL_PRESERVE);
2723
2724
15.9k
    node->u.object = preserve;
2725
15.9k
}
2726
2727
2728
static njs_parser_node_t *
2729
njs_parser_optional_chain_source(njs_parser_node_t *node)
2730
3.65k
{
2731
3.65k
    if (node != NULL && node->token_type == NJS_TOKEN_OPTIONAL_PRESERVE) {
2732
3.65k
        return node->u.object;
2733
3.65k
    }
2734
2735
0
    return NULL;
2736
3.65k
}
2737
2738
2739
static njs_parser_node_t *
2740
njs_parser_create_call(njs_parser_t *parser, njs_parser_node_t *node,
2741
    uint8_t ctor)
2742
1.10M
{
2743
1.10M
    njs_parser_node_t  *func, *receiver, *this_object;
2744
2745
1.10M
    receiver = njs_parser_call_receiver(node);
2746
1.10M
    if (receiver != NULL) {
2747
24.8k
        func = njs_parser_node_new(parser, NJS_TOKEN_METHOD_CALL);
2748
24.8k
        if (func == NULL) {
2749
0
            return NULL;
2750
0
        }
2751
2752
24.8k
        func->left = receiver;
2753
24.8k
        func->ctor = ctor;
2754
2755
24.8k
        return func;
2756
24.8k
    }
2757
2758
1.07M
    this_object = njs_parser_optional_chain_call_this(node);
2759
2760
    /*
2761
     * NJS_TOKEN_NAME,
2762
     * NJS_TOKEN_METHOD_CALL,
2763
     * NJS_TOKEN_FUNCTION_CALL,
2764
     * NJS_TOKEN_FUNCTION_EXPRESSION,
2765
     * NJS_TOKEN_OPEN_PARENTHESIS,
2766
     * NJS_TOKEN_EVAL.
2767
     */
2768
1.07M
    func = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_CALL);
2769
1.07M
    if (func == NULL) {
2770
0
        return NULL;
2771
0
    }
2772
2773
1.07M
    func->left = node;
2774
1.07M
    func->ctor = ctor;
2775
1.07M
    njs_parser_set_call_this(func, this_object);
2776
2777
1.07M
    return func;
2778
1.07M
}
2779
2780
2781
static njs_int_t
2782
njs_parser_call_arguments(njs_parser_t *parser, njs_lexer_token_t *token,
2783
    njs_queue_link_t *current, njs_parser_node_t *func,
2784
    njs_parser_state_func_t after)
2785
11.2k
{
2786
11.2k
    func->token_line = token->line;
2787
11.2k
    parser->node = func;
2788
2789
11.2k
    njs_lexer_consume_token(parser->lexer, 1);
2790
11.2k
    njs_parser_next(parser, njs_parser_arguments);
2791
2792
11.2k
    return njs_parser_after(parser, current, func, 1, after);
2793
11.2k
}
2794
2795
2796
static njs_int_t
2797
njs_parser_right_link_pop(njs_parser_t *parser)
2798
695k
{
2799
695k
    parser->target->right = parser->node;
2800
695k
    parser->node = parser->target;
2801
2802
695k
    return njs_parser_stack_pop(parser);
2803
695k
}
2804
2805
2806
static njs_parser_node_t *
2807
njs_parser_optional_chain_receiver(njs_parser_node_t *node)
2808
1.08M
{
2809
1.08M
    if (njs_parser_call_receiver(node) != NULL) {
2810
1.03k
        return node;
2811
1.03k
    }
2812
2813
1.07M
    if (node != NULL
2814
1.07M
        && node->token_type == NJS_TOKEN_OPTIONAL_CHAIN
2815
1.54k
        && node->right != NULL
2816
1.54k
        && njs_parser_call_receiver(node->right) != NULL)
2817
1.45k
    {
2818
1.45k
        return node->right;
2819
1.45k
    }
2820
2821
1.07M
    return NULL;
2822
1.07M
}
2823
2824
2825
static njs_vmcode_t
2826
njs_parser_optional_chain_receiver_operation(njs_parser_node_t *node)
2827
2.27k
{
2828
2.27k
    return node->u.operation;
2829
2.27k
}
2830
2831
2832
static njs_parser_node_t *
2833
njs_parser_optional_chain_receiver_base(njs_parser_node_t *node)
2834
2.48k
{
2835
2.48k
    return node->left;
2836
2.48k
}
2837
2838
2839
static njs_parser_node_t *
2840
njs_parser_optional_chain_receiver_key(njs_parser_node_t *node)
2841
2.27k
{
2842
2.27k
    return node->right;
2843
2.27k
}
2844
2845
2846
static njs_parser_node_t *
2847
njs_parser_optional_chain_call_this(njs_parser_node_t *node)
2848
1.07M
{
2849
1.07M
    njs_parser_node_t  *receiver;
2850
2851
1.07M
    receiver = njs_parser_optional_chain_receiver(node);
2852
1.07M
    if (receiver != NULL) {
2853
212
        return njs_parser_optional_chain_receiver_base(receiver);
2854
212
    }
2855
2856
1.07M
    return NULL;
2857
1.07M
}
2858
2859
2860
static void
2861
njs_parser_set_call_this(njs_parser_node_t *node,
2862
    njs_parser_node_t *this_object)
2863
1.07M
{
2864
1.07M
    njs_assert(node->token_type == NJS_TOKEN_FUNCTION_CALL);
2865
2866
1.07M
    node->u.object = this_object;
2867
1.07M
}
2868
2869
2870
static void
2871
njs_parser_set_optional_method_call_preserve(njs_parser_node_t *node,
2872
    njs_parser_node_t *preserve)
2873
2.27k
{
2874
2.27k
    njs_assert(node->token_type == NJS_TOKEN_METHOD_CALL);
2875
2.27k
    njs_assert(njs_parser_call_receiver(preserve) != NULL);
2876
2877
2.27k
    node->u.object = preserve;
2878
2.27k
}
2879
2880
2881
static njs_parser_node_t *
2882
njs_parser_optional_chain_target_property(njs_parser_node_t *node)
2883
2.10k
{
2884
2.10k
    if (node == NULL || node->token_type != NJS_TOKEN_OPTIONAL_CHAIN) {
2885
0
        return NULL;
2886
0
    }
2887
2888
2.10k
    return njs_parser_property_ref(node->right);
2889
2.10k
}
2890
2891
2892
static njs_parser_node_t *
2893
njs_parser_optional_chain_method_call(njs_parser_t *parser,
2894
    njs_parser_node_t *node, uint32_t token_line)
2895
3.65k
{
2896
3.65k
    njs_parser_node_t  *func, *prop, *src;
2897
2898
3.65k
    src = njs_parser_optional_chain_receiver(node);
2899
3.65k
    if (src == NULL) {
2900
1.38k
        return NULL;
2901
1.38k
    }
2902
2903
2.27k
    prop = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY_REF);
2904
2.27k
    if (prop == NULL) {
2905
0
        return NULL;
2906
0
    }
2907
2908
2.27k
    prop->u.operation = njs_parser_optional_chain_receiver_operation(src);
2909
2.27k
    prop->token_line = token_line;
2910
2.27k
    prop->left = njs_parser_optional_chain_receiver_base(src);
2911
2.27k
    prop->right = njs_parser_optional_chain_receiver_key(src);
2912
2913
2.27k
    func = njs_parser_create_call(parser, prop, 0);
2914
2.27k
    if (func == NULL) {
2915
0
        return NULL;
2916
0
    }
2917
2918
2.27k
    njs_parser_set_optional_method_call_preserve(func, src);
2919
2920
2.27k
    return func;
2921
2.27k
}
2922
2923
2924
static njs_parser_node_t *
2925
njs_parser_optional_chain_call(njs_parser_t *parser, njs_parser_node_t *node,
2926
    njs_parser_node_t *fallback, uint32_t token_line)
2927
3.65k
{
2928
3.65k
    njs_parser_node_t  *func;
2929
2930
3.65k
    func = njs_parser_optional_chain_method_call(parser, node, token_line);
2931
3.65k
    if (func != NULL) {
2932
2.27k
        return func;
2933
2.27k
    }
2934
2935
1.38k
    return njs_parser_create_call(parser, fallback, 0);
2936
3.65k
}
2937
2938
2939
static njs_int_t
2940
njs_parser_call_expression(njs_parser_t *parser, njs_lexer_token_t *token,
2941
    njs_queue_link_t *current)
2942
279
{
2943
279
    njs_int_t  ret;
2944
2945
    /*
2946
     * CoverCallExpressionAndAsyncArrowHead
2947
     * SuperCall
2948
     * ImportCall
2949
     * CallExpression Arguments
2950
     * CallExpression [ Expression ]
2951
     * CallExpression . IdentifierName
2952
     * CallExpression TemplateLiteral
2953
     */
2954
2955
279
    switch (token->type) {
2956
    /* MemberExpression or SuperCall */
2957
148
    case NJS_TOKEN_SUPER:
2958
148
        return njs_parser_not_supported(parser, token);
2959
2960
131
    case NJS_TOKEN_IMPORT:
2961
131
        return njs_parser_not_supported(parser, token);
2962
2963
0
    default:
2964
0
        break;
2965
279
    }
2966
2967
0
    njs_parser_next(parser, njs_parser_member_expression);
2968
2969
0
    ret = njs_parser_after(parser, current, NULL, 1,
2970
0
                           njs_parser_call_expression_args);
2971
0
    if (ret != NJS_OK) {
2972
0
        return NJS_ERROR;
2973
0
    }
2974
2975
0
    return njs_parser_after(parser, current, NULL, 1,
2976
0
                            njs_parser_call_expression_after);
2977
0
}
2978
2979
2980
static njs_int_t
2981
njs_parser_call_expression_args(njs_parser_t *parser, njs_lexer_token_t *token,
2982
    njs_queue_link_t *current)
2983
0
{
2984
0
    njs_parser_node_t  *func;
2985
2986
0
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
2987
0
        return njs_parser_failed(parser);
2988
0
    }
2989
2990
0
    func = njs_parser_create_call(parser, parser->node, 0);
2991
0
    if (func == NULL) {
2992
0
        return NJS_ERROR;
2993
0
    }
2994
2995
0
    return njs_parser_call_arguments(parser, token, current, func,
2996
0
                                     njs_parser_left_hand_side_expression_node);
2997
0
}
2998
2999
3000
static njs_int_t
3001
njs_parser_call_or_property_after(njs_parser_t *parser,
3002
    njs_lexer_token_t *token, njs_queue_link_t *current,
3003
    njs_parser_state_func_t after)
3004
110k
{
3005
110k
    njs_int_t          ret;
3006
110k
    njs_parser_node_t  *func;
3007
3008
110k
    switch (token->type) {
3009
4.11k
    case NJS_TOKEN_OPEN_PARENTHESIS:
3010
4.11k
        func = njs_parser_create_call(parser, parser->node, 0);
3011
4.11k
        if (func == NULL) {
3012
0
            return NJS_ERROR;
3013
0
        }
3014
3015
4.11k
        ret = njs_parser_call_arguments(parser, token, current, func,
3016
4.11k
                                        njs_parser_left_hand_side_expression_node);
3017
4.11k
        if (ret != NJS_OK) {
3018
0
            return NJS_ERROR;
3019
0
        }
3020
3021
4.11k
        break;
3022
3023
106k
    default:
3024
106k
        ret = njs_parser_property(parser, token, current);
3025
3026
106k
        switch (ret) {
3027
4.59k
        case NJS_AGAIN:
3028
4.59k
            return NJS_OK;
3029
3030
91.6k
        case NJS_DONE:
3031
91.6k
            return njs_parser_stack_pop(parser);
3032
3033
256
        case NJS_DECLINED:
3034
256
            return njs_parser_failed(parser);
3035
3036
9.57k
        default:
3037
9.57k
            break;
3038
106k
        }
3039
3040
9.57k
        break;
3041
110k
    }
3042
3043
13.6k
    return njs_parser_after(parser, current, NULL, 1, after);
3044
110k
}
3045
3046
3047
static njs_int_t
3048
njs_parser_call_expression_after(njs_parser_t *parser,
3049
    njs_lexer_token_t *token, njs_queue_link_t *current)
3050
0
{
3051
    /*
3052
     * Arguments
3053
     * [ Expression ]
3054
     * . IdentifierName
3055
     * TemplateLiteral
3056
     */
3057
3058
0
    return njs_parser_call_or_property_after(parser, token, current,
3059
0
                                             njs_parser_call_expression_after);
3060
0
}
3061
3062
3063
static njs_int_t
3064
njs_parser_arguments(njs_parser_t *parser, njs_lexer_token_t *token,
3065
    njs_queue_link_t *current)
3066
106k
{
3067
    /*
3068
     * )
3069
     * ArgumentList )
3070
     * ArgumentList , )
3071
     */
3072
3073
106k
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
3074
28.6k
        njs_lexer_consume_token(parser->lexer, 1);
3075
28.6k
        return njs_parser_stack_pop(parser);
3076
28.6k
    }
3077
3078
78.0k
    njs_parser_next(parser, njs_parser_argument_list);
3079
3080
78.0k
    return njs_parser_after(parser, current, NULL, 1,
3081
106k
                            njs_parser_parenthesis_or_comma);
3082
106k
}
3083
3084
3085
static njs_int_t
3086
njs_parser_parenthesis_or_comma(njs_parser_t *parser, njs_lexer_token_t *token,
3087
    njs_queue_link_t *current)
3088
61.2k
{
3089
61.2k
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
3090
60.1k
        njs_lexer_consume_token(parser->lexer, 1);
3091
60.1k
        return njs_parser_stack_pop(parser);
3092
60.1k
    }
3093
3094
1.13k
    if (token->type != NJS_TOKEN_COMMA) {
3095
1.13k
        return njs_parser_failed(parser);
3096
1.13k
    }
3097
3098
0
    njs_lexer_consume_token(parser->lexer, 1);
3099
3100
0
    token = njs_lexer_token(parser->lexer, 0);
3101
0
    if (njs_slow_path(token == NULL)) {
3102
0
        return NJS_ERROR;
3103
0
    }
3104
3105
0
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
3106
0
        return njs_parser_failed(parser);
3107
0
    }
3108
3109
0
    njs_lexer_consume_token(parser->lexer, 1);
3110
3111
0
    return njs_parser_stack_pop(parser);
3112
0
}
3113
3114
3115
static njs_int_t
3116
njs_parser_argument_list(njs_parser_t *parser, njs_lexer_token_t *token,
3117
    njs_queue_link_t *current)
3118
149k
{
3119
    /*
3120
     * AssignmentExpression
3121
     * ... AssignmentExpression
3122
     * ArgumentList , AssignmentExpression
3123
     * ArgumentList , ... AssignmentExpression
3124
     */
3125
3126
#if 0 /* TODO. */
3127
    if (token->type == NJS_TOKEN_ELLIPSIS) {
3128
        njs_lexer_consume_token(parser->lexer, 1);
3129
    }
3130
#endif
3131
3132
149k
    njs_parser_next(parser, njs_parser_assignment_expression);
3133
3134
149k
    return njs_parser_after(parser, current, parser->node, 1,
3135
149k
                            njs_parser_argument_list_after);
3136
149k
}
3137
3138
3139
static njs_int_t
3140
njs_parser_argument_list_after(njs_parser_t *parser, njs_lexer_token_t *token,
3141
    njs_queue_link_t *current)
3142
133k
{
3143
133k
    njs_parser_node_t  *node;
3144
3145
133k
    node = njs_parser_node_new(parser, NJS_TOKEN_ARGUMENT);
3146
133k
    if (node == NULL) {
3147
0
        return NJS_ERROR;
3148
0
    }
3149
3150
133k
    node->index = njs_scope_temp_index(node->scope);
3151
133k
    if (njs_slow_path(node->index == NJS_INDEX_ERROR)) {
3152
0
        return NJS_ERROR;
3153
0
    }
3154
3155
133k
    node->token_line = token->line;
3156
133k
    node->left = parser->node;
3157
3158
133k
    parser->node->dest = node;
3159
133k
    parser->target->right = node;
3160
133k
    parser->node = node;
3161
3162
133k
    if (token->type == NJS_TOKEN_COMMA) {
3163
72.3k
        njs_lexer_consume_token(parser->lexer, 1);
3164
3165
72.3k
        token = njs_lexer_token(parser->lexer, 0);
3166
72.3k
        if (token == NULL) {
3167
0
            return NJS_ERROR;
3168
0
        }
3169
3170
72.3k
        if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
3171
420
            return njs_parser_stack_pop(parser);
3172
420
        }
3173
3174
71.9k
        return njs_parser_argument_list(parser, token, current);
3175
72.3k
    }
3176
3177
60.8k
    return njs_parser_stack_pop(parser);
3178
133k
}
3179
3180
3181
static njs_int_t
3182
njs_parser_optional_chain_wrap(njs_parser_t *parser,
3183
    njs_lexer_token_t *token, njs_queue_link_t *current)
3184
11.9k
{
3185
11.9k
    return njs_parser_right_link_pop(parser);
3186
11.9k
}
3187
3188
3189
static njs_int_t
3190
njs_parser_optional_expression_after(njs_parser_t *parser,
3191
    njs_lexer_token_t *token, njs_queue_link_t *current)
3192
67.9k
{
3193
67.9k
    njs_int_t          ret;
3194
67.9k
    njs_parser_node_t  *opt, *ref;
3195
3196
67.9k
    if (token->type != NJS_TOKEN_CONDITIONAL) {
3197
8.78k
        return njs_parser_stack_pop(parser);
3198
8.78k
    }
3199
3200
59.1k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
3201
59.1k
    if (token == NULL) {
3202
0
        return NJS_ERROR;
3203
0
    }
3204
3205
59.1k
    if (token->type != NJS_TOKEN_DOT) {
3206
43.1k
        return njs_parser_stack_pop(parser);
3207
43.1k
    }
3208
3209
15.9k
    opt = njs_parser_node_new(parser, NJS_TOKEN_OPTIONAL_CHAIN);
3210
15.9k
    if (opt == NULL) {
3211
0
        return NJS_ERROR;
3212
0
    }
3213
3214
15.9k
    opt->token_line = token->line;
3215
15.9k
    opt->left = parser->node;
3216
15.9k
    opt->left->dest = opt;
3217
3218
15.9k
    ref = njs_parser_optional_chain_preserve(parser, parser->node,
3219
15.9k
                                             token->line);
3220
15.9k
    if (ref == NULL) {
3221
0
        return NJS_ERROR;
3222
0
    }
3223
3224
15.9k
    njs_parser_set_optional_chain_preserve(opt, ref);
3225
15.9k
    parser->node = ref;
3226
3227
15.9k
    njs_parser_next(parser, njs_parser_optional_chain);
3228
3229
15.9k
    ret = njs_parser_after(parser, current, opt, 1,
3230
15.9k
                           njs_parser_optional_chain_wrap);
3231
15.9k
    if (ret != NJS_OK) {
3232
0
        return NJS_ERROR;
3233
0
    }
3234
3235
15.9k
    return njs_parser_after(parser, current, NULL, 1,
3236
15.9k
                            njs_parser_optional_expression_after);
3237
15.9k
}
3238
3239
3240
static njs_int_t
3241
njs_parser_optional_chain(njs_parser_t *parser, njs_lexer_token_t *token,
3242
    njs_queue_link_t *current)
3243
15.9k
{
3244
15.9k
    njs_int_t          ret;
3245
15.9k
    njs_parser_node_t  *node, *func, *prop_node;
3246
3247
    /*
3248
     * ?. Arguments
3249
     * ?. [ Expression ]
3250
     * ?. IdentifierName
3251
     */
3252
3253
15.9k
    if (token->type != NJS_TOKEN_CONDITIONAL) {
3254
0
        return njs_parser_failed(parser);
3255
0
    }
3256
3257
15.9k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
3258
15.9k
    if (token == NULL) {
3259
0
        return NJS_ERROR;
3260
0
    }
3261
3262
15.9k
    if (token->type != NJS_TOKEN_DOT) {
3263
0
        return njs_parser_failed(parser);
3264
0
    }
3265
3266
    /* Consume both '?' and '.' */
3267
15.9k
    njs_lexer_consume_token(parser->lexer, 2);
3268
3269
15.9k
    token = njs_lexer_token(parser->lexer, 0);
3270
15.9k
    if (token == NULL) {
3271
0
        return NJS_ERROR;
3272
0
    }
3273
3274
15.9k
    switch (token->type) {
3275
3.65k
    case NJS_TOKEN_OPEN_PARENTHESIS:
3276
3.65k
        func = njs_parser_optional_chain_call(parser,
3277
3.65k
                                              njs_parser_optional_chain_source(
3278
3.65k
                                                  parser->node),
3279
3.65k
                                              parser->node, token->line);
3280
3.65k
        if (func == NULL) {
3281
0
            return NJS_ERROR;
3282
0
        }
3283
3284
3.65k
        ret = njs_parser_call_arguments(parser, token, current, func,
3285
3.65k
                                        njs_parser_left_hand_side_expression_node);
3286
3.65k
        if (ret != NJS_OK) {
3287
0
            return NJS_ERROR;
3288
0
        }
3289
3290
3.65k
        return njs_parser_after(parser, current, NULL, 1,
3291
3.65k
                                njs_parser_optional_chain_after);
3292
3293
832
    case NJS_TOKEN_OPEN_BRACKET:
3294
832
        node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
3295
832
        if (node == NULL) {
3296
0
            return NJS_ERROR;
3297
0
        }
3298
3299
832
        node->u.operation = NJS_VMCODE_PROPERTY_GET;
3300
832
        node->left = parser->node;
3301
832
        node->token_line = token->line;
3302
3303
832
        parser->node = NULL;
3304
3305
832
        njs_lexer_consume_token(parser->lexer, 1);
3306
3307
832
        njs_parser_next(parser, njs_parser_expression);
3308
3309
832
        ret = njs_parser_after(parser, current, node, 1,
3310
832
                               njs_parser_member_expression_bracket);
3311
832
        if (ret != NJS_OK) {
3312
0
            return NJS_ERROR;
3313
0
        }
3314
3315
832
        return njs_parser_after(parser, current, NULL, 1,
3316
832
                                njs_parser_optional_chain_after);
3317
3318
11.4k
    default:
3319
11.4k
        if (!njs_lexer_token_is_identifier_name(token)) {
3320
469
            return njs_parser_failed(parser);
3321
469
        }
3322
3323
11.0k
        node = njs_parser_node_new(parser, NJS_TOKEN_PROPERTY);
3324
11.0k
        if (node == NULL) {
3325
0
            return NJS_ERROR;
3326
0
        }
3327
3328
11.0k
        node->u.operation = NJS_VMCODE_PROPERTY_ATOM_GET;
3329
11.0k
        node->token_line = token->line;
3330
3331
11.0k
        prop_node = njs_parser_node_string(parser->vm, token,
3332
11.0k
                                           parser);
3333
11.0k
        if (prop_node == NULL) {
3334
0
            return NJS_ERROR;
3335
0
        }
3336
3337
11.0k
        prop_node->token_line = token->line;
3338
3339
11.0k
        node->left = parser->node;
3340
11.0k
        node->right = prop_node;
3341
3342
11.0k
        parser->node = node;
3343
3344
11.0k
        njs_lexer_consume_token(parser->lexer, 1);
3345
3346
11.0k
        njs_parser_next(parser, njs_parser_optional_chain_after);
3347
3348
11.0k
        return NJS_OK;
3349
15.9k
    }
3350
15.9k
}
3351
3352
3353
static njs_int_t
3354
njs_parser_optional_chain_after(njs_parser_t *parser, njs_lexer_token_t *token,
3355
    njs_queue_link_t *current)
3356
110k
{
3357
    /*
3358
     * OptionalChain Arguments
3359
     * OptionalChain [ Expression ]
3360
     * OptionalChain . IdentifierName
3361
     * OptionalChain TemplateLiteral
3362
     */
3363
3364
110k
    return njs_parser_call_or_property_after(parser, token, current,
3365
110k
                                             njs_parser_optional_chain_after);
3366
110k
}
3367
3368
3369
static njs_int_t
3370
njs_parser_new_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3371
    njs_queue_link_t *current)
3372
2.20k
{
3373
2.20k
    if (token->type != NJS_TOKEN_NEW) {
3374
1.10k
        parser->node = NULL;
3375
3376
1.10k
        njs_parser_next(parser, njs_parser_member_expression_new);
3377
3378
1.10k
        return NJS_OK;
3379
1.10k
    }
3380
3381
1.10k
    njs_lexer_consume_token(parser->lexer, 1);
3382
3383
1.10k
    return njs_parser_after(parser, current, NULL, 1,
3384
2.20k
                            njs_parser_new_expression_after);
3385
2.20k
}
3386
3387
3388
static njs_int_t
3389
njs_parser_new_expression_after(njs_parser_t *parser, njs_lexer_token_t *token,
3390
    njs_queue_link_t *current)
3391
1.10k
{
3392
1.10k
    njs_parser_node_t  *func;
3393
3394
1.10k
    if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
3395
132
        njs_parser_next(parser, njs_parser_member_expression_new_after);
3396
132
        return NJS_OK;
3397
132
    }
3398
3399
970
    func = njs_parser_create_call(parser, parser->node, 1);
3400
970
    if (func == NULL) {
3401
0
        return NJS_ERROR;
3402
0
    }
3403
3404
970
    func->token_line = token->line;
3405
970
    parser->node = func;
3406
3407
970
    return njs_parser_stack_pop(parser);
3408
970
}
3409
3410
3411
static njs_int_t
3412
njs_parser_left_hand_side_expression(njs_parser_t *parser,
3413
    njs_lexer_token_t *token, njs_queue_link_t *current)
3414
4.54M
{
3415
    /*
3416
     * NewExpression = new MemberExpression
3417
     * CallExpression = MemberExpression Arguments
3418
     * OptionalExpression = MemberExpression OptionalChain
3419
     */
3420
3421
4.54M
    switch (token->type) {
3422
    /* NewExpression or MemberExpression */
3423
9.50k
    case NJS_TOKEN_NEW:
3424
9.50k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
3425
9.50k
        if (token == NULL) {
3426
0
            return NJS_ERROR;
3427
0
        }
3428
3429
9.50k
        if (token->type == NJS_TOKEN_NEW) {
3430
1.10k
            njs_lexer_consume_token(parser->lexer, 1);
3431
3432
1.10k
            njs_parser_next(parser, njs_parser_new_expression);
3433
3434
1.10k
            return njs_parser_after(parser, current, NULL, 1,
3435
1.10k
                                    njs_parser_left_hand_side_expression_after);
3436
1.10k
        }
3437
3438
8.39k
        break;
3439
3440
    /* CallExpression or MemberExpression */
3441
8.39k
    case NJS_TOKEN_SUPER:
3442
1.06k
    case NJS_TOKEN_IMPORT:
3443
1.06k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
3444
1.06k
        if (token == NULL) {
3445
0
            return NJS_ERROR;
3446
0
        }
3447
3448
1.06k
        if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
3449
279
            njs_parser_next(parser, njs_parser_call_expression);
3450
279
            return NJS_OK;
3451
279
        }
3452
3453
784
        break;
3454
3455
4.53M
    default:
3456
4.53M
        break;
3457
4.54M
    }
3458
3459
4.54M
    njs_parser_next(parser, njs_parser_member_expression);
3460
3461
4.54M
    return njs_parser_after(parser, current, NULL, 1,
3462
4.54M
                            njs_parser_left_hand_side_expression_after);
3463
4.54M
}
3464
3465
3466
static njs_int_t
3467
njs_parser_left_hand_side_expression_after(njs_parser_t *parser,
3468
    njs_lexer_token_t *token, njs_queue_link_t *current)
3469
4.02M
{
3470
4.02M
    njs_int_t          ret;
3471
4.02M
    njs_parser_node_t  *func;
3472
3473
4.02M
    switch (token->type) {
3474
    /* CallExpression */
3475
95.4k
    case NJS_TOKEN_OPEN_PARENTHESIS:
3476
95.4k
        func = njs_parser_create_call(parser, parser->node, 0);
3477
95.4k
        if (func == NULL) {
3478
0
            return NJS_ERROR;
3479
0
        }
3480
3481
95.4k
        func->token_line = token->line;
3482
95.4k
        parser->node = func;
3483
3484
95.4k
        njs_lexer_consume_token(parser->lexer, 1);
3485
95.4k
        njs_parser_next(parser, njs_parser_arguments);
3486
3487
95.4k
        ret = njs_parser_after(parser, current, func, 1,
3488
95.4k
                               njs_parser_left_hand_side_expression_node);
3489
95.4k
        if (ret != NJS_OK) {
3490
0
            return NJS_ERROR;
3491
0
        }
3492
3493
95.4k
        return njs_parser_after(parser, current, NULL, 1,
3494
95.4k
                                njs_parser_left_hand_side_expression_optional);
3495
3496
    /* OptionalExpression */
3497
56.0k
    case NJS_TOKEN_CONDITIONAL:
3498
56.0k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
3499
56.0k
        if (token == NULL) {
3500
0
            return NJS_ERROR;
3501
0
        }
3502
3503
56.0k
        if (token->type == NJS_TOKEN_DOT
3504
13.2k
            && parser->node != NULL
3505
13.2k
            && parser->node->ctor)
3506
435
        {
3507
435
            njs_parser_syntax_error(parser,
3508
435
                                    "Optional chaining cannot be used "
3509
435
                                    "with new");
3510
435
            return NJS_DONE;
3511
435
        }
3512
3513
55.5k
        njs_parser_next(parser, njs_parser_optional_expression_after);
3514
55.5k
        break;
3515
3516
3.87M
    default:
3517
3.87M
        return njs_parser_stack_pop(parser);
3518
4.02M
    }
3519
3520
55.5k
    return NJS_OK;
3521
4.02M
}
3522
3523
3524
static njs_int_t
3525
njs_parser_left_hand_side_expression_node(njs_parser_t *parser,
3526
    njs_lexer_token_t *token, njs_queue_link_t *current)
3527
85.4k
{
3528
85.4k
    parser->node = parser->target;
3529
3530
85.4k
    return njs_parser_stack_pop(parser);
3531
85.4k
}
3532
3533
3534
static njs_int_t
3535
njs_parser_left_hand_side_expression_optional(njs_parser_t *parser,
3536
    njs_lexer_token_t *token, njs_queue_link_t *current)
3537
80.2k
{
3538
    /* OptionalExpression */
3539
80.2k
    if (token->type == NJS_TOKEN_CONDITIONAL) {
3540
405
        njs_parser_next(parser, njs_parser_optional_expression_after);
3541
405
        return NJS_OK;
3542
405
    }
3543
3544
79.8k
    njs_parser_next(parser, njs_parser_optional_chain_after);
3545
3546
79.8k
    return NJS_OK;
3547
80.2k
}
3548
3549
3550
static njs_int_t
3551
njs_parser_expression_node(njs_parser_t *parser, njs_lexer_token_t *token,
3552
    njs_queue_link_t *current, njs_token_type_t type, njs_vmcode_t operation,
3553
    njs_parser_state_func_t after)
3554
19.6M
{
3555
19.6M
    njs_parser_node_t  *node;
3556
3557
19.6M
    if (parser->target != NULL) {
3558
160k
        parser->target->right = parser->node;
3559
160k
        parser->target->right->dest = parser->target;
3560
160k
        parser->node = parser->target;
3561
160k
    }
3562
3563
19.6M
    if (token->type != type) {
3564
19.4M
        return njs_parser_stack_pop(parser);
3565
19.4M
    }
3566
3567
165k
    node = njs_parser_node_new(parser, type);
3568
165k
    if (node == NULL) {
3569
0
        return NJS_ERROR;
3570
0
    }
3571
3572
165k
    node->token_line = token->line;
3573
165k
    node->u.operation = operation;
3574
165k
    node->left = parser->node;
3575
165k
    node->left->dest = node;
3576
3577
165k
    njs_lexer_consume_token(parser->lexer, 1);
3578
3579
165k
    return njs_parser_after(parser, current, node, 1, after);
3580
165k
}
3581
3582
3583
/*
3584
 * 12.4 Update Expressions.
3585
 */
3586
static njs_int_t
3587
njs_parser_update_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3588
    njs_queue_link_t *current)
3589
4.51M
{
3590
4.51M
    njs_vmcode_t       operation;
3591
4.51M
    njs_parser_node_t  *node;
3592
3593
4.51M
    switch (token->type) {
3594
15.5k
    case NJS_TOKEN_INCREMENT:
3595
15.5k
        operation = NJS_VMCODE_INCREMENT;
3596
15.5k
        break;
3597
3598
27.5k
    case NJS_TOKEN_DECREMENT:
3599
27.5k
        operation = NJS_VMCODE_DECREMENT;
3600
27.5k
        break;
3601
3602
4.46M
    default:
3603
4.46M
        njs_parser_next(parser, njs_parser_left_hand_side_expression);
3604
3605
4.46M
        return njs_parser_after(parser, current, NULL, 1,
3606
4.51M
                                njs_parser_update_expression_post);
3607
4.51M
    }
3608
3609
43.0k
    node = njs_parser_node_new(parser, token->type);
3610
43.0k
    if (node == NULL) {
3611
0
        return NJS_ERROR;
3612
0
    }
3613
3614
43.0k
    node->token_line = token->line;
3615
43.0k
    node->u.operation = operation;
3616
3617
43.0k
    njs_lexer_consume_token(parser->lexer, 1);
3618
43.0k
    njs_parser_next(parser, njs_parser_left_hand_side_expression);
3619
3620
43.0k
    return njs_parser_after(parser, current, node, 1,
3621
43.0k
                            njs_parser_update_expression_unary);
3622
43.0k
}
3623
3624
3625
static njs_int_t
3626
njs_parser_update_expression_post(njs_parser_t *parser,
3627
    njs_lexer_token_t *token, njs_queue_link_t *current)
3628
3.95M
{
3629
3.95M
    njs_vmcode_t       operation;
3630
3.95M
    njs_token_type_t   type;
3631
3.95M
    njs_parser_node_t  *node;
3632
3633
    /* [no LineTerminator here] */
3634
3635
3.95M
    switch (token->type) {
3636
21.7k
    case NJS_TOKEN_INCREMENT:
3637
21.7k
        type = NJS_TOKEN_POST_INCREMENT;
3638
21.7k
        operation = NJS_VMCODE_POST_INCREMENT;
3639
21.7k
        break;
3640
3641
23.7k
    case NJS_TOKEN_DECREMENT:
3642
23.7k
        type = NJS_TOKEN_POST_DECREMENT;
3643
23.7k
        operation = NJS_VMCODE_POST_DECREMENT;
3644
23.7k
        break;
3645
3646
3.90M
    default:
3647
3.90M
        return njs_parser_stack_pop(parser);
3648
3.95M
    }
3649
3650
45.4k
    if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) {
3651
1.14k
        return njs_parser_stack_pop(parser);
3652
1.14k
    }
3653
3654
44.3k
    if (!njs_parser_is_lvalue(parser->node)) {
3655
302
        njs_lexer_consume_token(parser->lexer, 1);
3656
3657
302
        njs_parser_ref_error(parser,
3658
302
                             "Invalid left-hand side in postfix operation");
3659
302
        return NJS_DONE;
3660
302
    }
3661
3662
44.0k
    parser->node = njs_parser_lvalue_ref(parser->node);
3663
44.0k
    if (parser->node == NULL) {
3664
0
        return NJS_ERROR;
3665
0
    }
3666
3667
44.0k
    node = njs_parser_node_new(parser, type);
3668
44.0k
    if (node == NULL) {
3669
0
        return NJS_ERROR;
3670
0
    }
3671
3672
44.0k
    node->token_line = token->line;
3673
44.0k
    node->u.operation = operation;
3674
44.0k
    node->left = parser->node;
3675
3676
44.0k
    parser->node = node;
3677
3678
44.0k
    njs_lexer_consume_token(parser->lexer, 1);
3679
3680
44.0k
    return njs_parser_stack_pop(parser);
3681
44.0k
}
3682
3683
3684
static njs_int_t
3685
njs_parser_update_expression_unary(njs_parser_t *parser,
3686
    njs_lexer_token_t *token, njs_queue_link_t *current)
3687
42.9k
{
3688
42.9k
    if (!njs_parser_is_lvalue(parser->node)) {
3689
129
        njs_parser_ref_error(parser,
3690
129
                             "Invalid left-hand side in prefix operation");
3691
129
        return NJS_DONE;
3692
129
    }
3693
3694
42.7k
    parser->node = njs_parser_lvalue_ref(parser->node);
3695
42.7k
    if (parser->node == NULL) {
3696
0
        return NJS_ERROR;
3697
0
    }
3698
3699
42.7k
    parser->target->left = parser->node;
3700
42.7k
    parser->node = parser->target;
3701
3702
42.7k
    return njs_parser_stack_pop(parser);
3703
42.7k
}
3704
3705
3706
/*
3707
 * 12.5 Unary Operators.
3708
 */
3709
static njs_int_t
3710
njs_parser_unary_expression(njs_parser_t *parser, njs_lexer_token_t *token,
3711
    njs_queue_link_t *current)
3712
5.21M
{
3713
5.21M
    njs_vmcode_t       operation;
3714
5.21M
    njs_token_type_t   type;
3715
5.21M
    njs_parser_node_t  *node;
3716
3717
5.21M
    switch (token->type) {
3718
5.94k
    case NJS_TOKEN_DELETE:
3719
5.94k
        type = NJS_TOKEN_DELETE;
3720
5.94k
        operation = NJS_VMCODE_DELETE;
3721
5.94k
        break;
3722
3723
267
    case NJS_TOKEN_VOID:
3724
267
        type = NJS_TOKEN_VOID;
3725
267
        operation = NJS_VMCODE_VOID;
3726
267
        break;
3727
3728
5.20k
    case NJS_TOKEN_TYPEOF:
3729
5.20k
        type = NJS_TOKEN_TYPEOF;
3730
5.20k
        operation = NJS_VMCODE_TYPEOF;
3731
5.20k
        break;
3732
3733
40.9k
    case NJS_TOKEN_ADDITION:
3734
40.9k
        type = NJS_TOKEN_UNARY_PLUS;
3735
40.9k
        operation = NJS_VMCODE_UNARY_PLUS;
3736
40.9k
        break;
3737
3738
40.6k
    case NJS_TOKEN_SUBTRACTION:
3739
40.6k
        type = NJS_TOKEN_UNARY_NEGATION;
3740
40.6k
        operation = NJS_VMCODE_UNARY_NEGATION;
3741
40.6k
        break;
3742
3743
22.6k
    case NJS_TOKEN_BITWISE_NOT:
3744
22.6k
        type = NJS_TOKEN_BITWISE_NOT;
3745
22.6k
        operation = NJS_VMCODE_BITWISE_NOT;
3746
22.6k
        break;
3747
3748
579k
    case NJS_TOKEN_LOGICAL_NOT:
3749
579k
        type = NJS_TOKEN_LOGICAL_NOT;
3750
579k
        operation = NJS_VMCODE_LOGICAL_NOT;
3751
579k
        break;
3752
3753
    /* AwaitExpression */
3754
3.50k
    case NJS_TOKEN_AWAIT:
3755
3.50k
        njs_parser_next(parser, njs_parser_await);
3756
3.50k
        return NJS_OK;
3757
3758
4.51M
    default:
3759
4.51M
        njs_parser_next(parser, njs_parser_update_expression);
3760
3761
4.51M
        return njs_parser_after(parser, current, parser->target, 1,
3762
5.21M
                                njs_parser_unary_expression_after);
3763
5.21M
    }
3764
3765
695k
    node = njs_parser_node_new(parser, type);
3766
695k
    if (node == NULL) {
3767
0
        return NJS_ERROR;
3768
0
    }
3769
3770
695k
    node->token_line = token->line;
3771
695k
    node->u.operation = operation;
3772
3773
695k
    parser->target = node;
3774
3775
695k
    njs_lexer_consume_token(parser->lexer, 1);
3776
3777
695k
    return njs_parser_after(parser, current, node, 1,
3778
695k
                            njs_parser_unary_expression_next);
3779
695k
}
3780
3781
3782
static njs_int_t
3783
njs_parser_unary_expression_after(njs_parser_t *parser,
3784
    njs_lexer_token_t *token, njs_queue_link_t *current)
3785
3.97M
{
3786
3.97M
    if (parser->target == NULL &&
3787
3.86M
        token->type == NJS_TOKEN_EXPONENTIATION)
3788
4.25k
    {
3789
4.25k
        return njs_parser_exponentiation_expression_match(parser, token,
3790
4.25k
                                                          current);
3791
4.25k
    }
3792
3793
3.97M
    return njs_parser_stack_pop(parser);
3794
3.97M
}
3795
3796
3797
static njs_int_t
3798
njs_parser_unary_expression_next(njs_parser_t *parser,
3799
    njs_lexer_token_t *token, njs_queue_link_t *current)
3800
688k
{
3801
688k
    double             num;
3802
688k
    njs_token_type_t   type;
3803
688k
    njs_parser_node_t  *node, *prop;
3804
3805
688k
    type = parser->target->token_type;
3806
688k
    node = parser->node;
3807
3808
688k
    if (token->type == NJS_TOKEN_EXPONENTIATION) {
3809
257
        njs_parser_syntax_error(parser, "Either left-hand side or entire "
3810
257
                                "exponentiation must be parenthesized");
3811
257
        return NJS_DONE;
3812
257
    }
3813
3814
688k
    if (node->token_type == NJS_TOKEN_NUMBER) {
3815
27.2k
        if (type == NJS_TOKEN_UNARY_PLUS) {
3816
            /* Skip the unary plus of number. */
3817
3.60k
            return njs_parser_stack_pop(parser);
3818
3.60k
        }
3819
3820
23.6k
        if (type == NJS_TOKEN_UNARY_NEGATION) {
3821
            /* Optimization of common negative number. */
3822
10.0k
            num = -njs_number(&node->u.value);
3823
10.0k
            njs_set_number(&node->u.value, num);
3824
3825
10.0k
            return njs_parser_stack_pop(parser);
3826
10.0k
        }
3827
23.6k
    }
3828
3829
674k
    if (type == NJS_TOKEN_DELETE) {
3830
5.79k
        switch (node->token_type) {
3831
3832
1.17k
        case NJS_TOKEN_PROPERTY:
3833
1.17k
        case NJS_TOKEN_PROPERTY_REF:
3834
1.17k
            node = njs_parser_property_ref(node);
3835
1.17k
            if (node == NULL) {
3836
0
                return NJS_ERROR;
3837
0
            }
3838
3839
1.17k
            node->token_type = NJS_TOKEN_PROPERTY_DELETE;
3840
1.17k
            node->u.operation = NJS_VMCODE_PROPERTY_DELETE;
3841
3842
1.17k
            return njs_parser_stack_pop(parser);
3843
3844
2.10k
        case NJS_TOKEN_OPTIONAL_CHAIN:
3845
2.10k
            prop = njs_parser_optional_chain_target_property(node);
3846
2.10k
            if (prop != NULL) {
3847
759
                prop->token_type = NJS_TOKEN_PROPERTY_DELETE;
3848
759
                prop->u.operation = NJS_VMCODE_PROPERTY_DELETE;
3849
759
            }
3850
3851
2.10k
            break;
3852
3853
257
        case NJS_TOKEN_NAME:
3854
257
            njs_parser_syntax_error(parser,
3855
257
                                    "Delete of an unqualified identifier");
3856
257
            return NJS_DONE;
3857
3858
2.26k
        default:
3859
2.26k
            break;
3860
5.79k
        }
3861
5.79k
    }
3862
3863
673k
    if (type == NJS_TOKEN_TYPEOF && node->token_type == NJS_TOKEN_NAME) {
3864
3.10k
        node->u.reference.type = NJS_TYPEOF;
3865
3.10k
    }
3866
3867
673k
    parser->target->left = parser->node;
3868
673k
    parser->target->left->dest = parser->target;
3869
673k
    parser->node = parser->target;
3870
3871
673k
    return njs_parser_stack_pop(parser);
3872
674k
}
3873
3874
3875
static njs_int_t
3876
njs_parser_await(njs_parser_t *parser, njs_lexer_token_t *token,
3877
    njs_queue_link_t *current)
3878
3.50k
{
3879
3.50k
    njs_parser_node_t   *node;
3880
3881
3.50k
    if (!njs_function_scope(parser->scope)->async) {
3882
1.02k
        njs_parser_syntax_error(parser,
3883
1.02k
                                "await is only valid in async functions");
3884
1.02k
        return NJS_ERROR;
3885
1.02k
    }
3886
3887
2.48k
    node = njs_parser_node_new(parser, NJS_TOKEN_AWAIT);
3888
2.48k
    if (njs_slow_path(node == NULL)) {
3889
0
        return NJS_ERROR;
3890
0
    }
3891
3892
2.48k
    node->token_line = token->line;
3893
3894
2.48k
    njs_lexer_consume_token(parser->lexer, 1);
3895
3896
2.48k
    parser->node = NULL;
3897
3898
2.48k
    njs_parser_next(parser, njs_parser_unary_expression);
3899
3900
2.48k
    return njs_parser_after(parser, current, node, 0,
3901
2.48k
                            njs_parser_await_after);
3902
2.48k
}
3903
3904
3905
static njs_int_t
3906
njs_parser_await_after(njs_parser_t *parser, njs_lexer_token_t *token,
3907
    njs_queue_link_t *current)
3908
2.47k
{
3909
2.47k
    if (parser->ret != NJS_OK) {
3910
0
        return njs_parser_failed(parser);
3911
0
    }
3912
3913
2.47k
    return njs_parser_right_link_pop(parser);
3914
2.47k
}
3915
3916
3917
/*
3918
 * 12.6 Exponentiation Operator.
3919
 */
3920
static njs_int_t
3921
njs_parser_exponentiation_expression(njs_parser_t *parser,
3922
    njs_lexer_token_t *token, njs_queue_link_t *current)
3923
4.53M
{
3924
4.53M
    parser->target = NULL;
3925
3926
4.53M
    if (parser->use_lhs == 0) {
3927
4.51M
        njs_parser_next(parser, njs_parser_unary_expression);
3928
3929
        /* For UpdateExpression, see njs_parser_unary_expression_after. */
3930
3931
4.51M
        return NJS_OK;
3932
4.51M
    } else {
3933
17.1k
        parser->use_lhs = 0;
3934
3935
17.1k
        return njs_parser_update_expression_post(parser, token, current);
3936
17.1k
    }
3937
4.53M
}
3938
3939
3940
static njs_int_t
3941
njs_parser_exponentiation_expression_match(njs_parser_t *parser,
3942
    njs_lexer_token_t *token, njs_queue_link_t *current)
3943
8.38k
{
3944
8.38k
    njs_parser_node_t  *node;
3945
3946
8.38k
    if (parser->target != NULL) {
3947
4.12k
        parser->target->right = parser->node;
3948
4.12k
        parser->target->right->dest = parser->target;
3949
4.12k
        parser->node = parser->target;
3950
3951
4.12k
        return njs_parser_stack_pop(parser);
3952
4.12k
    }
3953
3954
4.25k
    if (token->type != NJS_TOKEN_EXPONENTIATION) {
3955
0
        return njs_parser_stack_pop(parser);
3956
0
    }
3957
3958
4.25k
    node = njs_parser_node_new(parser, token->type);
3959
4.25k
    if (node == NULL) {
3960
0
        return NJS_ERROR;
3961
0
    }
3962
3963
4.25k
    node->token_line = token->line;
3964
4.25k
    node->u.operation = NJS_VMCODE_EXPONENTIATION;
3965
4.25k
    node->left = parser->node;
3966
4.25k
    node->left->dest = node;
3967
3968
4.25k
    njs_lexer_consume_token(parser->lexer, 1);
3969
3970
4.25k
    njs_parser_next(parser, njs_parser_exponentiation_expression);
3971
3972
4.25k
    return njs_parser_after(parser, current, node, 1,
3973
4.25k
                            njs_parser_exponentiation_expression_match);
3974
4.25k
}
3975
3976
3977
/*
3978
 * 12.7 Multiplicative Operators.
3979
 */
3980
static njs_int_t
3981
njs_parser_multiplicative_expression(njs_parser_t *parser,
3982
    njs_lexer_token_t *token, njs_queue_link_t *current)
3983
4.42M
{
3984
4.42M
    njs_parser_next(parser, njs_parser_exponentiation_expression);
3985
3986
4.42M
    return njs_parser_after(parser, current, NULL, 1,
3987
4.42M
                            njs_parser_multiplicative_expression_match);
3988
4.42M
}
3989
3990
3991
static njs_int_t
3992
njs_parser_multiplicative_expression_match(njs_parser_t *parser,
3993
    njs_lexer_token_t *token, njs_queue_link_t *current)
3994
3.99M
{
3995
3.99M
    njs_vmcode_t       operation;
3996
3.99M
    njs_parser_node_t  *node;
3997
3998
3.99M
    if (parser->target != NULL) {
3999
94.7k
        parser->target->right = parser->node;
4000
94.7k
        parser->target->right->dest = parser->target;
4001
94.7k
        parser->node = parser->target;
4002
94.7k
    }
4003
4004
3.99M
    switch (token->type) {
4005
27.3k
    case NJS_TOKEN_MULTIPLICATION:
4006
27.3k
        operation = NJS_VMCODE_MULTIPLICATION;
4007
27.3k
        break;
4008
4009
53.9k
    case NJS_TOKEN_DIVISION:
4010
53.9k
        operation = NJS_VMCODE_DIVISION;
4011
53.9k
        break;
4012
4013
18.8k
    case NJS_TOKEN_REMAINDER:
4014
18.8k
        operation = NJS_VMCODE_REMAINDER;
4015
18.8k
        break;
4016
4017
3.89M
    default:
4018
3.89M
        return njs_parser_stack_pop(parser);
4019
3.99M
    }
4020
4021
100k
    node = njs_parser_node_new(parser, token->type);
4022
100k
    if (node == NULL) {
4023
0
        return NJS_ERROR;
4024
0
    }
4025
4026
100k
    node->token_line = token->line;
4027
100k
    node->u.operation = operation;
4028
100k
    node->left = parser->node;
4029
100k
    node->left->dest = node;
4030
4031
100k
    njs_lexer_consume_token(parser->lexer, 1);
4032
4033
100k
    njs_parser_next(parser, njs_parser_exponentiation_expression);
4034
4035
100k
    return njs_parser_after(parser, current, node, 1,
4036
100k
                            njs_parser_multiplicative_expression_match);
4037
100k
}
4038
4039
4040
/*
4041
 * 12.8 Additive Operators.
4042
 */
4043
static njs_int_t
4044
njs_parser_additive_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4045
    njs_queue_link_t *current)
4046
4.24M
{
4047
4.24M
    njs_parser_next(parser, njs_parser_multiplicative_expression);
4048
4049
4.24M
    return njs_parser_after(parser, current, NULL, 1,
4050
4.24M
                            njs_parser_additive_expression_match);
4051
4.24M
}
4052
4053
4054
static njs_int_t
4055
njs_parser_additive_expression_match(njs_parser_t *parser,
4056
    njs_lexer_token_t *token, njs_queue_link_t *current)
4057
3.89M
{
4058
3.89M
    njs_vmcode_t       operation;
4059
3.89M
    njs_parser_node_t  *node;
4060
4061
3.89M
    if (parser->target != NULL) {
4062
176k
        parser->target->right = parser->node;
4063
176k
        parser->target->right->dest = parser->target;
4064
176k
        parser->node = parser->target;
4065
176k
    }
4066
4067
3.89M
    switch (token->type) {
4068
95.8k
    case NJS_TOKEN_ADDITION:
4069
95.8k
        operation = NJS_VMCODE_ADDITION;
4070
95.8k
        break;
4071
4072
90.4k
    case NJS_TOKEN_SUBTRACTION:
4073
90.4k
        operation = NJS_VMCODE_SUBTRACTION;
4074
90.4k
        break;
4075
4076
3.70M
    default:
4077
3.70M
        return njs_parser_stack_pop(parser);
4078
3.89M
    }
4079
4080
186k
    node = njs_parser_node_new(parser, token->type);
4081
186k
    if (node == NULL) {
4082
0
        return NJS_ERROR;
4083
0
    }
4084
4085
186k
    node->token_line = token->line;
4086
186k
    node->u.operation = operation;
4087
186k
    node->left = parser->node;
4088
186k
    node->left->dest = node;
4089
4090
186k
    njs_lexer_consume_token(parser->lexer, 1);
4091
4092
186k
    njs_parser_next(parser, njs_parser_multiplicative_expression);
4093
4094
186k
    return njs_parser_after(parser, current, node, 1,
4095
186k
                            njs_parser_additive_expression_match);
4096
186k
}
4097
4098
4099
/*
4100
 * 12.9 Bitwise Shift Operators
4101
 */
4102
static njs_int_t
4103
njs_parser_shift_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4104
    njs_queue_link_t *current)
4105
4.22M
{
4106
4.22M
    njs_parser_next(parser, njs_parser_additive_expression);
4107
4108
4.22M
    return njs_parser_after(parser, current, NULL, 1,
4109
4.22M
                            njs_parser_shift_expression_match);
4110
4.22M
}
4111
4112
4113
static njs_int_t
4114
njs_parser_shift_expression_match(njs_parser_t *parser,
4115
    njs_lexer_token_t *token, njs_queue_link_t *current)
4116
3.70M
{
4117
3.70M
    njs_vmcode_t       operation;
4118
3.70M
    njs_parser_node_t  *node;
4119
4120
3.70M
    if (parser->target != NULL) {
4121
13.6k
        parser->target->right = parser->node;
4122
13.6k
        parser->target->right->dest = parser->target;
4123
13.6k
        parser->node = parser->target;
4124
13.6k
    }
4125
4126
3.70M
    switch (token->type) {
4127
12.4k
    case NJS_TOKEN_RIGHT_SHIFT:
4128
12.4k
        operation = NJS_VMCODE_RIGHT_SHIFT;
4129
12.4k
        break;
4130
4131
706
    case NJS_TOKEN_LEFT_SHIFT:
4132
706
        operation = NJS_VMCODE_LEFT_SHIFT;
4133
706
        break;
4134
4135
610
    case NJS_TOKEN_UNSIGNED_RIGHT_SHIFT:
4136
610
        operation = NJS_VMCODE_UNSIGNED_RIGHT_SHIFT;
4137
610
        break;
4138
4139
3.69M
    default:
4140
3.69M
        return njs_parser_stack_pop(parser);
4141
3.70M
    }
4142
4143
13.8k
    node = njs_parser_node_new(parser, token->type);
4144
13.8k
    if (node == NULL) {
4145
0
        return NJS_ERROR;
4146
0
    }
4147
4148
13.8k
    node->token_line = token->line;
4149
13.8k
    node->u.operation = operation;
4150
13.8k
    node->left = parser->node;
4151
13.8k
    node->left->dest = node;
4152
4153
13.8k
    njs_lexer_consume_token(parser->lexer, 1);
4154
4155
13.8k
    njs_parser_next(parser, njs_parser_additive_expression);
4156
4157
13.8k
    return njs_parser_after(parser, current, node, 1,
4158
13.8k
                            njs_parser_shift_expression_match);
4159
13.8k
}
4160
4161
4162
/*
4163
 * 12.10 Relational Operators.
4164
 */
4165
static njs_int_t
4166
njs_parser_relational_expression(njs_parser_t *parser,
4167
    njs_lexer_token_t *token, njs_queue_link_t *current)
4168
4.17M
{
4169
4.17M
    njs_parser_next(parser, njs_parser_shift_expression);
4170
4171
4.17M
    return njs_parser_after(parser, current, NULL, 1,
4172
4.17M
                            njs_parser_relational_expression_match);
4173
4.17M
}
4174
4175
4176
static njs_int_t
4177
njs_parser_relational_expression_match(njs_parser_t *parser,
4178
    njs_lexer_token_t *token, njs_queue_link_t *current)
4179
3.69M
{
4180
3.69M
    njs_vmcode_t       operation;
4181
3.69M
    njs_parser_node_t  *node;
4182
4183
3.69M
    if (parser->target != NULL) {
4184
52.6k
        parser->target->right = parser->node;
4185
52.6k
        parser->target->right->dest = parser->target;
4186
52.6k
        parser->node = parser->target;
4187
52.6k
    }
4188
4189
3.69M
    switch (token->type) {
4190
22.9k
    case NJS_TOKEN_LESS:
4191
22.9k
        operation = NJS_VMCODE_LESS;
4192
22.9k
        break;
4193
4194
19.2k
    case NJS_TOKEN_GREATER:
4195
19.2k
        operation = NJS_VMCODE_GREATER;
4196
19.2k
        break;
4197
4198
1.35k
    case NJS_TOKEN_LESS_OR_EQUAL:
4199
1.35k
        operation = NJS_VMCODE_LESS_OR_EQUAL;
4200
1.35k
        break;
4201
4202
390
    case NJS_TOKEN_GREATER_OR_EQUAL:
4203
390
        operation = NJS_VMCODE_GREATER_OR_EQUAL;
4204
390
        break;
4205
4206
1.14k
    case NJS_TOKEN_INSTANCEOF:
4207
1.14k
        operation = NJS_VMCODE_INSTANCE_OF;
4208
1.14k
        break;
4209
4210
9.05k
    case NJS_TOKEN_IN:
4211
9.05k
        if (njs_lexer_in_fail_get(parser->lexer)) {
4212
131
            njs_parser_syntax_error(parser, "Invalid left-hand side in for-loop");
4213
131
            return NJS_ERROR;
4214
131
        }
4215
8.92k
        operation = NJS_VMCODE_PROPERTY_IN;
4216
8.92k
        break;
4217
4218
3.63M
    default:
4219
3.63M
        return njs_parser_stack_pop(parser);
4220
3.69M
    }
4221
4222
53.9k
    node = njs_parser_node_new(parser, token->type);
4223
53.9k
    if (node == NULL) {
4224
0
        return NJS_ERROR;
4225
0
    }
4226
4227
53.9k
    node->token_line = token->line;
4228
53.9k
    node->u.operation = operation;
4229
53.9k
    node->left = parser->node;
4230
53.9k
    node->left->dest = node;
4231
4232
53.9k
    njs_lexer_consume_token(parser->lexer, 1);
4233
4234
53.9k
    njs_parser_next(parser, njs_parser_shift_expression);
4235
4236
53.9k
    return njs_parser_after(parser, current, node, 1,
4237
53.9k
                            njs_parser_relational_expression_match);
4238
53.9k
}
4239
4240
4241
/*
4242
 * 12.11 Equality Operators.
4243
 */
4244
static njs_int_t
4245
njs_parser_equality_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4246
    njs_queue_link_t *current)
4247
4.16M
{
4248
4.16M
    njs_parser_next(parser, njs_parser_relational_expression);
4249
4250
4.16M
    return njs_parser_after(parser, current, NULL, 1,
4251
4.16M
                            njs_parser_equality_expression_match);
4252
4.16M
}
4253
4254
4255
static njs_int_t
4256
njs_parser_equality_expression_match(njs_parser_t *parser,
4257
    njs_lexer_token_t *token, njs_queue_link_t *current)
4258
3.63M
{
4259
3.63M
    njs_vmcode_t       operation;
4260
3.63M
    njs_parser_node_t  *node;
4261
4262
3.63M
    if (parser->target != NULL) {
4263
10.8k
        parser->target->right = parser->node;
4264
10.8k
        parser->target->right->dest = parser->target;
4265
10.8k
        parser->node = parser->target;
4266
10.8k
    }
4267
4268
3.63M
    switch (token->type) {
4269
6.80k
    case NJS_TOKEN_EQUAL:
4270
6.80k
        operation = NJS_VMCODE_EQUAL;
4271
6.80k
        break;
4272
4273
385
    case NJS_TOKEN_NOT_EQUAL:
4274
385
        operation = NJS_VMCODE_NOT_EQUAL;
4275
385
        break;
4276
4277
1.66k
    case NJS_TOKEN_STRICT_EQUAL:
4278
1.66k
        operation = NJS_VMCODE_STRICT_EQUAL;
4279
1.66k
        break;
4280
4281
2.74k
    case NJS_TOKEN_STRICT_NOT_EQUAL:
4282
2.74k
        operation = NJS_VMCODE_STRICT_NOT_EQUAL;
4283
2.74k
        break;
4284
4285
3.62M
    default:
4286
3.62M
        return njs_parser_stack_pop(parser);
4287
3.63M
    }
4288
4289
11.6k
    node = njs_parser_node_new(parser, token->type);
4290
11.6k
    if (node == NULL) {
4291
0
        return NJS_ERROR;
4292
0
    }
4293
4294
11.6k
    node->token_line = token->line;
4295
11.6k
    node->u.operation = operation;
4296
11.6k
    node->left = parser->node;
4297
11.6k
    node->left->dest = node;
4298
4299
11.6k
    njs_lexer_consume_token(parser->lexer, 1);
4300
4301
11.6k
    njs_parser_next(parser, njs_parser_relational_expression);
4302
4303
11.6k
    return njs_parser_after(parser, current, node, 1,
4304
11.6k
                            njs_parser_equality_expression_match);
4305
11.6k
}
4306
4307
4308
/*
4309
 * 12.12 Binary Bitwise Operators.
4310
 */
4311
static njs_int_t
4312
njs_parser_bitwise_AND_expression(njs_parser_t *parser,
4313
    njs_lexer_token_t *token, njs_queue_link_t *current)
4314
4.13M
{
4315
4.13M
    njs_parser_next(parser, njs_parser_equality_expression);
4316
4317
4.13M
    return njs_parser_after(parser, current, NULL, 1,
4318
4.13M
                            njs_parser_bitwise_AND_expression_and);
4319
4.13M
}
4320
4321
4322
static njs_int_t
4323
njs_parser_bitwise_AND_expression_and(njs_parser_t *parser,
4324
    njs_lexer_token_t *token, njs_queue_link_t *current)
4325
3.62M
{
4326
3.62M
    njs_parser_next(parser, njs_parser_equality_expression);
4327
4328
3.62M
    return njs_parser_expression_node(parser, token, current,
4329
3.62M
                                       NJS_TOKEN_BITWISE_AND,
4330
3.62M
                                       NJS_VMCODE_BITWISE_AND,
4331
3.62M
                                       njs_parser_bitwise_AND_expression_and);
4332
3.62M
}
4333
4334
4335
static njs_int_t
4336
njs_parser_bitwise_XOR_expression(njs_parser_t *parser,
4337
    njs_lexer_token_t *token, njs_queue_link_t *current)
4338
4.10M
{
4339
4.10M
    njs_parser_next(parser, njs_parser_bitwise_AND_expression);
4340
4341
4.10M
    return njs_parser_after(parser, current, NULL, 1,
4342
4.10M
                            njs_parser_bitwise_XOR_expression_xor);
4343
4.10M
}
4344
4345
4346
static njs_int_t
4347
njs_parser_bitwise_XOR_expression_xor(njs_parser_t *parser,
4348
    njs_lexer_token_t *token, njs_queue_link_t *current)
4349
3.59M
{
4350
3.59M
    njs_parser_next(parser, njs_parser_bitwise_AND_expression);
4351
4352
3.59M
    return njs_parser_expression_node(parser, token, current,
4353
3.59M
                                       NJS_TOKEN_BITWISE_XOR,
4354
3.59M
                                       NJS_VMCODE_BITWISE_XOR,
4355
3.59M
                                       njs_parser_bitwise_XOR_expression_xor);
4356
3.59M
}
4357
4358
4359
static njs_int_t
4360
njs_parser_bitwise_OR_expression(njs_parser_t *parser,
4361
    njs_lexer_token_t *token, njs_queue_link_t *current)
4362
4.05M
{
4363
4.05M
    njs_parser_next(parser, njs_parser_bitwise_XOR_expression);
4364
4365
4.05M
    return njs_parser_after(parser, current, NULL, 1,
4366
4.05M
                            njs_parser_bitwise_OR_expression_or);
4367
4.05M
}
4368
4369
4370
static njs_int_t
4371
njs_parser_bitwise_OR_expression_or(njs_parser_t *parser,
4372
    njs_lexer_token_t *token, njs_queue_link_t *current)
4373
3.56M
{
4374
3.56M
    njs_parser_next(parser, njs_parser_bitwise_XOR_expression);
4375
4376
3.56M
    return njs_parser_expression_node(parser, token, current,
4377
3.56M
                                       NJS_TOKEN_BITWISE_OR,
4378
3.56M
                                       NJS_VMCODE_BITWISE_OR,
4379
3.56M
                                       njs_parser_bitwise_OR_expression_or);
4380
3.56M
}
4381
4382
4383
/*
4384
 * 12.13 Binary Logical Operators.
4385
 */
4386
static njs_int_t
4387
njs_parser_logical_AND_expression(njs_parser_t *parser,
4388
    njs_lexer_token_t *token, njs_queue_link_t *current)
4389
4.03M
{
4390
4.03M
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4391
4392
4.03M
    return njs_parser_after(parser, current, NULL, 1,
4393
4.03M
                            njs_parser_logical_AND_expression_and);
4394
4.03M
}
4395
4396
4397
static njs_int_t
4398
njs_parser_logical_AND_expression_and(njs_parser_t *parser,
4399
    njs_lexer_token_t *token, njs_queue_link_t *current)
4400
3.51M
{
4401
3.51M
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4402
4403
3.51M
    return njs_parser_expression_node(parser, token, current,
4404
3.51M
                                       NJS_TOKEN_LOGICAL_AND,
4405
3.51M
                                       NJS_VMCODE_TEST_IF_FALSE,
4406
3.51M
                                       njs_parser_logical_AND_expression_and);
4407
3.51M
}
4408
4409
4410
static njs_int_t
4411
njs_parser_logical_OR_expression(njs_parser_t *parser,
4412
    njs_lexer_token_t *token, njs_queue_link_t *current)
4413
4.03M
{
4414
4.03M
    njs_parser_next(parser, njs_parser_logical_AND_expression);
4415
4416
4.03M
    return njs_parser_after(parser, current, NULL, 1,
4417
4.03M
                            njs_parser_logical_OR_expression_or);
4418
4.03M
}
4419
4420
4421
static njs_int_t
4422
njs_parser_logical_OR_expression_or(njs_parser_t *parser,
4423
    njs_lexer_token_t *token, njs_queue_link_t *current)
4424
3.50M
{
4425
3.50M
    njs_parser_next(parser, njs_parser_logical_AND_expression);
4426
4427
3.50M
    return njs_parser_expression_node(parser, token, current,
4428
3.50M
                                       NJS_TOKEN_LOGICAL_OR,
4429
3.50M
                                       NJS_VMCODE_TEST_IF_TRUE,
4430
3.50M
                                       njs_parser_logical_OR_expression_or);
4431
3.50M
}
4432
4433
4434
static njs_int_t
4435
njs_parser_coalesce_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4436
    njs_queue_link_t *current)
4437
3.50M
{
4438
3.50M
    njs_token_type_t   type;
4439
3.50M
    njs_parser_node_t  *node;
4440
4441
3.50M
    node = parser->node;
4442
4443
3.50M
    if (parser->target != NULL) {
4444
2.65k
        parser->target->right = node;
4445
2.65k
        parser->target->right->dest = parser->target;
4446
2.65k
        parser->node = parser->target;
4447
2.65k
    }
4448
4449
3.50M
    if (token->type != NJS_TOKEN_COALESCE) {
4450
3.49M
        return njs_parser_stack_pop(parser);
4451
3.49M
    }
4452
4453
4.65k
    type = node->token_type;
4454
4455
4.65k
    if (parser->lexer->prev_type != NJS_TOKEN_CLOSE_PARENTHESIS
4456
4.64k
        && (type == NJS_TOKEN_LOGICAL_OR || type == NJS_TOKEN_LOGICAL_AND))
4457
1.95k
    {
4458
1.95k
        return njs_parser_failed(parser);
4459
1.95k
    }
4460
4461
2.69k
    node = njs_parser_node_new(parser, NJS_TOKEN_COALESCE);
4462
2.69k
    if (node == NULL) {
4463
0
        return NJS_ERROR;
4464
0
    }
4465
4466
2.69k
    node->token_line = token->line;
4467
2.69k
    node->u.operation = NJS_VMCODE_COALESCE;
4468
2.69k
    node->left = parser->node;
4469
2.69k
    node->left->dest = node;
4470
4471
2.69k
    njs_lexer_consume_token(parser->lexer, 1);
4472
2.69k
    njs_parser_next(parser, njs_parser_bitwise_OR_expression);
4473
4474
2.69k
    return njs_parser_after(parser, current, node, 1,
4475
2.69k
                            njs_parser_coalesce_expression);
4476
2.69k
}
4477
4478
4479
static njs_int_t
4480
njs_parser_short_circuit_expression(njs_parser_t *parser,
4481
    njs_lexer_token_t *token, njs_queue_link_t *current)
4482
4.03M
{
4483
4.03M
    njs_parser_next(parser, njs_parser_logical_OR_expression);
4484
4485
4.03M
    return njs_parser_after(parser, current, NULL, 1,
4486
4.03M
                            njs_parser_coalesce_expression);
4487
4.03M
}
4488
4489
4490
/*
4491
 * 12.14 Conditional Operator ( ? : ).
4492
 */
4493
static njs_int_t
4494
njs_parser_conditional_expression(njs_parser_t *parser,
4495
    njs_lexer_token_t *token, njs_queue_link_t *current)
4496
4.03M
{
4497
4.03M
    njs_parser_next(parser, njs_parser_short_circuit_expression);
4498
4499
4.03M
    return njs_parser_after(parser, current, NULL, 1,
4500
4.03M
                            njs_parser_conditional_question_mark);
4501
4.03M
}
4502
4503
4504
static njs_int_t
4505
njs_parser_conditional_question_mark(njs_parser_t *parser,
4506
    njs_lexer_token_t *token, njs_queue_link_t *current)
4507
3.49M
{
4508
3.49M
    njs_parser_node_t  *node, *cond;
4509
4510
3.49M
    if (token->type != NJS_TOKEN_CONDITIONAL) {
4511
3.45M
        return njs_parser_stack_pop(parser);
4512
3.45M
    }
4513
4514
43.1k
    cond = njs_parser_node_new(parser, NJS_TOKEN_CONDITIONAL);
4515
43.1k
    if (cond == NULL) {
4516
0
        return NJS_ERROR;
4517
0
    }
4518
4519
43.1k
    cond->token_line = token->line;
4520
43.1k
    cond->left = parser->node;
4521
4522
43.1k
    node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING);
4523
43.1k
    if (node == NULL) {
4524
0
        return NJS_ERROR;
4525
0
    }
4526
4527
43.1k
    node->token_line = token->line;
4528
43.1k
    cond->right = node;
4529
4530
43.1k
    njs_lexer_consume_token(parser->lexer, 1);
4531
4532
43.1k
    if (njs_lexer_in_stack_push(parser->lexer) != NJS_OK) {
4533
0
        return NJS_ERROR;
4534
0
    }
4535
4536
43.1k
    njs_parser_next(parser, njs_parser_assignment_expression);
4537
4538
43.1k
    return njs_parser_after(parser, current, cond, 1,
4539
43.1k
                            njs_parser_conditional_colon);
4540
43.1k
}
4541
4542
4543
static njs_int_t
4544
njs_parser_conditional_colon(njs_parser_t *parser, njs_lexer_token_t *token,
4545
    njs_queue_link_t *current)
4546
39.2k
{
4547
39.2k
    njs_parser_node_t  *node;
4548
4549
39.2k
    if (token->type != NJS_TOKEN_COLON) {
4550
3.33k
        return njs_parser_failed(parser);
4551
3.33k
    }
4552
4553
35.9k
    njs_lexer_in_stack_pop(parser->lexer);
4554
4555
35.9k
    njs_lexer_consume_token(parser->lexer, 1);
4556
4557
35.9k
    node = parser->target->right;
4558
4559
35.9k
    node->left = parser->node;
4560
35.9k
    node->left->dest = parser->target;
4561
4562
35.9k
    njs_parser_next(parser, njs_parser_assignment_expression);
4563
4564
35.9k
    return njs_parser_after(parser, current, parser->target, 1,
4565
39.2k
                            njs_parser_conditional_colon_after);
4566
39.2k
}
4567
4568
4569
static njs_int_t
4570
njs_parser_conditional_colon_after(njs_parser_t *parser,
4571
    njs_lexer_token_t *token, njs_queue_link_t *current)
4572
35.1k
{
4573
35.1k
    njs_parser_node_t  *node;
4574
4575
35.1k
    node = parser->target->right;
4576
4577
35.1k
    node->right = parser->node;
4578
35.1k
    node->right->dest = parser->target;
4579
4580
35.1k
    parser->node = parser->target;
4581
4582
35.1k
    return njs_parser_stack_pop(parser);
4583
35.1k
}
4584
4585
4586
/*
4587
 * 12.15 Assignment Operators.
4588
 */
4589
static njs_int_t
4590
njs_parser_assignment_expression(njs_parser_t *parser,
4591
    njs_lexer_token_t *token, njs_queue_link_t *current)
4592
4.40M
{
4593
4.40M
    njs_int_t  ret;
4594
4595
4.40M
    if (!parser->use_lhs) {
4596
4.38M
        ret = njs_parser_match_arrow_expression(parser, token);
4597
4.38M
        if (ret == NJS_OK) {
4598
370k
            njs_parser_next(parser, njs_parser_arrow_function);
4599
4600
370k
            return NJS_OK;
4601
4602
4.01M
        } else if (ret == NJS_ERROR) {
4603
0
            return NJS_ERROR;
4604
0
        }
4605
4.38M
    }
4606
4607
4.03M
    njs_parser_next(parser, njs_parser_conditional_expression);
4608
4609
4.03M
    return njs_parser_after(parser, current, NULL, 1,
4610
4.40M
                            njs_parser_assignment_expression_after);
4611
4.40M
}
4612
4613
4614
/*
4615
 * TODO: this function is a crutch.
4616
 * See NJS_TOKEN_OPEN_PARENTHESIS in njs_parser_primary_expression_test.
4617
 * and look CoverParenthesizedExpressionAndArrowParameterList in spec.
4618
 */
4619
static njs_int_t
4620
njs_parser_match_arrow_expression(njs_parser_t *parser,
4621
    njs_lexer_token_t *token)
4622
4.42M
{
4623
4.42M
    njs_bool_t  rest_parameters;
4624
4625
4.42M
    if (token->type == NJS_TOKEN_ASYNC) {
4626
7.61k
        token = njs_lexer_peek_token(parser->lexer, token, 1);
4627
7.61k
        if (token == NULL) {
4628
0
            return NJS_ERROR;
4629
0
        }
4630
7.61k
    }
4631
4632
4.42M
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS
4633
4.01M
        && !njs_lexer_token_is_binding_identifier(token))
4634
1.66M
    {
4635
1.66M
        return NJS_DECLINED;
4636
1.66M
    }
4637
4638
2.75M
    if (njs_lexer_token_is_binding_identifier(token)) {
4639
2.35M
        goto arrow;
4640
2.35M
    }
4641
4642
401k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
4643
401k
    if (token == NULL) {
4644
0
        return NJS_ERROR;
4645
0
    }
4646
4647
401k
    rest_parameters = 0;
4648
4649
457k
    while (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
4650
4651
423k
        if (rest_parameters) {
4652
579
            return NJS_DECLINED;
4653
579
        }
4654
4655
422k
        if (token->type == NJS_TOKEN_ELLIPSIS) {
4656
2.39k
            rest_parameters = 1;
4657
4658
2.39k
            token = njs_lexer_peek_token(parser->lexer, token, 0);
4659
2.39k
            if (token == NULL) {
4660
0
                return NJS_ERROR;
4661
0
            }
4662
2.39k
        }
4663
4664
422k
        if (!njs_lexer_token_is_binding_identifier(token)) {
4665
367k
            return NJS_DECLINED;
4666
367k
        }
4667
4668
55.1k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
4669
55.1k
        if (token == NULL) {
4670
0
            return NJS_ERROR;
4671
0
        }
4672
4673
55.1k
        if (token->type == NJS_TOKEN_COMMA) {
4674
5.05k
            token = njs_lexer_peek_token(parser->lexer, token, 0);
4675
5.05k
            if (token == NULL) {
4676
0
               return NJS_ERROR;
4677
0
            }
4678
5.05k
        }
4679
55.1k
    }
4680
4681
2.38M
arrow:
4682
4683
2.38M
    token = njs_lexer_peek_token(parser->lexer, token, 1);
4684
2.38M
    if (token == NULL) {
4685
0
        return NJS_ERROR;
4686
0
    }
4687
4688
2.38M
    if (token->type == NJS_TOKEN_LINE_END) {
4689
777k
        return NJS_DECLINED;
4690
777k
    }
4691
4692
1.61M
    if (token->type != NJS_TOKEN_ARROW) {
4693
1.24M
        return NJS_DECLINED;
4694
1.24M
    }
4695
4696
370k
    return NJS_OK;
4697
1.61M
}
4698
4699
4700
static njs_int_t
4701
njs_parser_assignment_expression_after(njs_parser_t *parser,
4702
    njs_lexer_token_t *token, njs_queue_link_t *current)
4703
3.49M
{
4704
3.49M
    return njs_parser_assignment_operator(parser, token, current);
4705
3.49M
}
4706
4707
4708
static njs_int_t
4709
njs_parser_assignment_operator(njs_parser_t *parser, njs_lexer_token_t *token,
4710
    njs_queue_link_t *current)
4711
3.49M
{
4712
3.49M
    njs_vmcode_t       operation;
4713
3.49M
    njs_token_type_t   type;
4714
3.49M
    njs_parser_node_t  *node;
4715
4716
3.49M
    switch (token->type) {
4717
269k
    case NJS_TOKEN_ASSIGNMENT:
4718
269k
        njs_thread_log_debug("JS: =");
4719
269k
        operation = NJS_VMCODE_MOVE;
4720
269k
        break;
4721
4722
8.02k
    case NJS_TOKEN_MULTIPLICATION_ASSIGNMENT:
4723
8.02k
        njs_thread_log_debug("JS: *=");
4724
8.02k
        operation = NJS_VMCODE_MULTIPLICATION;
4725
8.02k
        break;
4726
4727
96.8k
    case NJS_TOKEN_DIVISION_ASSIGNMENT:
4728
96.8k
        njs_thread_log_debug("JS: /=");
4729
96.8k
        operation = NJS_VMCODE_DIVISION;
4730
96.8k
        break;
4731
4732
35.9k
    case NJS_TOKEN_REMAINDER_ASSIGNMENT:
4733
35.9k
        njs_thread_log_debug("JS: %=");
4734
35.9k
        operation = NJS_VMCODE_REMAINDER;
4735
35.9k
        break;
4736
4737
9.37k
    case NJS_TOKEN_ADDITION_ASSIGNMENT:
4738
9.37k
        njs_thread_log_debug("JS: +=");
4739
9.37k
        operation = NJS_VMCODE_ADDITION;
4740
9.37k
        break;
4741
4742
7.68k
    case NJS_TOKEN_SUBTRACTION_ASSIGNMENT:
4743
7.68k
        njs_thread_log_debug("JS: -=");
4744
7.68k
        operation = NJS_VMCODE_SUBTRACTION;
4745
7.68k
        break;
4746
4747
1.19k
    case NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT:
4748
1.19k
        njs_thread_log_debug("JS: <<=");
4749
1.19k
        operation = NJS_VMCODE_LEFT_SHIFT;
4750
1.19k
        break;
4751
4752
2.76k
    case NJS_TOKEN_RIGHT_SHIFT_ASSIGNMENT:
4753
2.76k
        njs_thread_log_debug("JS: >>=");
4754
2.76k
        operation = NJS_VMCODE_RIGHT_SHIFT;
4755
2.76k
        break;
4756
4757
4.05k
    case NJS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
4758
4.05k
        njs_thread_log_debug("JS: >>>=");
4759
4.05k
        operation = NJS_VMCODE_UNSIGNED_RIGHT_SHIFT;
4760
4.05k
        break;
4761
4762
12.3k
    case NJS_TOKEN_BITWISE_AND_ASSIGNMENT:
4763
12.3k
        njs_thread_log_debug("JS: &=");
4764
12.3k
        operation = NJS_VMCODE_BITWISE_AND;
4765
12.3k
        break;
4766
4767
171
    case NJS_TOKEN_BITWISE_XOR_ASSIGNMENT:
4768
171
        njs_thread_log_debug("JS: ^=");
4769
171
        operation = NJS_VMCODE_BITWISE_XOR;
4770
171
        break;
4771
4772
19.3k
    case NJS_TOKEN_BITWISE_OR_ASSIGNMENT:
4773
19.3k
        njs_thread_log_debug("JS: |=");
4774
19.3k
        operation = NJS_VMCODE_BITWISE_OR;
4775
19.3k
        break;
4776
4777
160
    case NJS_TOKEN_EXPONENTIATION_ASSIGNMENT:
4778
160
        njs_thread_log_debug("JS: **=");
4779
160
        operation = NJS_VMCODE_EXPONENTIATION;
4780
160
        break;
4781
4782
1.61k
    case NJS_TOKEN_LOGICAL_OR_ASSIGNMENT:
4783
1.61k
        njs_thread_log_debug("JS: ||=");
4784
1.61k
        operation = NJS_VMCODE_TEST_IF_TRUE;
4785
1.61k
        break;
4786
4787
789
    case NJS_TOKEN_LOGICAL_AND_ASSIGNMENT:
4788
789
        njs_thread_log_debug("JS: &&=");
4789
789
        operation = NJS_VMCODE_TEST_IF_FALSE;
4790
789
        break;
4791
4792
19.1k
    case NJS_TOKEN_COALESCE_ASSIGNMENT:
4793
19.1k
        njs_thread_log_debug("JS: ?\?=");
4794
19.1k
        operation = NJS_VMCODE_COALESCE;
4795
19.1k
        break;
4796
4797
3.00M
    default:
4798
3.00M
        return njs_parser_stack_pop(parser);
4799
3.49M
    }
4800
4801
488k
    if (!njs_parser_is_lvalue(parser->node)) {
4802
1.81k
        type = parser->node->token_type;
4803
4804
1.81k
        if (njs_parser_restricted_identifier(type)) {
4805
1.11k
            njs_parser_syntax_error(parser, "Identifier \"%s\" "
4806
1.11k
                                    "is forbidden as left-hand in assignment",
4807
1.11k
                                    (type == NJS_TOKEN_EVAL) ? "eval"
4808
1.11k
                                                             : "arguments");
4809
4810
1.11k
        } else {
4811
698
            njs_parser_ref_error(parser,
4812
698
                                 "Invalid left-hand side in assignment");
4813
698
        }
4814
4815
1.81k
        return NJS_DONE;
4816
1.81k
    }
4817
4818
486k
    parser->node = njs_parser_lvalue_ref(parser->node);
4819
486k
    if (parser->node == NULL) {
4820
0
        return NJS_ERROR;
4821
0
    }
4822
4823
486k
    node = njs_parser_node_new(parser, token->type);
4824
486k
    if (node == NULL) {
4825
0
        return NJS_ERROR;
4826
0
    }
4827
4828
486k
    node->token_line = token->line;
4829
486k
    node->u.operation = operation;
4830
486k
    node->left = parser->node;
4831
4832
486k
    njs_lexer_consume_token(parser->lexer, 1);
4833
486k
    njs_parser_next(parser, njs_parser_assignment_expression);
4834
4835
486k
    return njs_parser_after(parser, current, node, 1,
4836
486k
                            njs_parser_assignment_operator_after);
4837
486k
}
4838
4839
4840
static njs_int_t
4841
njs_parser_assignment_operator_after(njs_parser_t *parser,
4842
    njs_lexer_token_t *token, njs_queue_link_t *current)
4843
477k
{
4844
477k
    return njs_parser_right_link_pop(parser);
4845
477k
}
4846
4847
4848
/*
4849
 * 12.16 Comma Operator ( , ).
4850
 */
4851
static njs_int_t
4852
njs_parser_expression(njs_parser_t *parser, njs_lexer_token_t *token,
4853
    njs_queue_link_t *current)
4854
2.23M
{
4855
2.23M
    njs_parser_next(parser, njs_parser_assignment_expression);
4856
4857
2.23M
    return njs_parser_after(parser, current, NULL, 1,
4858
2.23M
                            njs_parser_expression_comma);
4859
2.23M
}
4860
4861
4862
static njs_int_t
4863
njs_parser_expression_comma(njs_parser_t *parser, njs_lexer_token_t *token,
4864
    njs_queue_link_t *current)
4865
1.82M
{
4866
1.82M
    njs_parser_next(parser, njs_parser_assignment_expression);
4867
4868
1.82M
    return njs_parser_expression_node(parser, token, current, NJS_TOKEN_COMMA,
4869
1.82M
                                       0,
4870
1.82M
                                       njs_parser_expression_comma);
4871
1.82M
}
4872
4873
4874
/*
4875
 * 13 Statements and Declarations.
4876
 */
4877
static njs_int_t
4878
njs_parser_statement(njs_parser_t *parser, njs_lexer_token_t *token,
4879
    njs_queue_link_t *current)
4880
2.03M
{
4881
2.03M
    njs_int_t                 ret;
4882
2.03M
    njs_queue_link_t          *lnk;
4883
2.03M
    njs_parser_stack_entry_t  *entry;
4884
4885
2.03M
    if (token->type == NJS_TOKEN_END) {
4886
139k
        lnk = njs_queue_next(njs_queue_first(&parser->stack));
4887
4888
139k
        if (lnk == njs_queue_head(&parser->stack)) {
4889
0
            return njs_parser_reject(parser);
4890
0
        }
4891
4892
139k
        entry = njs_queue_link_data(lnk, njs_parser_stack_entry_t, link);
4893
4894
139k
        if (entry->state == njs_parser_check_error_state) {
4895
138k
            return NJS_DONE;
4896
138k
        }
4897
4898
1.06k
        return njs_parser_reject(parser);
4899
139k
    }
4900
4901
1.89M
    switch (token->type) {
4902
88.7k
    case NJS_TOKEN_SEMICOLON:
4903
88.7k
        njs_lexer_consume_token(parser->lexer, 1);
4904
88.7k
        return njs_parser_stack_pop(parser);
4905
4906
979
    case NJS_TOKEN_EXPORT:
4907
979
        parser->line = token->line;
4908
4909
979
        njs_lexer_consume_token(parser->lexer, 1);
4910
979
        njs_parser_next(parser, njs_parser_export);
4911
4912
979
        return njs_parser_after(parser, current, parser->node, 1,
4913
0
                                njs_parser_statement_after);
4914
4915
2.36k
    case NJS_TOKEN_IMPORT:
4916
2.36k
        parser->line = token->line;
4917
4918
2.36k
        njs_lexer_consume_token(parser->lexer, 1);
4919
2.36k
        njs_parser_next(parser, njs_parser_import);
4920
4921
2.36k
        return njs_parser_after(parser, current, parser->node, 1,
4922
0
                                njs_parser_statement_after);
4923
1.79M
    default:
4924
1.79M
        break;
4925
1.89M
    }
4926
4927
1.79M
    ret = njs_parser_statement_wo_node(parser, token, current);
4928
1.79M
    if (ret != NJS_OK) {
4929
0
        return ret;
4930
0
    }
4931
4932
1.79M
    return njs_parser_after(parser, current, parser->node, 1,
4933
1.79M
                            njs_parser_statement_after);
4934
1.79M
}
4935
4936
4937
static njs_int_t
4938
njs_parser_statement_wo_node(njs_parser_t *parser, njs_lexer_token_t *token,
4939
    njs_queue_link_t *current)
4940
1.95M
{
4941
1.95M
    switch (token->type) {
4942
133k
    case NJS_TOKEN_OPEN_BRACE:
4943
133k
        njs_parser_next(parser, njs_parser_block_statement);
4944
133k
        break;
4945
4946
18.5k
    case NJS_TOKEN_VAR:
4947
18.5k
        njs_lexer_consume_token(parser->lexer, 1);
4948
18.5k
        return njs_parser_variable_statement(parser, token, current);
4949
4950
6.05k
    case NJS_TOKEN_SEMICOLON:
4951
6.05k
        njs_lexer_consume_token(parser->lexer, 1);
4952
6.05k
        return njs_parser_stack_pop(parser);
4953
4954
14.6k
    case NJS_TOKEN_IF:
4955
14.6k
        njs_parser_next(parser, njs_parser_if_statement);
4956
14.6k
        break;
4957
4958
    /* BreakableStatement */
4959
20.5k
    case NJS_TOKEN_DO:
4960
20.5k
        njs_parser_next(parser, njs_parser_iteration_statement_do);
4961
20.5k
        break;
4962
4963
1.72k
    case NJS_TOKEN_WHILE:
4964
1.72k
        njs_parser_next(parser, njs_parser_iteration_statement_while);
4965
1.72k
        break;
4966
4967
64.1k
    case NJS_TOKEN_FOR:
4968
64.1k
        njs_parser_next(parser, njs_parser_iteration_statement_for);
4969
64.1k
        break;
4970
4971
11.2k
    case NJS_TOKEN_SWITCH:
4972
11.2k
        njs_parser_next(parser, njs_parser_switch_statement);
4973
11.2k
        break;
4974
4975
8.38k
    case NJS_TOKEN_CONTINUE:
4976
8.38k
        njs_parser_next(parser, njs_parser_continue_statement);
4977
8.38k
        break;
4978
4979
31.8k
    case NJS_TOKEN_BREAK:
4980
31.8k
        njs_parser_next(parser, njs_parser_break_statement);
4981
31.8k
        break;
4982
4983
15.2k
    case NJS_TOKEN_RETURN:
4984
15.2k
        njs_parser_next(parser, njs_parser_return_statement);
4985
15.2k
        break;
4986
4987
940
    case NJS_TOKEN_WITH:
4988
940
        njs_parser_next(parser, njs_parser_with_statement);
4989
940
        break;
4990
4991
14.3k
    case NJS_TOKEN_THROW:
4992
14.3k
        njs_parser_next(parser, njs_parser_throw_statement);
4993
14.3k
        break;
4994
4995
45.5k
    case NJS_TOKEN_TRY:
4996
45.5k
        njs_parser_next(parser, njs_parser_try_statement);
4997
45.5k
        break;
4998
4999
9.26k
    case NJS_TOKEN_DEBUGGER:
5000
9.26k
        njs_parser_next(parser, njs_parser_debugger_statement);
5001
9.26k
        break;
5002
5003
129
    case NJS_TOKEN_END:
5004
129
        return njs_parser_failed(parser);
5005
5006
1.55M
    default:
5007
1.55M
        if (njs_lexer_token_is_identifier_reference(token)) {
5008
1.15M
            token = njs_lexer_peek_token(parser->lexer, token, 0);
5009
1.15M
            if (token == NULL) {
5010
0
                return NJS_ERROR;
5011
0
            }
5012
5013
1.15M
            if (token->type == NJS_TOKEN_COLON) {
5014
64.9k
                njs_parser_next(parser, njs_parser_labelled_statement);
5015
64.9k
                return NJS_OK;
5016
64.9k
            }
5017
1.15M
        }
5018
5019
1.49M
        njs_parser_next(parser, njs_parser_expression_statement);
5020
1.49M
        return NJS_OK;
5021
1.95M
    }
5022
5023
371k
    parser->line = token->line;
5024
5025
371k
    njs_lexer_consume_token(parser->lexer, 1);
5026
5027
371k
    return NJS_OK;
5028
1.95M
}
5029
5030
5031
static njs_int_t
5032
njs_parser_statement_after(njs_parser_t *parser, njs_lexer_token_t *token,
5033
    njs_queue_link_t *current)
5034
1.53M
{
5035
1.53M
    njs_parser_node_t  *stmt, *last, *new_node, **child;
5036
1.53M
    njs_parser_node_t  *node, *top;
5037
5038
1.53M
    child = &parser->target;
5039
1.53M
    last = *child;
5040
5041
1.53M
    new_node = parser->node;
5042
5043
1.53M
    if (new_node != NULL) {
5044
1.53M
        if (new_node->hoist) {
5045
0
            child = &njs_parser_chain_top(parser);
5046
5047
0
            while (*child != NULL) {
5048
0
                node = *child;
5049
5050
0
                if (node->hoist) {
5051
0
                    break;
5052
0
                }
5053
5054
0
                child = &node->left;
5055
0
            }
5056
5057
0
            last = *child;
5058
0
        }
5059
5060
1.53M
        stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
5061
1.53M
        if (njs_slow_path(stmt == NULL)) {
5062
0
            return NJS_ERROR;
5063
0
        }
5064
5065
1.53M
        stmt->hoist = new_node->hoist;
5066
1.53M
        stmt->left = last;
5067
1.53M
        stmt->right = new_node;
5068
5069
1.53M
        *child = stmt;
5070
5071
1.53M
        top = (child != &parser->target) ? njs_parser_chain_top(parser)
5072
1.53M
                                         : stmt;
5073
5074
1.53M
        parser->node = top;
5075
5076
1.53M
       njs_parser_chain_top_set(parser, top);
5077
1.53M
    }
5078
5079
1.53M
    return njs_parser_stack_pop(parser);
5080
1.53M
}
5081
5082
5083
static njs_int_t
5084
njs_parser_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
5085
    njs_queue_link_t *current)
5086
2.08M
{
5087
2.08M
    njs_int_t  ret;
5088
5089
2.08M
    ret = njs_parser_hoistable_declaration(parser, token, current);
5090
2.08M
    if (ret == NJS_OK) {
5091
8.47k
        return NJS_OK;
5092
8.47k
    }
5093
5094
2.07M
    switch (token->type) {
5095
168
    case NJS_TOKEN_CLASS:
5096
168
        njs_parser_next(parser, njs_parser_class_declaration);
5097
168
        return NJS_OK;
5098
5099
12.3k
    case NJS_TOKEN_LET:
5100
43.5k
    case NJS_TOKEN_CONST:
5101
43.5k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
5102
43.5k
        if (token == NULL) {
5103
0
            return NJS_ERROR;
5104
0
        }
5105
5106
43.5k
        switch (token->type) {
5107
182
        case NJS_TOKEN_OPEN_BRACE:
5108
325
        case NJS_TOKEN_OPEN_BRACKET:
5109
325
            njs_parser_next(parser, njs_parser_lexical_declaration);
5110
325
            break;
5111
5112
43.2k
        default:
5113
43.2k
            if (njs_lexer_token_is_reserved(token)) {
5114
130
                njs_lexer_consume_token(parser->lexer, 1);
5115
130
                njs_parser_next(parser, njs_parser_failed_state);
5116
130
                return NJS_OK;
5117
130
            }
5118
5119
43.0k
            if (njs_lexer_token_is_binding_identifier(token)) {
5120
42.8k
                njs_parser_next(parser, njs_parser_lexical_declaration);
5121
42.8k
                break;
5122
42.8k
            }
5123
5124
267
            return NJS_DECLINED;
5125
43.5k
        }
5126
5127
43.1k
        break;
5128
5129
2.03M
    default:
5130
2.03M
        return NJS_DECLINED;
5131
2.07M
    }
5132
5133
43.1k
    return njs_parser_after(parser, current, parser->node, 1,
5134
2.07M
                            njs_parser_statement_after);
5135
2.07M
}
5136
5137
5138
static njs_int_t
5139
njs_parser_hoistable_declaration(njs_parser_t *parser,
5140
    njs_lexer_token_t *token, njs_queue_link_t *current)
5141
2.08M
{
5142
2.08M
    njs_int_t  ret;
5143
5144
2.08M
    ret = njs_parser_function_or_generator(parser, token, current);
5145
2.08M
    if (ret == NJS_OK) {
5146
5.77k
        return NJS_OK;
5147
5.77k
    }
5148
5149
2.07M
    ret = njs_parser_async_function_or_generator(parser, token, current);
5150
2.07M
    if (ret == NJS_OK) {
5151
2.70k
        return NJS_OK;
5152
2.70k
    }
5153
5154
2.07M
    return NJS_DECLINED;
5155
2.07M
}
5156
5157
5158
/*
5159
 * 13.2 Block.
5160
 */
5161
static njs_int_t
5162
njs_parser_block_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5163
    njs_queue_link_t *current)
5164
190k
{
5165
190k
    void       *target;
5166
190k
    njs_int_t  ret;
5167
5168
190k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK, 0);
5169
190k
    if (ret != NJS_OK) {
5170
0
        return NJS_ERROR;
5171
0
    }
5172
5173
190k
    target = (void *) (uintptr_t) parser->line;
5174
190k
    parser->node = NULL;
5175
5176
190k
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
5177
20.3k
        parser->target = target;
5178
5179
20.3k
        njs_parser_next(parser, njs_parser_block_statement_close_brace);
5180
20.3k
        return NJS_OK;
5181
20.3k
    }
5182
5183
170k
    njs_parser_next(parser, njs_parser_statement_list);
5184
5185
170k
    return njs_parser_after(parser, current, target, 0,
5186
190k
                            njs_parser_block_statement_close_brace);
5187
190k
}
5188
5189
5190
static njs_int_t
5191
njs_parser_block_statement_open_brace(njs_parser_t *parser,
5192
    njs_lexer_token_t *token, njs_queue_link_t *current)
5193
57.4k
{
5194
57.4k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
5195
46
        return njs_parser_failed(parser);
5196
46
    }
5197
5198
57.4k
    parser->line = token->line;
5199
5200
57.4k
    njs_lexer_consume_token(parser->lexer, 1);
5201
5202
57.4k
    token = njs_lexer_token(parser->lexer, 0);
5203
57.4k
    if (token == NULL) {
5204
0
        return NJS_ERROR;
5205
0
    }
5206
5207
57.4k
    return njs_parser_block_statement(parser, token, current);
5208
57.4k
}
5209
5210
5211
static njs_int_t
5212
njs_parser_block_statement_close_brace(njs_parser_t *parser,
5213
    njs_lexer_token_t *token, njs_queue_link_t *current)
5214
162k
{
5215
162k
    njs_parser_node_t  *node;
5216
5217
162k
    if (parser->ret != NJS_OK) {
5218
2.38k
        return njs_parser_failed(parser);
5219
2.38k
    }
5220
5221
160k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
5222
0
        return njs_parser_failed(parser);
5223
0
    }
5224
5225
160k
    node = njs_parser_node_new(parser, NJS_TOKEN_BLOCK);
5226
160k
    if (node == NULL) {
5227
0
        return NJS_ERROR;
5228
0
    }
5229
5230
160k
    node->token_line = (uint32_t) (uintptr_t) parser->target;
5231
160k
    node->left = parser->node;
5232
160k
    node->right = NULL;
5233
5234
160k
    parser->target = NULL;
5235
160k
    parser->node = node;
5236
5237
160k
    njs_parser_scope_end(parser);
5238
5239
160k
    njs_lexer_consume_token(parser->lexer, 1);
5240
160k
    return njs_parser_stack_pop(parser);
5241
160k
}
5242
5243
5244
static njs_int_t
5245
njs_parser_statement_list(njs_parser_t *parser, njs_lexer_token_t *token,
5246
    njs_queue_link_t *current)
5247
718k
{
5248
718k
    njs_parser_next(parser, njs_parser_statement_list_item);
5249
5250
718k
    return njs_parser_after(parser, current, NULL, 1,
5251
718k
                            njs_parser_statement_list_next);
5252
718k
}
5253
5254
5255
static njs_int_t
5256
njs_parser_statement_list_next(njs_parser_t *parser, njs_lexer_token_t *token,
5257
    njs_queue_link_t *current)
5258
1.63M
{
5259
1.63M
    if (parser->ret != NJS_OK) {
5260
13.2k
        if (token->type != NJS_TOKEN_CLOSE_BRACE) {
5261
12.7k
            parser->node = parser->target;
5262
5263
12.7k
            (void) njs_parser_stack_pop(parser);
5264
5265
12.7k
            return parser->ret;
5266
12.7k
        }
5267
5268
502
        return njs_parser_failed(parser);
5269
13.2k
    }
5270
5271
1.62M
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
5272
262k
        return njs_parser_stack_pop(parser);
5273
262k
    }
5274
5275
1.36M
    njs_parser_next(parser, njs_parser_statement_list_item);
5276
5277
1.36M
    return njs_parser_after(parser, current, parser->node, 0,
5278
1.62M
                            njs_parser_statement_list_next);
5279
1.62M
}
5280
5281
5282
static njs_int_t
5283
njs_parser_statement_list_item(njs_parser_t *parser, njs_lexer_token_t *token,
5284
    njs_queue_link_t *current)
5285
2.08M
{
5286
2.08M
    njs_int_t  ret;
5287
5288
2.08M
    ret = njs_parser_declaration(parser, token, current);
5289
2.08M
    if (ret == NJS_OK) {
5290
51.9k
        return NJS_OK;
5291
51.9k
    }
5292
5293
2.03M
    njs_parser_next(parser, njs_parser_statement);
5294
5295
2.03M
    return NJS_OK;
5296
2.08M
}
5297
5298
5299
/*
5300
 * 13.3.1 Let and Const Declarations
5301
 */
5302
static njs_int_t
5303
njs_parser_lexical_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
5304
    njs_queue_link_t *current)
5305
43.1k
{
5306
43.1k
    parser->var_type = (token->type == NJS_TOKEN_LET) ? NJS_VARIABLE_LET
5307
43.1k
                                                      : NJS_VARIABLE_CONST;
5308
5309
43.1k
    njs_lexer_consume_token(parser->lexer, 1);
5310
5311
43.1k
    njs_parser_next(parser, njs_parser_variable_declaration_list);
5312
5313
43.1k
    return njs_parser_after(parser, current, NULL, 1, njs_parser_semicolon);
5314
43.1k
}
5315
5316
5317
/*
5318
 * 13.3.2 Variable Statement
5319
 */
5320
static njs_int_t
5321
njs_parser_variable_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5322
    njs_queue_link_t *current)
5323
18.5k
{
5324
18.5k
    parser->var_type = NJS_VARIABLE_VAR;
5325
5326
18.5k
    njs_parser_next(parser, njs_parser_variable_declaration_list);
5327
5328
18.5k
    return njs_parser_after(parser, current, NULL, 1, njs_parser_semicolon);
5329
18.5k
}
5330
5331
5332
static njs_int_t
5333
njs_parser_variable_declaration_list(njs_parser_t *parser,
5334
    njs_lexer_token_t *token, njs_queue_link_t *current)
5335
63.8k
{
5336
63.8k
    njs_parser_next(parser, njs_parser_variable_declaration);
5337
5338
63.8k
    return njs_parser_after(parser, current, NULL, 1,
5339
63.8k
                            njs_parser_variable_declaration_list_next);
5340
63.8k
}
5341
5342
5343
static njs_int_t
5344
njs_parser_variable_declaration_list_next(njs_parser_t *parser,
5345
    njs_lexer_token_t *token, njs_queue_link_t *current)
5346
65.6k
{
5347
65.6k
    njs_parser_node_t  *node;
5348
5349
65.6k
    if (parser->target != NULL) {
5350
6.80k
        parser->node->left = parser->target;
5351
6.80k
    }
5352
5353
65.6k
    if (token->type != NJS_TOKEN_COMMA) {
5354
47.4k
        return njs_parser_stack_pop(parser);
5355
47.4k
    }
5356
5357
18.2k
    njs_lexer_consume_token(parser->lexer, 1);
5358
5359
18.2k
    node = parser->node;
5360
5361
18.2k
    parser->node = NULL;
5362
5363
18.2k
    njs_parser_next(parser, njs_parser_variable_declaration);
5364
5365
18.2k
    return njs_parser_after(parser, current, node, 1,
5366
65.6k
                            njs_parser_variable_declaration_list_next);
5367
65.6k
}
5368
5369
5370
static njs_int_t
5371
njs_parser_variable_declaration(njs_parser_t *parser,
5372
    njs_lexer_token_t *token, njs_queue_link_t *current)
5373
82.0k
{
5374
82.0k
    njs_int_t          ret;
5375
82.0k
    njs_variable_t     *var;
5376
82.0k
    njs_token_type_t   type;
5377
82.0k
    njs_parser_node_t  *name;
5378
5379
82.0k
    ret = njs_parser_binding_pattern(parser, token, current);
5380
82.0k
    if (ret == NJS_OK) {
5381
325
        return njs_parser_after(parser, current, NULL, 1,
5382
325
                                njs_parser_initializer);
5383
325
    }
5384
5385
81.7k
    if (!njs_lexer_token_is_binding_identifier(token)) {
5386
1.59k
        return njs_parser_failed(parser);
5387
1.59k
    }
5388
5389
80.1k
    if (njs_parser_restricted_identifier(token->type)) {
5390
1.49k
        njs_parser_syntax_error(parser, "Identifier \"%V\" is forbidden in"
5391
1.49k
                                " var declaration", &token->text);
5392
1.49k
        return NJS_DONE;
5393
1.49k
    }
5394
5395
78.6k
    name = njs_parser_variable_node(parser, token->atom_id, parser->var_type,
5396
78.6k
                                    &var);
5397
78.6k
    if (name == NULL) {
5398
1.40k
        return NJS_ERROR;
5399
1.40k
    }
5400
5401
77.2k
    if (var->self) {
5402
432
        var->type = parser->var_type;
5403
432
        var->self = 0;
5404
432
    }
5405
5406
77.2k
    name->token_line = token->line;
5407
5408
77.2k
    parser->node = name;
5409
5410
77.2k
    njs_lexer_consume_token(parser->lexer, 1);
5411
5412
77.2k
    token = njs_lexer_token(parser->lexer, 0);
5413
77.2k
    if (token == NULL) {
5414
0
        return NJS_ERROR;
5415
0
    }
5416
5417
77.2k
    switch (parser->var_type) {
5418
11.8k
    case NJS_VARIABLE_LET:
5419
11.8k
        type = NJS_TOKEN_LET;
5420
11.8k
        break;
5421
5422
47.8k
    case NJS_VARIABLE_CONST:
5423
47.8k
        type = NJS_TOKEN_CONST;
5424
47.8k
        break;
5425
5426
17.5k
    default:
5427
17.5k
        type = NJS_TOKEN_VAR;
5428
17.5k
        break;
5429
77.2k
    }
5430
5431
77.2k
    ret = njs_parser_initializer_assign(parser, type);
5432
77.2k
    if (ret != NJS_OK) {
5433
0
        return ret;
5434
0
    }
5435
5436
77.2k
    parser->node->token_line = token->line;
5437
5438
77.2k
    if (token->type == NJS_TOKEN_ASSIGNMENT) {
5439
63.7k
        njs_parser_next(parser, njs_parser_initializer);
5440
5441
63.7k
        return NJS_OK;
5442
63.7k
    }
5443
5444
13.4k
    parser->target = parser->node;
5445
13.4k
    parser->node = NULL;
5446
5447
13.4k
    njs_parser_next(parser, njs_parser_initializer_after);
5448
5449
13.4k
    return NJS_OK;
5450
77.2k
}
5451
5452
5453
/*
5454
 * 13.3.3 Destructuring Binding Patterns.
5455
 */
5456
static njs_int_t
5457
njs_parser_binding_pattern(njs_parser_t *parser, njs_lexer_token_t *token,
5458
    njs_queue_link_t *current)
5459
82.0k
{
5460
82.0k
    if (token->type == NJS_TOKEN_OPEN_BRACE) {
5461
182
        njs_parser_next(parser, njs_parser_object_binding_pattern);
5462
5463
81.8k
    } else if (token->type == NJS_TOKEN_OPEN_BRACKET) {
5464
143
        njs_parser_next(parser, njs_parser_array_binding_pattern);
5465
5466
81.7k
    } else {
5467
81.7k
        return NJS_DECLINED;
5468
81.7k
    }
5469
5470
325
    njs_lexer_consume_token(parser->lexer, 1);
5471
5472
325
    return NJS_OK;
5473
82.0k
}
5474
5475
static njs_int_t
5476
njs_parser_object_binding_pattern(njs_parser_t *parser,
5477
    njs_lexer_token_t *token, njs_queue_link_t *current)
5478
435
{
5479
435
    return njs_parser_not_supported(parser, token);
5480
435
}
5481
5482
5483
static njs_int_t
5484
njs_parser_array_binding_pattern(njs_parser_t *parser,
5485
    njs_lexer_token_t *token, njs_queue_link_t *current)
5486
277
{
5487
277
    return njs_parser_not_supported(parser, token);
5488
277
}
5489
5490
5491
/*
5492
 * 13.5 Expression Statement.
5493
 */
5494
static njs_int_t
5495
njs_parser_expression_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5496
    njs_queue_link_t *current)
5497
1.49M
{
5498
1.49M
    njs_token_type_t   type;
5499
1.49M
    njs_lexer_token_t  *next;
5500
5501
1.49M
    switch (token->type) {
5502
196
    case NJS_TOKEN_FUNCTION:
5503
196
        njs_parser_syntax_error(parser, "Functions can only be declared "
5504
196
                                        "at top level or inside a block");
5505
196
        return NJS_DONE;
5506
5507
134
    case NJS_TOKEN_CLASS:
5508
134
        njs_parser_syntax_error(parser, "Class can only be declared "
5509
134
                                        "at top level or inside a block");
5510
134
        return NJS_DONE;
5511
5512
0
    case NJS_TOKEN_OPEN_BRACE:
5513
0
        return njs_parser_reject(parser);
5514
5515
1.68k
    case NJS_TOKEN_ASYNC:
5516
1.68k
        next = njs_lexer_peek_token(parser->lexer, token, 1);
5517
1.68k
        if (next == NULL) {
5518
0
            return NJS_ERROR;
5519
0
        }
5520
5521
1.68k
        if (next->type == NJS_TOKEN_FUNCTION) {
5522
0
            return njs_parser_not_supported(parser, token);
5523
0
        }
5524
5525
1.68k
        break;
5526
5527
1.68k
    case NJS_TOKEN_CONST:
5528
400
    case NJS_TOKEN_LET:
5529
400
        type = token->type;
5530
5531
400
        token = njs_lexer_peek_token(parser->lexer, token, 0);
5532
400
        if (token == NULL) {
5533
0
            return NJS_ERROR;
5534
0
        }
5535
5536
400
        if (token->type == NJS_TOKEN_NAME) {
5537
133
            njs_parser_syntax_error(parser, "%s declaration cannot appear "
5538
133
                                    "in a single-statement context",
5539
133
                                    (type == NJS_TOKEN_CONST ? "const"
5540
133
                                                             : "let" ));
5541
133
            return NJS_DONE;
5542
133
        }
5543
5544
267
        if (token->type == NJS_TOKEN_OPEN_BRACKET) {
5545
0
            return njs_parser_failed(parser);
5546
0
        }
5547
5548
267
        break;
5549
5550
1.49M
    default:
5551
1.49M
        break;
5552
1.49M
    }
5553
5554
1.49M
    parser->node = NULL;
5555
5556
1.49M
    njs_parser_next(parser, njs_parser_expression);
5557
5558
1.49M
    return njs_parser_after(parser, current, NULL, 1,
5559
1.49M
                            njs_parser_expression_statement_after);
5560
1.49M
}
5561
5562
5563
static njs_int_t
5564
njs_parser_expression_statement_after(njs_parser_t *parser,
5565
    njs_lexer_token_t *token, njs_queue_link_t *current)
5566
1.30M
{
5567
1.30M
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
5568
4.94k
        return njs_parser_failed(parser);
5569
4.94k
    }
5570
5571
1.29M
    return njs_parser_stack_pop(parser);
5572
1.30M
}
5573
5574
5575
/*
5576
 * 13.6 if Statement.
5577
 */
5578
static njs_int_t
5579
njs_parser_if_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5580
    njs_queue_link_t *current)
5581
14.6k
{
5582
14.6k
    njs_int_t          ret;
5583
14.6k
    njs_parser_node_t  *node;
5584
5585
14.6k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
5586
150
        return njs_parser_failed(parser);
5587
150
    }
5588
5589
14.5k
    njs_lexer_consume_token(parser->lexer, 1);
5590
5591
14.5k
    node = njs_parser_node_new(parser, NJS_TOKEN_IF);
5592
14.5k
    if (node == NULL) {
5593
0
        return NJS_ERROR;
5594
0
    }
5595
5596
14.5k
    node->token_line = parser->line;
5597
5598
14.5k
    parser->node = NULL;
5599
5600
14.5k
    njs_parser_next(parser, njs_parser_expression);
5601
5602
14.5k
    ret = njs_parser_after(parser, current, node, 1,
5603
14.5k
                           njs_parser_if_close_parenthesis);
5604
14.5k
    if (ret != NJS_OK) {
5605
0
        return ret;
5606
0
    }
5607
5608
14.5k
    ret = njs_parser_after(parser, current, NULL, 1,
5609
14.5k
                           njs_parser_statement_wo_node);
5610
14.5k
    if (ret != NJS_OK) {
5611
0
        return ret;
5612
0
    }
5613
5614
14.5k
    return njs_parser_after(parser, current, node, 1,
5615
14.5k
                            njs_parser_else_statement);
5616
14.5k
}
5617
5618
5619
static njs_int_t
5620
njs_parser_if_close_parenthesis(njs_parser_t *parser, njs_lexer_token_t *token,
5621
    njs_queue_link_t *current)
5622
14.3k
{
5623
14.3k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
5624
2.86k
        return njs_parser_failed(parser);
5625
2.86k
    }
5626
5627
11.4k
    njs_lexer_consume_token(parser->lexer, 1);
5628
5629
11.4k
    parser->target->left = parser->node;
5630
11.4k
    parser->node = NULL;
5631
5632
11.4k
    return njs_parser_stack_pop(parser);
5633
14.3k
}
5634
5635
5636
static njs_int_t
5637
njs_parser_else_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5638
    njs_queue_link_t *current)
5639
11.2k
{
5640
11.2k
    njs_parser_node_t  *node;
5641
5642
11.2k
    parser->target->right = parser->node;
5643
11.2k
    parser->node = NULL;
5644
5645
11.2k
    if (token->type == NJS_TOKEN_ELSE) {
5646
9.46k
        node = njs_parser_node_new(parser, NJS_TOKEN_BRANCHING);
5647
9.46k
        if (node == NULL) {
5648
0
            return NJS_ERROR;
5649
0
        }
5650
5651
9.46k
        node->token_line = token->line;
5652
9.46k
        node->left = parser->target->right;
5653
5654
9.46k
        parser->target->right = node;
5655
5656
9.46k
        njs_lexer_consume_token(parser->lexer, 1);
5657
9.46k
        njs_parser_next(parser, njs_parser_statement_wo_node);
5658
5659
9.46k
        return njs_parser_after(parser, current, parser->target, 1,
5660
9.46k
                                njs_parser_else_statement_after);
5661
9.46k
    }
5662
5663
1.82k
    parser->node = parser->target;
5664
5665
1.82k
    return njs_parser_stack_pop(parser);
5666
11.2k
}
5667
5668
5669
static njs_int_t
5670
njs_parser_else_statement_after(njs_parser_t *parser, njs_lexer_token_t *token,
5671
    njs_queue_link_t *current)
5672
9.30k
{
5673
9.30k
    parser->target->right->right = parser->node;
5674
5675
9.30k
    parser->node = parser->target;
5676
5677
9.30k
    return njs_parser_stack_pop(parser);
5678
9.30k
}
5679
5680
5681
static njs_int_t
5682
njs_parser_iteration_statement_do(njs_parser_t *parser,
5683
    njs_lexer_token_t *token, njs_queue_link_t *current)
5684
20.5k
{
5685
20.5k
    njs_parser_node_t  *node;
5686
5687
20.5k
    node = njs_parser_node_new(parser, NJS_TOKEN_DO);
5688
20.5k
    if (node == NULL) {
5689
0
        return NJS_ERROR;
5690
0
    }
5691
5692
20.5k
    node->token_line = parser->line;
5693
5694
20.5k
    parser->node = NULL;
5695
5696
20.5k
    njs_parser_next(parser, njs_parser_statement_wo_node);
5697
5698
20.5k
    return njs_parser_after(parser, current, node, 1,
5699
20.5k
                            njs_parser_iteration_statement_do_while);
5700
20.5k
}
5701
5702
5703
static njs_int_t
5704
njs_parser_iteration_statement_do_while(njs_parser_t *parser,
5705
    njs_lexer_token_t *token, njs_queue_link_t *current)
5706
20.5k
{
5707
20.5k
    if (token->type != NJS_TOKEN_WHILE) {
5708
207
        return njs_parser_failed(parser);
5709
207
    }
5710
5711
20.3k
    parser->target->left = parser->node;
5712
5713
20.3k
    njs_lexer_consume_token(parser->lexer, 1);
5714
5715
20.3k
    njs_parser_next(parser, njs_parser_expression_parenthesis);
5716
5717
20.3k
    return njs_parser_after(parser, current, parser->target, 1,
5718
20.5k
                            njs_parser_do_while_semicolon);
5719
20.5k
}
5720
5721
5722
static njs_int_t
5723
njs_parser_do_while_semicolon(njs_parser_t *parser, njs_lexer_token_t *token,
5724
    njs_queue_link_t *current)
5725
20.3k
{
5726
20.3k
    return njs_parser_right_link_pop(parser);
5727
20.3k
}
5728
5729
5730
static njs_int_t
5731
njs_parser_iteration_statement_while(njs_parser_t *parser,
5732
    njs_lexer_token_t *token, njs_queue_link_t *current)
5733
1.72k
{
5734
1.72k
    njs_parser_node_t  *node;
5735
5736
1.72k
    node = njs_parser_node_new(parser, NJS_TOKEN_WHILE);
5737
1.72k
    if (node == NULL) {
5738
0
        return NJS_ERROR;
5739
0
    }
5740
5741
1.72k
    node->token_line = token->line;
5742
5743
1.72k
    njs_parser_next(parser, njs_parser_expression_parenthesis);
5744
5745
1.72k
    return njs_parser_after(parser, current, node, 1,
5746
1.72k
                            njs_parser_while_statement);
5747
1.72k
}
5748
5749
5750
static njs_int_t
5751
njs_parser_while_statement(njs_parser_t *parser, njs_lexer_token_t *token,
5752
    njs_queue_link_t *current)
5753
1.72k
{
5754
1.72k
    parser->target->right = parser->node;
5755
1.72k
    parser->node = NULL;
5756
5757
1.72k
    njs_parser_next(parser, njs_parser_statement_wo_node);
5758
5759
1.72k
    return njs_parser_after(parser, current, parser->target, 1,
5760
1.72k
                            njs_parser_while_after);
5761
1.72k
}
5762
5763
5764
static njs_int_t
5765
njs_parser_while_after(njs_parser_t *parser, njs_lexer_token_t *token,
5766
    njs_queue_link_t *current)
5767
1.58k
{
5768
1.58k
    parser->target->left = parser->node;
5769
1.58k
    parser->node = parser->target;
5770
5771
1.58k
    return njs_parser_stack_pop(parser);
5772
1.58k
}
5773
5774
5775
static njs_int_t
5776
njs_parser_iteration_statement_for(njs_parser_t *parser,
5777
    njs_lexer_token_t *token, njs_queue_link_t *current)
5778
64.1k
{
5779
64.1k
    njs_int_t  ret;
5780
5781
64.1k
    if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
5782
61.9k
        njs_lexer_consume_token(parser->lexer, 1);
5783
5784
61.9k
        ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK, 0);
5785
61.9k
        if (njs_slow_path(ret != NJS_OK)) {
5786
0
            return ret;
5787
0
        }
5788
5789
61.9k
        njs_parser_next(parser, njs_parser_iteration_statement_for_map);
5790
5791
61.9k
        return njs_parser_after(parser, current,
5792
61.9k
                                (void *) (uintptr_t) parser->line, 1,
5793
61.9k
                                njs_parser_iteration_statement_for_end);
5794
61.9k
    }
5795
5796
2.19k
    if (token->type == NJS_TOKEN_AWAIT) {
5797
2.03k
        return njs_parser_not_supported(parser, token);
5798
2.03k
    }
5799
5800
164
    return njs_parser_failed(parser);
5801
2.19k
}
5802
5803
5804
static njs_int_t
5805
njs_parser_for_expression_map_reparse(njs_parser_t *parser,
5806
    njs_lexer_token_t *token, njs_queue_link_t *current)
5807
29.4k
{
5808
29.4k
    if (parser->ret != NJS_OK && parser->node != NULL) {
5809
195
        return njs_parser_failed(parser);
5810
195
    }
5811
5812
29.2k
    if (parser->node == NULL) {
5813
1.72k
        njs_lexer_in_fail_set(parser->lexer, 1);
5814
5815
1.72k
        njs_parser_next(parser, njs_parser_expression);
5816
5817
1.72k
        return NJS_OK;
5818
1.72k
    }
5819
5820
27.5k
    return njs_parser_stack_pop(parser);
5821
29.2k
}
5822
5823
5824
static njs_int_t
5825
njs_parser_for_expression_map_continue(njs_parser_t *parser,
5826
    njs_lexer_token_t *token, njs_queue_link_t *current)
5827
29.0k
{
5828
29.0k
    njs_int_t          operation;
5829
29.0k
    njs_str_t          *text;
5830
29.0k
    njs_parser_node_t  *node;
5831
5832
29.0k
    if (token->type != NJS_TOKEN_IN) {
5833
17.4k
        njs_lexer_in_fail_set(parser->lexer, 1);
5834
5835
        /* Continue parsing of expr1 in "for (expr1;[expr2];[expr3])". */
5836
5837
17.4k
        njs_parser_next(parser, njs_parser_expression_continue_op);
5838
5839
        /*
5840
         * Here we pass not a node, but a token, this is important.
5841
         * This is necessary for correct error output.
5842
         */
5843
5844
17.4k
        text = njs_mp_alloc(parser->vm->mem_pool, sizeof(njs_str_t));
5845
17.4k
        if (text == NULL) {
5846
0
            return NJS_ERROR;
5847
0
        }
5848
5849
17.4k
        *text = token->text;
5850
5851
17.4k
        return njs_parser_after(parser, current, text, 1,
5852
17.4k
                                njs_parser_for_var_in_of_expression);
5853
5854
17.4k
    } else {
5855
5856
        /* for-in */
5857
5858
11.5k
        if (!njs_parser_is_lvalue(parser->node)) {
5859
130
            text = (njs_str_t *) parser->target;
5860
5861
130
            njs_parser_ref_error(parser, "Invalid left-hand side \"%V\" "
5862
130
                                 "in for-in statement", text);
5863
5864
130
            njs_mp_free(parser->vm->mem_pool, text);
5865
5866
130
            return NJS_DONE;
5867
130
        }
5868
5869
11.4k
        parser->node = njs_parser_lvalue_ref(parser->node);
5870
11.4k
        if (parser->node == NULL) {
5871
0
            return NJS_ERROR;
5872
0
        }
5873
5874
11.4k
        operation = NJS_VMCODE_PROPERTY_IN;
5875
5876
11.4k
        node = njs_parser_node_new(parser, token->type);
5877
11.4k
        if (node == NULL) {
5878
0
            return NJS_ERROR;
5879
0
        }
5880
5881
11.4k
        node->token_line = token->line;
5882
11.4k
        node->u.operation = operation;
5883
11.4k
        node->left = parser->node;
5884
11.4k
        node->left->dest = node;
5885
5886
11.4k
        njs_lexer_consume_token(parser->lexer, 1);
5887
5888
11.4k
        njs_parser_next(parser, njs_parser_expression);
5889
5890
11.4k
        return njs_parser_after(parser, current, node, 0,
5891
11.4k
                                njs_parser_for_in_statement_statement);
5892
11.4k
    }
5893
29.0k
}
5894
5895
5896
static njs_int_t
5897
njs_parser_after_expr(njs_parser_t *parser,
5898
    njs_lexer_token_t *token, njs_queue_link_t *current)
5899
0
{
5900
0
    return njs_parser_right_link_pop(parser);
5901
0
}
5902
5903
5904
static njs_int_t
5905
njs_parser_comma_expression_comma(njs_parser_t *parser,
5906
    njs_lexer_token_t *token, njs_queue_link_t *current)
5907
16.2k
{
5908
16.2k
    njs_parser_node_t  *node;
5909
5910
16.2k
    if (parser->target != NULL) {
5911
0
        parser->target->right = parser->node;
5912
0
        parser->target->right->dest = parser->target;
5913
0
        parser->node = parser->target;
5914
0
    }
5915
5916
16.2k
    if (token->type != NJS_TOKEN_COMMA) {
5917
16.2k
        return njs_parser_stack_pop(parser);
5918
16.2k
    }
5919
5920
0
    node = njs_parser_node_new(parser, NJS_TOKEN_COMMA);
5921
0
    if (node == NULL) {
5922
0
        return NJS_ERROR;
5923
0
    }
5924
5925
0
    node->token_line = token->line;
5926
0
    node->u.operation = 0;
5927
0
    node->left = parser->node;
5928
0
    node->left->dest = node;
5929
5930
0
    njs_lexer_consume_token(parser->lexer, 1);
5931
5932
0
    njs_parser_next(parser, njs_parser_expression);
5933
5934
0
    return njs_parser_after(parser, current, node, 1, njs_parser_after_expr);
5935
0
}
5936
5937
5938
static njs_int_t
5939
njs_parser_expression_continue_op(njs_parser_t *parser,
5940
    njs_lexer_token_t *token, njs_queue_link_t *current)
5941
17.4k
{
5942
17.4k
    if (token->type == NJS_TOKEN_CONDITIONAL) {
5943
343
        njs_parser_next(parser, njs_parser_conditional_question_mark);
5944
343
        return njs_parser_after(parser, current, NULL, 0,
5945
343
                                njs_parser_expression_continue_assign_comma);
5946
17.1k
    } else {
5947
17.1k
        parser->target = NULL;
5948
5949
17.1k
        parser->use_lhs = 1;
5950
5951
17.1k
        njs_parser_next(parser, njs_parser_expression);
5952
5953
17.1k
        return njs_parser_after(parser, current, NULL, 1,
5954
17.1k
                                njs_parser_comma_expression_comma);
5955
17.1k
    }
5956
17.4k
}
5957
5958
5959
static njs_int_t
5960
njs_parser_expression_continue_assign_comma(njs_parser_t *parser,
5961
    njs_lexer_token_t *token, njs_queue_link_t *current)
5962
278
{
5963
278
    if (parser->ret != NJS_OK) {
5964
54
        return njs_parser_failed(parser);
5965
54
    }
5966
5967
224
    njs_parser_next(parser, njs_parser_assignment_expression_after);
5968
5969
224
    return njs_parser_after(parser, current, NULL, 1,
5970
278
                            njs_parser_expression_comma);
5971
278
}
5972
5973
5974
static njs_int_t
5975
njs_parser_iteration_statement_for_map(njs_parser_t *parser,
5976
    njs_lexer_token_t *token, njs_queue_link_t *current)
5977
62.9k
{
5978
62.9k
    njs_int_t         ret;
5979
62.9k
    njs_str_t         *text;
5980
62.9k
    njs_token_type_t  token_type;
5981
5982
    /*
5983
     * "var" <VariableDeclarationList> ";" <Expression>? ";" <Expression>? ")"
5984
     *     <Statement>
5985
     * "var" <ForBinding> "in" <Expression> ")" <Statement>
5986
     * "var" <ForBinding> "of" <AssignmentExpression> ")" <Statement>
5987
5988
     * <ForDeclaration> "in" <Expression> ")" <Statement>
5989
     * <ForDeclaration> "of" <AssignmentExpression> ")" <Statement>
5990
5991
     * <Expression>? ";" <Expression>? ";" <Expression>? ")" <Statement>
5992
     * <LexicalDeclaration> <Expression>? ";" <Expression>? ")" <Statement>
5993
5994
     * <LeftHandSideExpression> "in" <Expression> ")" <Statement>
5995
     * <LeftHandSideExpression> "of" <AssignmentExpression> ")" <Statement>
5996
     */
5997
5998
62.9k
    parser->node = NULL;
5999
6000
62.9k
    switch (token->type) {
6001
12.9k
    case NJS_TOKEN_SEMICOLON:
6002
12.9k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
6003
12.9k
        if (token == NULL) {
6004
0
            return NJS_ERROR;
6005
0
        }
6006
6007
12.9k
        if (token->type != NJS_TOKEN_SEMICOLON) {
6008
2.80k
            njs_lexer_consume_token(parser->lexer, 1);
6009
6010
2.80k
            parser->target = NULL;
6011
6012
2.80k
            njs_parser_next(parser, njs_parser_expression);
6013
6014
2.80k
            return njs_parser_after(parser, current, NULL, 1,
6015
2.80k
                                    njs_parser_for_expression);
6016
2.80k
        }
6017
6018
10.1k
        parser->node = NULL;
6019
10.1k
        parser->target = NULL;
6020
6021
10.1k
        njs_lexer_consume_token(parser->lexer, 1);
6022
10.1k
        njs_parser_next(parser, njs_parser_for_expression);
6023
6024
10.1k
        return NJS_OK;
6025
6026
17.0k
    case NJS_TOKEN_VAR:
6027
17.3k
    case NJS_TOKEN_LET:
6028
17.4k
    case NJS_TOKEN_CONST:
6029
17.4k
        token_type = token->type;
6030
6031
17.4k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
6032
17.4k
        if (token == NULL) {
6033
0
            return NJS_ERROR;
6034
0
        }
6035
6036
17.4k
        njs_lexer_consume_token(parser->lexer, 1);
6037
6038
17.4k
        ret = njs_parser_for_var_binding_or_var_list(parser, token,
6039
17.4k
                                                     current, token_type);
6040
17.4k
        if (ret != NJS_OK) {
6041
15.4k
            if (ret == NJS_DONE) {
6042
12.3k
                return NJS_OK;
6043
12.3k
            }
6044
6045
3.00k
            return ret;
6046
15.4k
        }
6047
6048
2.06k
        goto expression_after;
6049
6050
2.06k
    case NJS_TOKEN_AWAIT:
6051
156
        njs_parser_next(parser, njs_parser_expression);
6052
6053
156
        goto expression_after;
6054
6055
32.3k
    default:
6056
32.3k
        ret = njs_parser_match_arrow_expression(parser, token);
6057
32.3k
        if (ret == NJS_OK) {
6058
397
            parser->target = NULL;
6059
397
            njs_parser_next(parser, njs_parser_expression);
6060
397
            goto expression_after;
6061
31.9k
        } else if (ret == NJS_ERROR) {
6062
0
            return NJS_ERROR;
6063
0
        }
6064
6065
31.9k
        parser->target = NULL;
6066
31.9k
        njs_parser_next(parser, njs_parser_left_hand_side_expression);
6067
6068
        /*
6069
         * Here we pass not a node, but a token, this is important.
6070
         * This is necessary for correct error output.
6071
         */
6072
6073
31.9k
        text = njs_mp_alloc(parser->vm->mem_pool, sizeof(njs_str_t));
6074
31.9k
        if (text == NULL) {
6075
0
            return NJS_ERROR;
6076
0
        }
6077
6078
31.9k
        *text = token->text;
6079
6080
31.9k
        ret = njs_parser_after(parser, current, text, 0,
6081
31.9k
                               njs_parser_for_expression_map_reparse);
6082
31.9k
        if (ret != NJS_OK) {
6083
0
            return NJS_ERROR;
6084
0
        }
6085
6086
31.9k
        return njs_parser_after(parser, current, text, 1,
6087
62.9k
                                njs_parser_for_expression_map_continue);
6088
62.9k
    }
6089
6090
2.62k
expression_after:
6091
6092
    /*
6093
     * Here we pass not a node, but a token, this is important.
6094
     * This is necessary for correct error output.
6095
     */
6096
6097
2.62k
    text = njs_mp_alloc(parser->vm->mem_pool, sizeof(njs_str_t));
6098
2.62k
    if (text == NULL) {
6099
0
        return NJS_ERROR;
6100
0
    }
6101
6102
2.62k
    *text = token->text;
6103
6104
2.62k
    return njs_parser_after(parser, current, text, 1,
6105
2.62k
                            njs_parser_for_var_in_of_expression);
6106
2.62k
}
6107
6108
6109
static njs_int_t
6110
njs_parser_for_var_binding_or_var_list(njs_parser_t *parser,
6111
    njs_lexer_token_t *token, njs_queue_link_t *current,
6112
    njs_token_type_t token_type)
6113
17.4k
{
6114
17.4k
    njs_int_t            ret;
6115
17.4k
    njs_lexer_token_t    *next;
6116
17.4k
    njs_parser_node_t    *node, *var, *node_type, *statement;
6117
17.4k
    njs_variable_type_t  type;
6118
6119
17.4k
    switch (token_type) {
6120
217
    case NJS_TOKEN_LET:
6121
217
        type = NJS_VARIABLE_LET;
6122
217
        break;
6123
6124
160
    case NJS_TOKEN_CONST:
6125
160
        type = NJS_VARIABLE_CONST;
6126
160
        break;
6127
6128
17.0k
    default:
6129
17.0k
        type = NJS_VARIABLE_VAR;
6130
17.0k
        break;
6131
17.4k
    }
6132
6133
17.4k
    switch (token->type) {
6134
    /* BindingPattern */
6135
253
    case NJS_TOKEN_OPEN_BRACE:
6136
253
        njs_parser_next(parser, njs_parser_object_binding_pattern);
6137
253
        return NJS_DONE;
6138
6139
134
    case NJS_TOKEN_OPEN_BRACKET:
6140
134
        njs_parser_next(parser, njs_parser_array_binding_pattern);
6141
134
        return NJS_DONE;
6142
6143
17.0k
    default:
6144
17.0k
        if (njs_lexer_token_is_binding_identifier(token)) {
6145
14.1k
            if (njs_parser_restricted_identifier(token->type)) {
6146
937
                njs_parser_syntax_error(parser, "Identifier \"%V\" is forbidden"
6147
937
                                        " in var declaration", &token->text);
6148
937
                return NJS_DONE;
6149
937
            }
6150
6151
13.2k
            next = njs_lexer_peek_token(parser->lexer, token, 0);
6152
13.2k
            if (next == NULL) {
6153
0
                return NJS_ERROR;
6154
0
            }
6155
6156
13.2k
            if (next->type != NJS_TOKEN_IN) {
6157
2.06k
                parser->var_type = type;
6158
6159
2.06k
                njs_lexer_in_fail_set(parser->lexer, 1);
6160
6161
2.06k
                njs_parser_next(parser, njs_parser_variable_declaration_list);
6162
2.06k
                return NJS_OK;
6163
2.06k
            }
6164
6165
11.1k
            statement = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
6166
11.1k
            if (njs_slow_path(statement == NULL)) {
6167
0
                return NJS_ERROR;
6168
0
            }
6169
6170
11.1k
            node_type = njs_parser_node_new(parser, token_type);
6171
11.1k
            if (njs_slow_path(node_type == NULL)) {
6172
0
                return NJS_ERROR;
6173
0
            }
6174
6175
11.1k
            var = njs_parser_variable_node(parser, token->atom_id, type, NULL);
6176
11.1k
            if (var == NULL) {
6177
67
                return NJS_ERROR;
6178
67
            }
6179
6180
11.0k
            node_type->token_line = token->line;
6181
11.0k
            var->token_line = token->line;
6182
6183
11.0k
            statement->right = node_type;
6184
11.0k
            node_type->left = var;
6185
11.0k
            parser->node = NULL;
6186
6187
11.0k
            node = njs_parser_node_new(parser, NJS_TOKEN_IN);
6188
11.0k
            if (node == NULL) {
6189
0
                return NJS_ERROR;
6190
0
            }
6191
6192
11.0k
            node->token_line = next->line;
6193
11.0k
            node->left = statement;
6194
6195
11.0k
            njs_parser_next(parser, njs_parser_expression);
6196
6197
11.0k
            ret = njs_parser_after(parser, current, node, 1,
6198
11.0k
                                   njs_parser_for_var_in_statement);
6199
11.0k
            if (ret != NJS_OK) {
6200
0
                return NJS_ERROR;
6201
0
            }
6202
6203
11.0k
            njs_lexer_consume_token(parser->lexer, 2);
6204
6205
11.0k
            return NJS_DONE;
6206
6207
11.0k
        } else {
6208
2.93k
            return njs_parser_failed(parser);
6209
2.93k
        }
6210
17.4k
    }
6211
17.4k
}
6212
6213
6214
static njs_int_t
6215
njs_parser_for_var_in_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6216
    njs_queue_link_t *current)
6217
11.0k
{
6218
11.0k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
6219
141
        return njs_parser_failed(parser);
6220
141
    }
6221
6222
10.8k
    njs_lexer_consume_token(parser->lexer, 1);
6223
6224
10.8k
    parser->target->right = parser->node;
6225
10.8k
    parser->node = NULL;
6226
6227
10.8k
    njs_parser_next(parser, njs_parser_statement_wo_node);
6228
6229
10.8k
    return njs_parser_after(parser, current, parser->target, 1,
6230
11.0k
                            njs_parser_for_var_in_statement_after);
6231
11.0k
}
6232
6233
6234
static njs_int_t
6235
njs_parser_for_var_in_statement_after(njs_parser_t *parser,
6236
    njs_lexer_token_t *token, njs_queue_link_t *current)
6237
10.8k
{
6238
10.8k
    njs_parser_node_t  *foreach;
6239
6240
10.8k
    foreach = njs_parser_node_new(parser, NJS_TOKEN_FOR_IN);
6241
10.8k
    if (foreach == NULL) {
6242
0
        return NJS_ERROR;
6243
0
    }
6244
6245
10.8k
    foreach->left = parser->target;
6246
10.8k
    foreach->right = parser->node;
6247
6248
10.8k
    parser->node = foreach;
6249
6250
10.8k
    return njs_parser_stack_pop(parser);
6251
10.8k
}
6252
6253
6254
static njs_int_t
6255
njs_parser_for_var_in_of_expression(njs_parser_t *parser,
6256
    njs_lexer_token_t *token, njs_queue_link_t *current)
6257
18.5k
{
6258
18.5k
    njs_str_t          *text;
6259
18.5k
    njs_parser_node_t  *node;
6260
6261
    /*
6262
     * ";" <Expression>? ";" <Expression>? ")" <Statement>
6263
     * "in" <Expression> ")" <Statement>
6264
     * "of" <AssignmentExpression> ")" <Statement>
6265
     */
6266
6267
18.5k
    if (token->type != NJS_TOKEN_SEMICOLON &&
6268
4.11k
        token->type != NJS_TOKEN_CLOSE_PARENTHESIS &&
6269
3.10k
        parser->node != NULL && parser->node->token_type == NJS_TOKEN_IN)
6270
1.87k
    {
6271
1.87k
        node = parser->node->left;
6272
6273
1.87k
        if (!njs_parser_is_lvalue(node)) {
6274
6275
144
            text = (njs_str_t *) parser->target;
6276
6277
144
            njs_parser_ref_error(parser, "Invalid left-hand side \"%V\" "
6278
144
                                 "in for-in statement", text);
6279
6280
144
            njs_mp_free(parser->vm->mem_pool, text);
6281
6282
144
            return NJS_DONE;
6283
144
        }
6284
6285
1.73k
        node = njs_parser_lvalue_ref(node);
6286
1.73k
        if (node == NULL) {
6287
0
            return NJS_ERROR;
6288
0
        }
6289
6290
1.73k
        parser->node->left = node;
6291
6292
1.73k
        njs_parser_next(parser, njs_parser_for_in_statement);
6293
1.73k
        return NJS_OK;
6294
1.73k
    }
6295
6296
16.6k
    if (parser->target != NULL) {
6297
16.6k
        text = (njs_str_t *) parser->target;
6298
6299
16.6k
        njs_mp_free(parser->vm->mem_pool, text);
6300
16.6k
    }
6301
6302
16.6k
    switch (token->type) {
6303
14.4k
    case NJS_TOKEN_SEMICOLON:
6304
14.4k
        njs_lexer_in_fail_set(parser->lexer, 0);
6305
6306
14.4k
        token = njs_lexer_peek_token(parser->lexer, token, 0);
6307
14.4k
        if (token == NULL) {
6308
0
            return NJS_ERROR;
6309
0
        }
6310
6311
14.4k
        node = parser->node;
6312
14.4k
        parser->node = NULL;
6313
6314
14.4k
        if (token->type != NJS_TOKEN_SEMICOLON) {
6315
9.85k
            njs_lexer_consume_token(parser->lexer, 1);
6316
6317
9.85k
            njs_parser_next(parser, njs_parser_expression);
6318
6319
9.85k
            return njs_parser_after(parser, current, node, 1,
6320
9.85k
                                    njs_parser_for_expression);
6321
9.85k
        }
6322
6323
4.55k
        parser->target = node;
6324
6325
4.55k
        njs_lexer_consume_token(parser->lexer, 1);
6326
4.55k
        njs_parser_next(parser, njs_parser_for_expression);
6327
6328
4.55k
        return NJS_OK;
6329
6330
191
    case NJS_TOKEN_OF:
6331
191
        return njs_parser_not_supported(parser, token);
6332
6333
2.04k
    default:
6334
2.04k
        return njs_parser_failed(parser);
6335
16.6k
    }
6336
16.6k
}
6337
6338
6339
static njs_int_t
6340
njs_parser_for_in_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6341
    njs_queue_link_t *current)
6342
1.73k
{
6343
1.73k
    njs_parser_node_t  *node, *forin;
6344
6345
1.73k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
6346
1.73k
        return njs_parser_failed(parser);
6347
1.73k
    }
6348
6349
0
    njs_lexer_consume_token(parser->lexer, 1);
6350
6351
0
    node = parser->node;
6352
6353
0
    if (node->right != NULL && node->right->token_type == NJS_TOKEN_VAR) {
6354
0
        return NJS_ERROR;
6355
0
    }
6356
6357
0
    forin = njs_parser_node_new(parser, NJS_TOKEN_FOR_IN);
6358
0
    if (forin == NULL) {
6359
0
        return NJS_ERROR;
6360
0
    }
6361
6362
0
    forin->left = parser->node;
6363
6364
0
    parser->node = NULL;
6365
6366
0
    njs_parser_next(parser, njs_parser_statement_wo_node);
6367
6368
0
    return njs_parser_after(parser, current, forin, 1,
6369
0
                            njs_parser_for_in_statement_after);
6370
0
}
6371
6372
6373
static njs_int_t
6374
njs_parser_for_in_statement_statement(njs_parser_t *parser,
6375
    njs_lexer_token_t *token, njs_queue_link_t *current)
6376
11.2k
{
6377
11.2k
    njs_parser_node_t  *forin;
6378
6379
11.2k
    if (parser->ret != NJS_OK || token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
6380
382
        return njs_parser_failed(parser);
6381
382
    }
6382
6383
10.9k
    njs_lexer_consume_token(parser->lexer, 1);
6384
6385
10.9k
    parser->target->right = parser->node;
6386
6387
10.9k
    forin = njs_parser_node_new(parser, NJS_TOKEN_FOR_IN);
6388
10.9k
    if (forin == NULL) {
6389
0
        return NJS_ERROR;
6390
0
    }
6391
6392
10.9k
    forin->left = parser->target;
6393
6394
10.9k
    parser->node = NULL;
6395
6396
10.9k
    njs_parser_next(parser, njs_parser_statement_wo_node);
6397
6398
10.9k
    return njs_parser_after(parser, current, forin, 1,
6399
10.9k
                            njs_parser_for_in_statement_after);
6400
10.9k
}
6401
6402
6403
static njs_int_t
6404
njs_parser_for_in_statement_after(njs_parser_t *parser,
6405
    njs_lexer_token_t *token, njs_queue_link_t *current)
6406
10.7k
{
6407
10.7k
    return njs_parser_right_link_pop(parser);
6408
10.7k
}
6409
6410
6411
static njs_int_t
6412
njs_parser_for_expression(njs_parser_t *parser, njs_lexer_token_t *token,
6413
    njs_queue_link_t *current)
6414
27.1k
{
6415
27.1k
    njs_parser_node_t  *body, *cond, *for_node;
6416
6417
27.1k
    if (token->type != NJS_TOKEN_SEMICOLON) {
6418
205
        return njs_parser_failed(parser);
6419
205
    }
6420
6421
26.9k
    njs_lexer_consume_token(parser->lexer, 1);
6422
6423
26.9k
    for_node = njs_parser_node_new(parser, NJS_TOKEN_FOR);
6424
26.9k
    if (for_node == NULL) {
6425
0
        return NJS_ERROR;
6426
0
    }
6427
6428
26.9k
    cond = njs_parser_node_new(parser, 0);
6429
26.9k
    if (cond == NULL) {
6430
0
        return NJS_ERROR;
6431
0
    }
6432
6433
26.9k
    body = njs_parser_node_new(parser, 0);
6434
26.9k
    if (body == NULL) {
6435
0
        return NJS_ERROR;
6436
0
    }
6437
6438
26.9k
    for_node->left = parser->target;
6439
26.9k
    for_node->right = cond;
6440
6441
26.9k
    cond->left = parser->node;
6442
26.9k
    cond->right = body;
6443
6444
26.9k
    parser->node = NULL;
6445
6446
26.9k
    token = njs_lexer_token(parser->lexer, 0);
6447
26.9k
    if (token == NULL) {
6448
0
        return NJS_ERROR;
6449
0
    }
6450
6451
26.9k
    if (token->type == NJS_TOKEN_CLOSE_PARENTHESIS) {
6452
5.48k
        parser->target = for_node;
6453
6454
5.48k
        njs_parser_next(parser, njs_parser_for_expression_end);
6455
6456
5.48k
        return NJS_OK;
6457
5.48k
    }
6458
6459
21.5k
    njs_parser_next(parser, njs_parser_expression);
6460
6461
21.5k
    return njs_parser_after(parser, current, for_node, 1,
6462
26.9k
                            njs_parser_for_expression_end);
6463
26.9k
}
6464
6465
6466
static njs_int_t
6467
njs_parser_for_expression_end(njs_parser_t *parser, njs_lexer_token_t *token,
6468
    njs_queue_link_t *current)
6469
26.9k
{
6470
26.9k
    njs_parser_node_t  *body;
6471
6472
26.9k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
6473
7
        return njs_parser_failed(parser);
6474
7
    }
6475
6476
26.9k
    njs_lexer_consume_token(parser->lexer, 1);
6477
6478
26.9k
    body = parser->target->right->right;
6479
6480
26.9k
    body->right = parser->node;
6481
6482
26.9k
    parser->node = NULL;
6483
6484
26.9k
    njs_parser_next(parser, njs_parser_statement_wo_node);
6485
6486
26.9k
    return njs_parser_after(parser, current, parser->target, 1,
6487
26.9k
                            njs_parser_for_end);
6488
26.9k
}
6489
6490
6491
static njs_int_t
6492
njs_parser_for_end(njs_parser_t *parser, njs_lexer_token_t *token,
6493
    njs_queue_link_t *current)
6494
23.4k
{
6495
23.4k
    njs_parser_node_t  *body;
6496
6497
23.4k
    body = parser->target->right->right;
6498
6499
23.4k
    body->left = parser->node;
6500
23.4k
    parser->node = parser->target;
6501
6502
23.4k
    return njs_parser_stack_pop(parser);
6503
23.4k
}
6504
6505
6506
/*
6507
 * 13.8 continue Statement.
6508
 */
6509
static njs_int_t
6510
njs_parser_continue_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6511
    njs_queue_link_t *current)
6512
8.38k
{
6513
8.38k
    return njs_parser_break_continue(parser, token, NJS_TOKEN_CONTINUE);
6514
8.38k
}
6515
6516
6517
/*
6518
 * 13.9 break Statement.
6519
 */
6520
static njs_int_t
6521
njs_parser_break_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6522
    njs_queue_link_t *current)
6523
31.8k
{
6524
31.8k
    return njs_parser_break_continue(parser, token, NJS_TOKEN_BREAK);
6525
31.8k
}
6526
6527
6528
static njs_int_t
6529
njs_parser_break_continue(njs_parser_t *parser, njs_lexer_token_t *token,
6530
    njs_token_type_t type)
6531
40.2k
{
6532
40.2k
    njs_int_t  ret;
6533
6534
40.2k
    parser->node = njs_parser_node_new(parser, type);
6535
40.2k
    if (parser->node == NULL) {
6536
0
        return NJS_ERROR;
6537
0
    }
6538
6539
40.2k
    parser->node->token_line = parser->line;
6540
6541
40.2k
    switch (token->type) {
6542
4.28k
    case NJS_TOKEN_SEMICOLON:
6543
4.28k
        break;
6544
6545
0
    case NJS_TOKEN_LINE_END:
6546
0
        return njs_parser_failed(parser);
6547
6548
35.9k
    default:
6549
35.9k
        if (njs_lexer_token_is_label_identifier(token)) {
6550
15.9k
            if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) {
6551
15.5k
                return njs_parser_stack_pop(parser);
6552
15.5k
            }
6553
6554
390
            if (njs_label_find(parser->vm, parser->scope, token->atom_id)
6555
390
                == NULL)
6556
246
            {
6557
246
                njs_parser_syntax_error(parser, "Undefined label \"%V\"",
6558
246
                                        &token->text);
6559
246
                return NJS_DONE;
6560
246
            }
6561
6562
144
            ret = njs_name_copy(parser->vm, &parser->node->name, &token->text);
6563
144
            if (ret != NJS_OK) {
6564
0
                return NJS_ERROR;
6565
0
            }
6566
6567
144
            break;
6568
144
        }
6569
6570
20.0k
        if (token->type != NJS_TOKEN_END
6571
20.0k
            && token->type != NJS_TOKEN_CLOSE_BRACE
6572
4.24k
            && parser->lexer->prev_type != NJS_TOKEN_LINE_END)
6573
441
        {
6574
441
            return njs_parser_failed(parser);
6575
441
        }
6576
6577
19.6k
        return njs_parser_stack_pop(parser);
6578
40.2k
    }
6579
6580
4.42k
    njs_lexer_consume_token(parser->lexer, 1);
6581
6582
4.42k
    return njs_parser_stack_pop(parser);
6583
40.2k
}
6584
6585
6586
/*
6587
 * 13.10 return Statement.
6588
 */
6589
static njs_int_t
6590
njs_parser_return_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6591
    njs_queue_link_t *current)
6592
15.2k
{
6593
15.2k
    njs_parser_node_t   *node;
6594
15.2k
    njs_parser_scope_t  *scope;
6595
6596
15.2k
    for (scope = parser->scope;
6597
55.3k
         scope != NULL;
6598
40.0k
         scope = scope->parent)
6599
55.3k
    {
6600
55.3k
        if (scope->type == NJS_SCOPE_FUNCTION) {
6601
15.0k
            break;
6602
15.0k
        }
6603
6604
40.2k
        if (scope->parent == NULL) {
6605
130
            njs_parser_syntax_error(parser, "Illegal return statement");
6606
130
            return NJS_ERROR;
6607
130
        }
6608
40.2k
    }
6609
6610
15.0k
    node = njs_parser_node_new(parser, NJS_TOKEN_RETURN);
6611
15.0k
    if (njs_slow_path(node == NULL)) {
6612
0
        return NJS_ERROR;
6613
0
    }
6614
6615
15.0k
    node->token_line = parser->line;
6616
6617
15.0k
    switch (token->type) {
6618
509
    case NJS_TOKEN_SEMICOLON:
6619
509
        njs_lexer_consume_token(parser->lexer, 1);
6620
509
        break;
6621
6622
0
    case NJS_TOKEN_LINE_END:
6623
0
        return njs_parser_failed(parser);
6624
6625
14.5k
    default:
6626
14.5k
        if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) {
6627
4.22k
            break;
6628
4.22k
        }
6629
6630
10.3k
        parser->node = NULL;
6631
6632
10.3k
        if (token->type != NJS_TOKEN_CLOSE_BRACE) {
6633
7.00k
            njs_parser_next(parser, njs_parser_expression);
6634
6635
7.00k
            return njs_parser_after(parser, current, node, 0,
6636
7.00k
                                    njs_parser_return_statement_after);
6637
7.00k
        }
6638
15.0k
    }
6639
6640
8.08k
    parser->node = node;
6641
6642
8.08k
    return njs_parser_stack_pop(parser);
6643
15.0k
}
6644
6645
6646
static njs_int_t
6647
njs_parser_return_statement_after(njs_parser_t *parser,
6648
    njs_lexer_token_t *token, njs_queue_link_t *current)
6649
7.00k
{
6650
7.00k
    if (parser->ret != NJS_OK) {
6651
330
        njs_parser_syntax_error(parser, "Unexpected token \"%V\"",
6652
330
                                &token->text);
6653
330
        return NJS_DONE;
6654
330
    }
6655
6656
6.67k
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
6657
12
        return njs_parser_failed(parser);
6658
12
    }
6659
6660
6.66k
    return njs_parser_right_link_pop(parser);
6661
6.67k
}
6662
6663
6664
/*
6665
 * 13.11 with Statement
6666
 */
6667
static njs_int_t
6668
njs_parser_with_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6669
    njs_queue_link_t *current)
6670
940
{
6671
940
    return njs_parser_not_supported(parser, token);
6672
940
}
6673
6674
6675
/*
6676
 * 13.12 switch Statement
6677
 */
6678
static njs_int_t
6679
njs_parser_switch_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6680
    njs_queue_link_t *current)
6681
11.2k
{
6682
11.2k
    njs_int_t          ret;
6683
11.2k
    njs_parser_node_t  *swtch;
6684
6685
11.2k
    swtch = njs_parser_node_new(parser, NJS_TOKEN_SWITCH);
6686
11.2k
    if (swtch == NULL) {
6687
0
        return NJS_ERROR;
6688
0
    }
6689
6690
11.2k
    swtch->token_line = parser->line;
6691
6692
11.2k
    njs_parser_next(parser, njs_parser_expression_parenthesis);
6693
6694
11.2k
    ret = njs_parser_after(parser, current, swtch, 1,
6695
11.2k
                           njs_parser_switch_block);
6696
11.2k
    if (ret != NJS_OK) {
6697
0
        return ret;
6698
0
    }
6699
6700
11.2k
    return njs_parser_after(parser, current, swtch, 1,
6701
11.2k
                            njs_parser_switch_statement_after);
6702
11.2k
}
6703
6704
6705
static njs_int_t
6706
njs_parser_switch_statement_after(njs_parser_t *parser,
6707
    njs_lexer_token_t *token, njs_queue_link_t *current)
6708
5.99k
{
6709
5.99k
    parser->node = parser->target;
6710
6711
5.99k
    return njs_parser_stack_pop(parser);
6712
5.99k
}
6713
6714
6715
static njs_int_t
6716
njs_parser_switch_block(njs_parser_t *parser, njs_lexer_token_t *token,
6717
    njs_queue_link_t *current)
6718
10.5k
{
6719
10.5k
    njs_int_t  ret;
6720
6721
10.5k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
6722
148
        return njs_parser_failed(parser);
6723
148
    }
6724
6725
10.3k
    njs_lexer_consume_token(parser->lexer, 1);
6726
6727
10.3k
    parser->target->left = parser->node;
6728
6729
10.3k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK, 0);
6730
10.3k
    if (ret != NJS_OK) {
6731
0
        return NJS_ERROR;
6732
0
    }
6733
6734
10.3k
    njs_parser_next(parser, njs_parser_switch_case);
6735
6736
10.3k
    return njs_parser_after(parser, current, NULL, 1,
6737
10.3k
                            njs_parser_switch_block_after);
6738
10.3k
}
6739
6740
static njs_int_t
6741
njs_parser_switch_block_after(njs_parser_t *parser, njs_lexer_token_t *token,
6742
    njs_queue_link_t *current)
6743
5.99k
{
6744
5.99k
    njs_parser_scope_end(parser);
6745
6746
5.99k
    return njs_parser_stack_pop(parser);
6747
5.99k
}
6748
6749
6750
static njs_int_t
6751
njs_parser_switch_case(njs_parser_t *parser, njs_lexer_token_t *token,
6752
    njs_queue_link_t *current)
6753
19.1k
{
6754
19.1k
    return njs_parser_switch_case_def(parser, token, current, 1);
6755
19.1k
}
6756
6757
6758
static njs_int_t
6759
njs_parser_switch_case_wo_def(njs_parser_t *parser, njs_lexer_token_t *token,
6760
    njs_queue_link_t *current)
6761
5.66k
{
6762
5.66k
    return njs_parser_switch_case_def(parser, token, current, 0);
6763
5.66k
}
6764
6765
6766
static njs_int_t
6767
njs_parser_switch_case_def(njs_parser_t *parser, njs_lexer_token_t *token,
6768
    njs_queue_link_t *current, njs_bool_t with_default)
6769
24.8k
{
6770
24.8k
    njs_parser_node_t  *node, *branch;
6771
6772
24.8k
    node = njs_parser_node_new(parser, 0);
6773
24.8k
    if (node == NULL) {
6774
0
        return NJS_ERROR;
6775
0
    }
6776
6777
24.8k
    parser->node = NULL;
6778
6779
24.8k
    switch (token->type) {
6780
13.7k
    case NJS_TOKEN_CASE:
6781
13.7k
        branch = njs_parser_node_new(parser, 0);
6782
13.7k
        if (branch == NULL) {
6783
0
            return NJS_ERROR;
6784
0
        }
6785
6786
13.7k
        branch->token_line = token->line;
6787
13.7k
        branch->right = node;
6788
6789
13.7k
        njs_parser_next(parser, njs_parser_expression);
6790
6791
13.7k
        njs_lexer_consume_token(parser->lexer, 1);
6792
6793
13.7k
        if (parser->target->token_type == NJS_TOKEN_SWITCH) {
6794
8.73k
            parser->target->right = branch;
6795
6796
8.73k
        } else {
6797
4.98k
            parser->target->left = branch;
6798
4.98k
        }
6799
6800
13.7k
        if (with_default) {
6801
11.1k
            return njs_parser_after(parser, current, branch, 1,
6802
11.1k
                                    njs_parser_switch_case_after);
6803
6804
11.1k
        } else {
6805
2.58k
            return njs_parser_after(parser, current, branch, 1,
6806
2.58k
                                    njs_parser_switch_case_after_wo_def);
6807
2.58k
        }
6808
6809
4.78k
    case NJS_TOKEN_DEFAULT:
6810
4.78k
        if (!with_default) {
6811
506
            njs_parser_syntax_error(parser, "More than one default clause "
6812
506
                                            "in switch statement");
6813
506
            return NJS_DONE;
6814
506
        }
6815
6816
4.28k
        if (parser->target->token_type == NJS_TOKEN_SWITCH) {
6817
1.40k
            parser->target->right = node;
6818
6819
2.87k
        } else {
6820
2.87k
            parser->target->left = node;
6821
2.87k
        }
6822
6823
4.28k
        node->token_line = token->line;
6824
4.28k
        node->token_type = NJS_TOKEN_DEFAULT;
6825
6826
4.28k
        parser->target = node;
6827
6828
4.28k
        njs_lexer_consume_token(parser->lexer, 1);
6829
4.28k
        njs_parser_next(parser, njs_parser_switch_case_after_wo_def);
6830
6831
4.28k
        break;
6832
6833
5.99k
    case NJS_TOKEN_CLOSE_BRACE:
6834
5.99k
        njs_lexer_consume_token(parser->lexer, 1);
6835
5.99k
        return njs_parser_stack_pop(parser);
6836
6837
314
    default:
6838
314
        return njs_parser_failed(parser);
6839
24.8k
    }
6840
6841
4.28k
    return NJS_OK;
6842
24.8k
}
6843
6844
6845
static njs_int_t
6846
njs_parser_switch_case_after(njs_parser_t *parser, njs_lexer_token_t *token,
6847
    njs_queue_link_t *current)
6848
10.5k
{
6849
10.5k
    if (token->type != NJS_TOKEN_COLON) {
6850
346
        return njs_parser_failed(parser);
6851
346
    }
6852
6853
10.1k
    njs_lexer_consume_token(parser->lexer, 1);
6854
6855
10.1k
    parser->target->right->left = parser->node;
6856
10.1k
    parser->node = NULL;
6857
6858
10.1k
    token = njs_lexer_token(parser->lexer, 0);
6859
10.1k
    if (token == NULL) {
6860
0
        return NJS_ERROR;
6861
0
    }
6862
6863
10.1k
    switch (token->type) {
6864
249
    case NJS_TOKEN_CASE:
6865
1.67k
    case NJS_TOKEN_DEFAULT:
6866
2.80k
    case NJS_TOKEN_CLOSE_BRACE:
6867
2.80k
        njs_parser_next(parser, njs_parser_switch_case_block);
6868
2.80k
        return NJS_OK;
6869
6870
7.35k
    default:
6871
7.35k
        njs_parser_next(parser, njs_parser_statement_list);
6872
7.35k
        break;
6873
10.1k
    }
6874
6875
7.35k
    return njs_parser_after(parser, current, parser->target, 1,
6876
10.1k
                            njs_parser_switch_case_block);
6877
10.1k
}
6878
6879
6880
static njs_int_t
6881
njs_parser_switch_case_block(njs_parser_t *parser, njs_lexer_token_t *token,
6882
    njs_queue_link_t *current)
6883
9.39k
{
6884
9.39k
    parser->target->right->right = parser->node;
6885
6886
9.39k
    if (parser->ret != NJS_OK && parser->target->scope != parser->scope) {
6887
634
        return njs_parser_failed(parser);
6888
634
    }
6889
6890
8.76k
    njs_parser_next(parser, njs_parser_switch_case);
6891
6892
8.76k
    return NJS_OK;
6893
9.39k
}
6894
6895
6896
static njs_int_t
6897
njs_parser_switch_case_after_wo_def(njs_parser_t *parser,
6898
    njs_lexer_token_t *token, njs_queue_link_t *current)
6899
6.62k
{
6900
6.62k
    if (token->type != NJS_TOKEN_COLON) {
6901
730
        return njs_parser_failed(parser);
6902
730
    }
6903
6904
5.89k
    njs_lexer_consume_token(parser->lexer, 1);
6905
6906
5.89k
    if (parser->target->right != NULL) {
6907
1.61k
        parser->target->right->left = parser->node;
6908
1.61k
    }
6909
6910
5.89k
    parser->node = NULL;
6911
6912
5.89k
    token = njs_lexer_token(parser->lexer, 0);
6913
5.89k
    if (token == NULL) {
6914
0
        return NJS_ERROR;
6915
0
    }
6916
6917
5.89k
    switch (token->type) {
6918
1.71k
    case NJS_TOKEN_CASE:
6919
2.21k
    case NJS_TOKEN_DEFAULT:
6920
3.09k
    case NJS_TOKEN_CLOSE_BRACE:
6921
3.09k
        njs_parser_next(parser, njs_parser_switch_case_block_wo_def);
6922
3.09k
        return NJS_OK;
6923
6924
2.79k
    default:
6925
2.79k
        njs_parser_next(parser, njs_parser_statement_list);
6926
2.79k
        break;
6927
5.89k
    }
6928
6929
2.79k
    return njs_parser_after(parser, current, parser->target, 1,
6930
5.89k
                            njs_parser_switch_case_block_wo_def);
6931
5.89k
}
6932
6933
6934
static njs_int_t
6935
njs_parser_switch_case_block_wo_def(njs_parser_t *parser,
6936
    njs_lexer_token_t *token, njs_queue_link_t *current)
6937
5.89k
{
6938
5.89k
    if (parser->target->right != NULL) {
6939
1.61k
        parser->target->right->right = parser->node;
6940
6941
4.27k
    } else {
6942
4.27k
        parser->target->right = parser->node;
6943
4.27k
    }
6944
6945
5.89k
    if (parser->ret != NJS_OK && parser->target->scope != parser->scope) {
6946
229
        return njs_parser_failed(parser);
6947
229
    }
6948
6949
5.66k
    njs_parser_next(parser, njs_parser_switch_case_wo_def);
6950
6951
5.66k
    return NJS_OK;
6952
5.89k
}
6953
6954
6955
/*
6956
 * 13.13 Labelled Statements
6957
 */
6958
static njs_int_t
6959
njs_parser_labelled_statement(njs_parser_t *parser, njs_lexer_token_t *token,
6960
    njs_queue_link_t *current)
6961
64.9k
{
6962
64.9k
    uintptr_t       atom_id;
6963
64.9k
    njs_variable_t  *label;
6964
6965
64.9k
    atom_id = token->atom_id;
6966
6967
64.9k
    label = njs_label_find(parser->vm, parser->scope, atom_id);
6968
64.9k
    if (label != NULL) {
6969
143
        njs_parser_syntax_error(parser, "Label \"%V\" "
6970
143
                                "has already been declared", &token->text);
6971
143
        return NJS_DONE;
6972
143
    }
6973
6974
64.8k
    label = njs_label_add(parser->vm, parser->scope, atom_id);
6975
64.8k
    if (label == NULL) {
6976
0
        return NJS_ERROR;
6977
0
    }
6978
6979
64.8k
    njs_lexer_consume_token(parser->lexer, 2);
6980
6981
64.8k
    token = njs_lexer_token(parser->lexer, 0);
6982
64.8k
    if (token == NULL) {
6983
0
        return NJS_ERROR;
6984
0
    }
6985
6986
64.8k
    parser->node = NULL;
6987
6988
64.8k
    if (token->type == NJS_TOKEN_FUNCTION) {
6989
148
        njs_syntax_error(parser->vm, "In strict mode code, functions can only "
6990
148
                                "be declared at top level or inside a block.");
6991
148
        return NJS_DONE;
6992
6993
64.6k
    } else {
6994
64.6k
        njs_parser_next(parser, njs_parser_statement_wo_node);
6995
64.6k
    }
6996
6997
64.6k
    return njs_parser_after(parser, current, (void *) atom_id, 1,
6998
64.8k
                            njs_parser_labelled_statement_after);
6999
64.8k
}
7000
7001
7002
static njs_int_t
7003
njs_parser_labelled_statement_after(njs_parser_t *parser,
7004
    njs_lexer_token_t *token, njs_queue_link_t *current)
7005
57.1k
{
7006
57.1k
    njs_int_t          ret;
7007
57.1k
    njs_str_t          str;
7008
57.1k
    uintptr_t          atom_id;
7009
57.1k
    njs_parser_node_t  *node;
7010
7011
57.1k
    node = parser->node;
7012
57.1k
    if (node == NULL) {
7013
1.65k
        node = njs_parser_node_new(parser, NJS_TOKEN_BLOCK);
7014
1.65k
        if (node == NULL) {
7015
0
            return NJS_ERROR;
7016
0
        }
7017
7018
1.65k
        node->token_line = token->line;
7019
7020
1.65k
        parser->node = node;
7021
1.65k
    }
7022
7023
57.1k
    atom_id = (uint32_t) (uintptr_t) parser->target;
7024
7025
57.1k
    njs_atom_string_get(parser->vm, atom_id, &str);
7026
7027
57.1k
    ret = njs_name_copy(parser->vm, &parser->node->name, &str);
7028
57.1k
    if (ret != NJS_OK) {
7029
0
        return NJS_ERROR;
7030
0
    }
7031
7032
57.1k
    ret = njs_label_remove(parser->vm, parser->scope, atom_id);
7033
57.1k
    if (ret != NJS_OK) {
7034
0
        return NJS_ERROR;
7035
0
    }
7036
7037
57.1k
    return njs_parser_stack_pop(parser);
7038
57.1k
}
7039
7040
7041
/*
7042
 * 13.14 throw Statement
7043
 */
7044
static njs_int_t
7045
njs_parser_throw_statement(njs_parser_t *parser, njs_lexer_token_t *token,
7046
    njs_queue_link_t *current)
7047
14.3k
{
7048
14.3k
    njs_parser_node_t  *node;
7049
7050
14.3k
    node = njs_parser_node_new(parser, NJS_TOKEN_THROW);
7051
14.3k
    if (node == NULL) {
7052
0
        return NJS_ERROR;
7053
0
    }
7054
7055
14.3k
    node->token_line = parser->line;
7056
7057
14.3k
    if (parser->lexer->prev_type == NJS_TOKEN_LINE_END) {
7058
1.09k
        njs_parser_syntax_error(parser, "Illegal newline after throw");
7059
1.09k
        return NJS_DONE;
7060
1.09k
    }
7061
7062
13.2k
    parser->node = NULL;
7063
7064
13.2k
    njs_parser_next(parser, njs_parser_expression);
7065
7066
13.2k
    return njs_parser_after(parser, current, node, 1,
7067
14.3k
                            njs_parser_throw_statement_after);
7068
14.3k
}
7069
7070
7071
static njs_int_t
7072
njs_parser_throw_statement_after(njs_parser_t *parser,
7073
    njs_lexer_token_t *token, njs_queue_link_t *current)
7074
13.0k
{
7075
13.0k
    if (parser->ret != NJS_OK) {
7076
0
        parser->node = parser->target;
7077
0
        return njs_parser_reject(parser);
7078
0
    }
7079
7080
13.0k
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
7081
148
        return njs_parser_failed(parser);
7082
148
    }
7083
7084
12.9k
    return njs_parser_right_link_pop(parser);
7085
13.0k
}
7086
7087
7088
/*
7089
 * 13.15 try Statement.
7090
 */
7091
static njs_int_t
7092
njs_parser_try_statement(njs_parser_t *parser, njs_lexer_token_t *token,
7093
    njs_queue_link_t *current)
7094
45.5k
{
7095
45.5k
    njs_parser_node_t  *try;
7096
7097
45.5k
    try = njs_parser_node_new(parser, NJS_TOKEN_TRY);
7098
45.5k
    if (try == NULL) {
7099
0
        return NJS_ERROR;
7100
0
    }
7101
7102
45.5k
    try->token_line = parser->line;
7103
7104
45.5k
    parser->node = NULL;
7105
7106
45.5k
    njs_parser_next(parser, njs_parser_block_statement_open_brace);
7107
7108
45.5k
    return njs_parser_after(parser, current, try, 1,
7109
45.5k
                            njs_parser_catch_or_finally);
7110
45.5k
}
7111
7112
7113
static njs_int_t
7114
njs_parser_catch_or_finally(njs_parser_t *parser, njs_lexer_token_t *token,
7115
    njs_queue_link_t *current)
7116
40.5k
{
7117
40.5k
    njs_int_t          ret;
7118
40.5k
    njs_parser_node_t  *catch, *node, *try;
7119
7120
40.5k
    try = parser->target;
7121
7122
40.5k
    try->left = parser->node;
7123
7124
40.5k
    if (token->type == NJS_TOKEN_FINALLY) {
7125
4.76k
        node = njs_parser_node_new(parser, NJS_TOKEN_FINALLY);
7126
4.76k
        if (node == NULL) {
7127
0
            return NJS_ERROR;
7128
0
        }
7129
7130
4.76k
        node->token_line = token->line;
7131
7132
4.76k
        if (try->right != NULL) {
7133
0
            node->left = try->right;
7134
0
        }
7135
7136
4.76k
        try->right = node;
7137
4.76k
        parser->node = NULL;
7138
7139
4.76k
        njs_lexer_consume_token(parser->lexer, 1);
7140
4.76k
        njs_parser_next(parser, njs_parser_block_statement_open_brace);
7141
7142
4.76k
        return njs_parser_after(parser, current, try, 0,
7143
4.76k
                                njs_parser_catch_finally);
7144
7145
35.8k
    } else if (token->type != NJS_TOKEN_CATCH) {
7146
520
        njs_parser_syntax_error(parser, "Missing catch or finally after try");
7147
520
        return NJS_DONE;
7148
520
    }
7149
7150
35.3k
    catch = njs_parser_node_new(parser, NJS_TOKEN_CATCH);
7151
35.3k
    if (catch == NULL) {
7152
0
        return NJS_ERROR;
7153
0
    }
7154
7155
35.3k
    catch->token_line = token->line;
7156
7157
35.3k
    njs_lexer_consume_token(parser->lexer, 1);
7158
7159
35.3k
    token = njs_lexer_token(parser->lexer, 0);
7160
35.3k
    if (token == NULL) {
7161
0
        return NJS_ERROR;
7162
0
    }
7163
7164
35.3k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_BLOCK, 0);
7165
35.3k
    if (ret != NJS_OK) {
7166
0
        return NJS_ERROR;
7167
0
    }
7168
7169
35.3k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
7170
269
        parser->node = NULL;
7171
7172
269
        njs_parser_next(parser, njs_parser_block_statement_open_brace);
7173
7174
269
        try->right = catch;
7175
7176
        /* TODO: it is necessary to change the generator. */
7177
7178
269
        return njs_parser_not_supported(parser, token);
7179
7180
        /*
7181
         *  return njs_parser_after(parser, current, parser->target, 0,
7182
         *                          njs_parser_catch_after);
7183
         */
7184
269
    }
7185
7186
35.0k
    njs_lexer_consume_token(parser->lexer, 1);
7187
7188
35.0k
    token = njs_lexer_token(parser->lexer, 0);
7189
35.0k
    if (token == NULL) {
7190
0
        return NJS_ERROR;
7191
0
    }
7192
7193
35.0k
    try->right = catch;
7194
7195
35.0k
    if (njs_lexer_token_is_binding_identifier(token)) {
7196
31.3k
        node = njs_parser_variable_node(parser, token->atom_id,
7197
31.3k
                                        NJS_VARIABLE_CATCH, NULL);
7198
31.3k
        if (node == NULL) {
7199
0
            return NJS_ERROR;
7200
0
        }
7201
7202
31.3k
        node->token_line = token->line;
7203
7204
31.3k
        catch->left = node;
7205
7206
31.3k
        njs_lexer_consume_token(parser->lexer, 1);
7207
31.3k
        njs_parser_next(parser, njs_parser_catch_parenthesis);
7208
31.3k
        return NJS_OK;
7209
31.3k
    }
7210
7211
3.65k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
7212
3.49k
        return njs_parser_failed(parser);
7213
3.49k
    }
7214
7215
    /*
7216
     * njs_parser_next(parser, njs_parser_block_statement_open_brace);
7217
     *
7218
     * return njs_parser_after(parser, current, try, 1,
7219
     *                       njs_parser_catch_parenthesis);
7220
     */
7221
7222
157
    return njs_parser_not_supported(parser, token);
7223
3.65k
}
7224
7225
7226
static njs_int_t
7227
njs_parser_catch_after(njs_parser_t *parser, njs_lexer_token_t *token,
7228
    njs_queue_link_t *current)
7229
30.5k
{
7230
30.5k
    njs_parser_node_t  *node;
7231
7232
30.5k
    parser->target->right->right = parser->node;
7233
7234
30.5k
    if (token->type == NJS_TOKEN_FINALLY) {
7235
7.20k
        node = njs_parser_node_new(parser, NJS_TOKEN_FINALLY);
7236
7.20k
        if (node == NULL) {
7237
0
            return NJS_ERROR;
7238
0
        }
7239
7240
7.20k
        node->token_line = token->line;
7241
7242
7.20k
        if (parser->target->right != NULL) {
7243
7.20k
            node->left = parser->target->right;
7244
7.20k
        }
7245
7246
7.20k
        parser->target->right = node;
7247
7.20k
        parser->node = NULL;
7248
7249
7.20k
        njs_lexer_consume_token(parser->lexer, 1);
7250
7.20k
        njs_parser_next(parser, njs_parser_block_statement_open_brace);
7251
7252
7.20k
        return njs_parser_after(parser, current, parser->target, 1,
7253
7.20k
                                njs_parser_catch_finally);
7254
7.20k
    }
7255
7256
23.3k
    parser->node = parser->target;
7257
7258
23.3k
    return njs_parser_stack_pop(parser);
7259
30.5k
}
7260
7261
7262
static njs_int_t
7263
njs_parser_catch_parenthesis(njs_parser_t *parser, njs_lexer_token_t *token,
7264
    njs_queue_link_t *current)
7265
31.3k
{
7266
31.3k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
7267
267
        return njs_parser_failed(parser);
7268
267
    }
7269
7270
31.1k
    njs_lexer_consume_token(parser->lexer, 1);
7271
7272
31.1k
    parser->target->right->right = parser->node;
7273
31.1k
    parser->node = NULL;
7274
7275
31.1k
    njs_parser_next(parser, njs_parser_catch_statement_open_brace);
7276
7277
31.1k
    return njs_parser_after(parser, current, parser->target, 1,
7278
31.3k
                            njs_parser_catch_after);
7279
31.3k
}
7280
7281
7282
static njs_int_t
7283
njs_parser_catch_statement_open_brace(njs_parser_t *parser,
7284
    njs_lexer_token_t *token, njs_queue_link_t *current)
7285
31.1k
{
7286
31.1k
    void  *target;
7287
7288
31.1k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
7289
45
        return njs_parser_failed(parser);
7290
45
    }
7291
7292
31.0k
    parser->line = token->line;
7293
7294
31.0k
    njs_lexer_consume_token(parser->lexer, 1);
7295
7296
31.0k
    token = njs_lexer_token(parser->lexer, 0);
7297
31.0k
    if (token == NULL) {
7298
0
        return NJS_ERROR;
7299
0
    }
7300
7301
31.0k
    target = (void *) (uintptr_t) parser->line;
7302
31.0k
    parser->node = NULL;
7303
7304
31.0k
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
7305
22.6k
        parser->target = target;
7306
7307
22.6k
        njs_parser_next(parser, njs_parser_block_statement_close_brace);
7308
22.6k
        return NJS_OK;
7309
22.6k
    }
7310
7311
8.41k
    njs_parser_next(parser, njs_parser_statement_list);
7312
7313
8.41k
    return njs_parser_after(parser, current, target, 0,
7314
31.0k
                            njs_parser_block_statement_close_brace);
7315
31.0k
}
7316
7317
7318
static njs_int_t
7319
njs_parser_catch_finally(njs_parser_t *parser, njs_lexer_token_t *token,
7320
    njs_queue_link_t *current)
7321
11.9k
{
7322
11.9k
    if (parser->ret != NJS_OK) {
7323
0
        return njs_parser_failed(parser);
7324
0
    }
7325
7326
11.9k
    parser->target->right->right = parser->node;
7327
11.9k
    parser->node = parser->target;
7328
7329
11.9k
    return njs_parser_stack_pop(parser);
7330
11.9k
}
7331
7332
7333
static njs_int_t
7334
njs_parser_debugger_statement(njs_parser_t *parser, njs_lexer_token_t *token,
7335
    njs_queue_link_t *current)
7336
9.26k
{
7337
9.26k
    parser->node = njs_parser_node_new(parser, NJS_TOKEN_DEBUGGER);
7338
9.26k
    if (parser->node == NULL) {
7339
0
        return NJS_ERROR;
7340
0
    }
7341
7342
9.26k
    parser->node->token_line = parser->line;
7343
7344
9.26k
    if (token->type != NJS_TOKEN_SEMICOLON
7345
516
        && token->type != NJS_TOKEN_END)
7346
516
    {
7347
516
        return njs_parser_failed(parser);
7348
516
    }
7349
7350
8.74k
    njs_lexer_consume_token(parser->lexer, 1);
7351
7352
8.74k
    return njs_parser_stack_pop(parser);
7353
9.26k
}
7354
7355
7356
/*
7357
 * 14.1 Function Definitions.
7358
 */
7359
static njs_int_t
7360
njs_parser_function_declaration(njs_parser_t *parser, njs_lexer_token_t *token,
7361
    njs_queue_link_t *current)
7362
8.47k
{
7363
8.47k
    njs_int_t          ret;
7364
8.47k
    uintptr_t          atom_id;
7365
8.47k
    njs_bool_t         async;
7366
8.47k
    njs_variable_t     *var;
7367
8.47k
    njs_parser_node_t  *node;
7368
7369
8.47k
    if (!njs_lexer_token_is_binding_identifier(token)) {
7370
2.22k
        return njs_parser_failed(parser);
7371
2.22k
    }
7372
7373
6.25k
    if (njs_parser_restricted_identifier(token->type)) {
7374
167
        njs_parser_syntax_error(parser, "Identifier \"%V\" is forbidden"
7375
167
                                " in function declaration", &token->text);
7376
167
        return NJS_DONE;
7377
167
    }
7378
7379
6.08k
    node = parser->node;
7380
6.08k
    atom_id = token->atom_id;
7381
7382
6.08k
    njs_lexer_consume_token(parser->lexer, 1);
7383
7384
6.08k
    token = njs_lexer_token(parser->lexer, 0);
7385
6.08k
    if (token == NULL) {
7386
0
        return NJS_ERROR;
7387
0
    }
7388
7389
6.08k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
7390
1.25k
        return njs_parser_failed(parser);
7391
1.25k
    }
7392
7393
4.83k
    njs_lexer_consume_token(parser->lexer, 1);
7394
7395
4.83k
    var = njs_variable_function_add(parser, parser->scope, atom_id);
7396
4.83k
    if (var == NULL) {
7397
228
        return NJS_ERROR;
7398
228
    }
7399
7400
4.60k
    node->u.value.data.u.lambda = njs_variable_lambda(var);
7401
7402
4.60k
    node->left = (njs_parser_node_t *) atom_id;
7403
7404
4.60k
    parser->node = node;
7405
7406
4.60k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_FUNCTION, 1);
7407
4.60k
    if (ret != NJS_OK) {
7408
0
        return NJS_ERROR;
7409
0
    }
7410
7411
4.60k
    async = (node->token_type == NJS_TOKEN_ASYNC_FUNCTION_DECLARATION);
7412
4.60k
    parser->scope->async = async;
7413
7414
4.60k
    njs_parser_next(parser, njs_parser_function_parse);
7415
7416
4.60k
    return njs_parser_after(parser, current, node, 1,
7417
4.60k
                            njs_parser_function_declaration_after);
7418
4.60k
}
7419
7420
7421
static njs_int_t
7422
njs_parser_function_declaration_after(njs_parser_t *parser,
7423
    njs_lexer_token_t *token, njs_queue_link_t *current)
7424
4.59k
{
7425
4.59k
    njs_int_t  ret;
7426
4.59k
    uintptr_t  atom_id;
7427
7428
4.59k
    atom_id = (uint32_t) (uintptr_t) parser->node->left;
7429
7430
4.59k
    parser->node->left = NULL;
7431
7432
4.59k
    njs_value_null_set(&parser->node->u.value);
7433
7434
4.59k
    ret = njs_parser_variable_reference(parser, parser->scope, parser->node,
7435
4.59k
                                        atom_id, NJS_DECLARATION);
7436
4.59k
    if (ret != NJS_OK) {
7437
0
        return NJS_ERROR;
7438
0
    }
7439
7440
4.59k
    return njs_parser_stack_pop(parser);
7441
4.59k
}
7442
7443
7444
static njs_int_t
7445
njs_parser_function_parse(njs_parser_t *parser, njs_lexer_token_t *token,
7446
    njs_queue_link_t *current)
7447
263k
{
7448
263k
    parser->target = parser->node;
7449
263k
    parser->node = NULL;
7450
7451
263k
    njs_parser_next(parser, njs_parser_formal_parameters);
7452
7453
263k
    return njs_parser_after(parser, current, parser->target, 1,
7454
263k
                            njs_parser_function_lambda_args_after);
7455
263k
}
7456
7457
7458
static njs_int_t
7459
njs_parser_function_expression(njs_parser_t *parser, njs_lexer_token_t *token,
7460
    njs_queue_link_t *current)
7461
260k
{
7462
260k
    njs_int_t              ret;
7463
260k
    uintptr_t              atom_id;
7464
260k
    njs_bool_t             async;
7465
260k
    njs_variable_t         *var;
7466
260k
    njs_function_lambda_t  *lambda;
7467
7468
260k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_FUNCTION, 1);
7469
260k
    if (ret != NJS_OK) {
7470
0
        return NJS_ERROR;
7471
0
    }
7472
7473
260k
    async = (parser->node->token_type == NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION);
7474
260k
    parser->scope->async = async;
7475
7476
260k
    var = NULL;
7477
7478
260k
    if (njs_lexer_token_is_binding_identifier(token)) {
7479
5.29k
        atom_id = token->atom_id;
7480
7481
5.29k
        njs_lexer_consume_token(parser->lexer, 1);
7482
7483
5.29k
        token = njs_lexer_token(parser->lexer, 0);
7484
5.29k
        if (token == NULL) {
7485
0
            return NJS_ERROR;
7486
0
        }
7487
7488
255k
    } else {
7489
255k
        atom_id = NJS_ATOM_STRING_empty;
7490
255k
    }
7491
7492
260k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
7493
1.25k
        return njs_parser_failed(parser);
7494
1.25k
    }
7495
7496
259k
    njs_lexer_consume_token(parser->lexer, 1);
7497
7498
259k
    parser->node->left = njs_parser_node_new(parser, NJS_TOKEN_NAME);
7499
259k
    if (parser->node->left == NULL) {
7500
0
        return NJS_ERROR;
7501
0
    }
7502
7503
259k
    var = njs_variable_scope_add(parser, parser->scope, parser->scope,
7504
259k
                                 atom_id, NJS_VARIABLE_FUNCTION, 1);
7505
259k
    if (var == NULL) {
7506
0
        return NJS_ERROR;
7507
0
    }
7508
7509
259k
    var->self = 1;
7510
7511
259k
    ret = njs_parser_variable_reference(parser, parser->scope,
7512
259k
                                        parser->node->left, atom_id,
7513
259k
                                        NJS_DECLARATION);
7514
259k
    if (ret != NJS_OK) {
7515
0
        return NJS_ERROR;
7516
0
    }
7517
7518
259k
    lambda = njs_function_lambda_alloc(parser->vm, !async);
7519
259k
    if (lambda == NULL) {
7520
0
        return NJS_ERROR;
7521
0
    }
7522
7523
259k
    parser->node->u.value.data.u.lambda = lambda;
7524
7525
259k
    njs_parser_next(parser, njs_parser_function_parse);
7526
7527
259k
    return njs_parser_after(parser, current, var, 1,
7528
259k
                            njs_parser_function_expression_after);
7529
259k
}
7530
7531
7532
static njs_int_t
7533
njs_parser_function_expression_after(njs_parser_t *parser,
7534
    njs_lexer_token_t *token, njs_queue_link_t *current)
7535
138k
{
7536
138k
    njs_variable_t  *var;
7537
7538
138k
    var = (njs_variable_t *) parser->target;
7539
7540
138k
    if (var->self) {
7541
137k
        var->init = 1;
7542
137k
        var->type = NJS_VARIABLE_CONST;
7543
137k
    }
7544
7545
138k
    var->index = njs_scope_index(var->scope->type, var->scope->items,
7546
138k
                                 NJS_LEVEL_LOCAL, var->type);
7547
138k
    var->scope->items++;
7548
7549
138k
    if (var->self) {
7550
137k
        parser->node->u.value.data.u.lambda->self = var->index;
7551
137k
    }
7552
7553
138k
    return njs_parser_stack_pop(parser);
7554
138k
}
7555
7556
7557
static njs_int_t
7558
njs_parser_unique_formal_parameters(njs_parser_t *parser,
7559
    njs_lexer_token_t *token, njs_queue_link_t *current)
7560
10.6k
{
7561
10.6k
    parser->node = NULL;
7562
7563
10.6k
    njs_parser_next(parser, njs_parser_formal_parameters);
7564
7565
10.6k
    return NJS_OK;
7566
10.6k
}
7567
7568
7569
static njs_int_t
7570
njs_parser_formal_parameters(njs_parser_t *parser, njs_lexer_token_t *token,
7571
    njs_queue_link_t *current)
7572
309k
{
7573
309k
    njs_variable_t         *arg;
7574
309k
    njs_rbtree_node_t      *rb_node;
7575
309k
    njs_variable_node_t    var_node;
7576
309k
    njs_function_lambda_t  *lambda;
7577
7578
309k
    lambda = parser->target->u.value.data.u.lambda;
7579
7580
309k
    switch (token->type) {
7581
    /* BindingRestElement */
7582
2.23k
    case NJS_TOKEN_ELLIPSIS:
7583
2.23k
        if (lambda->rest_parameters != 0) {
7584
0
            return njs_parser_failed(parser);
7585
0
        }
7586
7587
2.23k
        njs_lexer_consume_token(parser->lexer, 1);
7588
7589
2.23k
        token = njs_lexer_token(parser->lexer, 0);
7590
2.23k
        if (token == NULL) {
7591
0
            return NJS_ERROR;
7592
0
        }
7593
7594
2.23k
        if (!njs_lexer_token_is_binding_identifier(token)) {
7595
157
            return njs_parser_failed(parser);
7596
157
        }
7597
7598
2.07k
        lambda->rest_parameters = 1;
7599
7600
2.07k
        return NJS_OK;
7601
7602
    /* BindingElement */
7603
268
    case NJS_TOKEN_OPEN_BRACE:
7604
268
        return njs_parser_not_supported(parser, token);
7605
7606
131
    case NJS_TOKEN_OPEN_BRACKET:
7607
131
        return njs_parser_not_supported(parser, token);
7608
7609
306k
    default:
7610
        /* SingleNameBinding */
7611
306k
        if (njs_lexer_token_is_binding_identifier(token)) {
7612
44.1k
            var_node.key = token->atom_id;
7613
7614
44.1k
            rb_node = njs_rbtree_find(&parser->scope->variables,
7615
44.1k
                                      &var_node.node);
7616
44.1k
            if (rb_node != NULL) {
7617
1.04k
                arg = ((njs_variable_node_t *) rb_node)->variable;
7618
7619
1.04k
                if (!arg->self) {
7620
128
                    njs_parser_syntax_error(parser,
7621
128
                                            "Duplicate parameter names");
7622
128
                    return NJS_DONE;
7623
128
                }
7624
7625
918
                arg->self = 0;
7626
7627
43.0k
            } else {
7628
43.0k
                arg = njs_variable_add(parser, parser->scope,
7629
43.0k
                                       token->atom_id, NJS_VARIABLE_VAR);
7630
43.0k
            }
7631
7632
43.9k
            if (arg == NULL) {
7633
0
                return NJS_ERROR;
7634
0
            }
7635
7636
43.9k
            arg->argument = 1;
7637
7638
43.9k
            lambda->nargs++;
7639
7640
            /* Crutch for temporary storage. */
7641
43.9k
            parser->node = (njs_parser_node_t *) arg;
7642
7643
43.9k
            njs_lexer_consume_token(parser->lexer, 1);
7644
7645
43.9k
            njs_parser_next(parser, njs_parser_formal_parameters_after);
7646
43.9k
            break;
7647
43.9k
        }
7648
7649
262k
        return njs_parser_stack_pop(parser);
7650
309k
    }
7651
7652
43.9k
    return NJS_OK;
7653
309k
}
7654
7655
7656
static njs_int_t
7657
njs_parser_formal_parameters_after(njs_parser_t *parser,
7658
    njs_lexer_token_t *token, njs_queue_link_t *current)
7659
43.9k
{
7660
43.9k
    njs_function_lambda_t  *lambda;
7661
7662
43.9k
    if (token->type != NJS_TOKEN_COMMA) {
7663
38.6k
        return njs_parser_stack_pop(parser);
7664
38.6k
    }
7665
7666
5.35k
    lambda = parser->target->u.value.data.u.lambda;
7667
7668
5.35k
    if (lambda->rest_parameters) {
7669
147
        njs_parser_syntax_error(parser, "Rest parameter must be "
7670
147
                                        "last formal parameter");
7671
147
        return NJS_DONE;
7672
147
    }
7673
7674
5.21k
    njs_lexer_consume_token(parser->lexer, 1);
7675
7676
5.21k
    njs_parser_next(parser, njs_parser_formal_parameters);
7677
7678
5.21k
    return NJS_OK;
7679
5.35k
}
7680
7681
7682
/*
7683
 * 14.2 Arrow Function Definitions
7684
 *
7685
 * TODO: implement according to specification.
7686
 */
7687
static njs_int_t
7688
njs_parser_arrow_function(njs_parser_t *parser, njs_lexer_token_t *token,
7689
    njs_queue_link_t *current)
7690
370k
{
7691
370k
    njs_int_t              ret;
7692
370k
    njs_bool_t             async;
7693
370k
    njs_variable_t         *arg, *var;
7694
370k
    njs_parser_node_t      *node, *name;
7695
370k
    njs_function_lambda_t  *lambda;
7696
7697
370k
    if (token->type == NJS_TOKEN_ASYNC) {
7698
1.62k
        njs_lexer_consume_token(parser->lexer, 1);
7699
7700
1.62k
        token = njs_lexer_token(parser->lexer, 0);
7701
1.62k
        if (token == NULL) {
7702
0
            return NJS_ERROR;
7703
0
        }
7704
7705
1.62k
        async = 1;
7706
1.62k
        node = njs_parser_node_new(parser, NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION);
7707
7708
368k
    } else {
7709
368k
        async = 0;
7710
368k
        node = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION_EXPRESSION);
7711
368k
    }
7712
7713
370k
    if (node == NULL) {
7714
0
        return NJS_ERROR;
7715
0
    }
7716
7717
370k
    node->token_line = token->line;
7718
370k
    parser->node = node;
7719
7720
370k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_FUNCTION, 0);
7721
370k
    if (ret != NJS_OK) {
7722
0
        return NJS_ERROR;
7723
0
    }
7724
7725
370k
    parser->scope->async = async;
7726
7727
370k
    name = njs_parser_node_new(parser, NJS_TOKEN_NAME);
7728
370k
    if (name == NULL) {
7729
0
        return NJS_ERROR;
7730
0
    }
7731
7732
370k
    node->left = name;
7733
7734
370k
    var = njs_variable_scope_add(parser, parser->scope, parser->scope,
7735
370k
                                 NJS_ATOM_STRING_empty, NJS_VARIABLE_FUNCTION,
7736
370k
                                 1);
7737
370k
    if (var == NULL) {
7738
0
        return NJS_ERROR;
7739
0
    }
7740
7741
370k
    ret = njs_parser_variable_reference(parser, parser->scope, node->left,
7742
370k
                                        NJS_ATOM_STRING_empty, NJS_DECLARATION);
7743
370k
    if (ret != NJS_OK) {
7744
0
        return NJS_ERROR;
7745
0
    }
7746
7747
370k
    node->left->u.reference.variable = var;
7748
7749
370k
    lambda = njs_function_lambda_alloc(parser->vm, 0);
7750
370k
    if (lambda == NULL) {
7751
0
        return NJS_ERROR;
7752
0
    }
7753
7754
370k
    node->u.value.data.u.lambda = lambda;
7755
7756
370k
    parser->scope->arrow_function = 1;
7757
7758
370k
    if (token->type == NJS_TOKEN_OPEN_PARENTHESIS) {
7759
27.3k
        njs_lexer_consume_token(parser->lexer, 1);
7760
7761
27.3k
        parser->node = NULL;
7762
27.3k
        parser->target = node;
7763
7764
27.3k
        njs_parser_next(parser, njs_parser_formal_parameters);
7765
7766
27.3k
        return njs_parser_after(parser, current, node, 1,
7767
27.3k
                                njs_parser_arrow_function_args_after);
7768
7769
343k
    } else if (njs_lexer_token_is_binding_identifier(token)) {
7770
343k
        arg = njs_variable_add(parser, parser->scope, token->atom_id,
7771
343k
                               NJS_VARIABLE_VAR);
7772
343k
        if (arg == NULL) {
7773
0
            return NJS_ERROR;
7774
0
        }
7775
7776
343k
        arg->argument = 1;
7777
7778
343k
        var->index = njs_scope_index(parser->scope->type, parser->scope->items,
7779
343k
                                     NJS_LEVEL_LOCAL, NJS_VARIABLE_VAR);
7780
343k
        parser->scope->items++;
7781
7782
343k
        lambda->self = var->index;
7783
343k
        lambda->nargs++;
7784
7785
343k
        njs_lexer_consume_token(parser->lexer, 1);
7786
7787
343k
        parser->target = node;
7788
7789
343k
        njs_parser_next(parser, njs_parser_arrow_function_arrow);
7790
7791
343k
    } else {
7792
0
        return njs_parser_failed(parser);
7793
0
    }
7794
7795
343k
    return NJS_OK;
7796
370k
}
7797
7798
7799
static njs_int_t
7800
njs_parser_arrow_function_args_after(njs_parser_t *parser,
7801
    njs_lexer_token_t *token, njs_queue_link_t *current)
7802
27.3k
{
7803
27.3k
    njs_variable_t  *var, **vv;
7804
7805
27.3k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
7806
9.01k
        return njs_parser_failed(parser);
7807
9.01k
    }
7808
7809
18.2k
    njs_lexer_consume_token(parser->lexer, 1);
7810
7811
18.2k
    vv = &parser->target->left->u.reference.variable;
7812
7813
18.2k
    var = *vv;
7814
18.2k
    *vv = NULL;
7815
7816
18.2k
    var->index = njs_scope_index(var->scope->type, var->scope->items,
7817
18.2k
                                 NJS_LEVEL_LOCAL, NJS_VARIABLE_VAR);
7818
18.2k
    var->scope->items++;
7819
7820
18.2k
    parser->target->u.value.data.u.lambda->self = var->index;
7821
7822
18.2k
    njs_parser_next(parser, njs_parser_arrow_function_arrow);
7823
7824
18.2k
    return NJS_OK;
7825
27.3k
}
7826
7827
7828
static njs_int_t
7829
njs_parser_arrow_function_arrow(njs_parser_t *parser,
7830
    njs_lexer_token_t *token, njs_queue_link_t *current)
7831
361k
{
7832
361k
    if (token->type != NJS_TOKEN_ARROW) {
7833
0
        return njs_parser_failed(parser);
7834
0
    }
7835
7836
361k
    njs_lexer_consume_token(parser->lexer, 1);
7837
7838
361k
    token = njs_lexer_token(parser->lexer, 0);
7839
361k
    if (token == NULL) {
7840
0
        return NJS_ERROR;
7841
0
    }
7842
7843
361k
    if (token->type == NJS_TOKEN_OPEN_BRACE) {
7844
3.65k
        njs_lexer_consume_token(parser->lexer, 1);
7845
7846
3.65k
        token = njs_lexer_token(parser->lexer, 0);
7847
3.65k
        if (token == NULL) {
7848
0
            return NJS_ERROR;
7849
0
        }
7850
7851
3.65k
        if (token->type == NJS_TOKEN_CLOSE_BRACE) {
7852
72
            parser->node = NULL;
7853
7854
72
            njs_parser_next(parser, njs_parser_function_lambda_body_after);
7855
7856
72
            return NJS_OK;
7857
72
        }
7858
7859
3.58k
        parser->node = NULL;
7860
7861
3.58k
        njs_parser_next(parser, njs_parser_statement_list);
7862
7863
3.58k
        return njs_parser_after(parser, current, parser->target, 1,
7864
3.65k
                                njs_parser_function_lambda_body_after);
7865
3.65k
    }
7866
7867
357k
    parser->node = NULL;
7868
7869
357k
    njs_parser_next(parser, njs_parser_assignment_expression);
7870
7871
357k
    return njs_parser_after(parser, current, parser->target, 1,
7872
361k
                            njs_parser_arrow_function_body_after);
7873
361k
}
7874
7875
7876
static njs_int_t
7877
njs_parser_arrow_function_body_after(njs_parser_t *parser,
7878
    njs_lexer_token_t *token, njs_queue_link_t *current)
7879
340k
{
7880
340k
    njs_parser_node_t  *body;
7881
7882
340k
    body = njs_parser_return_set(parser, parser->node);
7883
340k
    if (body == NULL) {
7884
0
        return NJS_ERROR;
7885
0
    }
7886
7887
340k
    parser->target->right = body;
7888
340k
    parser->node = parser->target;
7889
7890
340k
    njs_parser_scope_end(parser);
7891
7892
340k
    return njs_parser_stack_pop(parser);
7893
340k
}
7894
7895
7896
/*
7897
 * 14.3 Method Definitions.
7898
 */
7899
static njs_int_t
7900
njs_parser_method_definition(njs_parser_t *parser, njs_lexer_token_t *token,
7901
    njs_queue_link_t *current)
7902
4.17k
{
7903
4.17k
    njs_token_type_t   type;
7904
4.17k
    njs_lexer_token_t  *next;
7905
4.17k
    njs_parser_node_t  *expr;
7906
7907
4.17k
    type = NJS_TOKEN_FUNCTION;
7908
7909
4.17k
    if (token->type == NJS_TOKEN_ASYNC) {
7910
151
        njs_lexer_consume_token(parser->lexer, 1);
7911
7912
151
        token = njs_lexer_token(parser->lexer, 0);
7913
151
        if (token == NULL) {
7914
0
            return NJS_ERROR;
7915
0
        }
7916
7917
151
        type = NJS_TOKEN_ASYNC_FUNCTION;
7918
151
    }
7919
7920
4.17k
    switch (token->type) {
7921
    /* PropertyName */
7922
0
    case NJS_TOKEN_STRING:
7923
132
    case NJS_TOKEN_ESCAPE_STRING:
7924
1.81k
    case NJS_TOKEN_NUMBER:
7925
1.81k
        break;
7926
7927
2.36k
    default:
7928
2.36k
        if (njs_lexer_token_is_identifier_name(token)) {
7929
2.36k
            break;
7930
2.36k
        }
7931
7932
0
        return njs_parser_failed(parser);
7933
4.17k
    }
7934
7935
4.17k
    njs_lexer_consume_token(parser->lexer, 1);
7936
7937
4.17k
    next = njs_lexer_token(parser->lexer, 0);
7938
4.17k
    if (next == NULL) {
7939
0
        return NJS_ERROR;
7940
0
    }
7941
7942
4.17k
    if (next->type != NJS_TOKEN_OPEN_PARENTHESIS) {
7943
0
        return njs_parser_failed(parser);
7944
0
    }
7945
7946
4.17k
    expr = njs_parser_node_new(parser, type);
7947
4.17k
    if (expr == NULL) {
7948
0
        return NJS_ERROR;
7949
0
    }
7950
7951
4.17k
    expr->token_line = next->line;
7952
7953
4.17k
    parser->node = expr;
7954
7955
4.17k
    njs_lexer_consume_token(parser->lexer, 1);
7956
4.17k
    njs_parser_next(parser, njs_parser_function_lambda);
7957
7958
4.17k
    return NJS_OK;
7959
4.17k
}
7960
7961
7962
static njs_int_t
7963
njs_parser_get_set(njs_parser_t *parser, njs_lexer_token_t *token,
7964
    njs_queue_link_t *current)
7965
7.38k
{
7966
7.38k
    njs_token_type_t   accessor;
7967
7.38k
    njs_lexer_token_t  *name;
7968
7.38k
    njs_parser_node_t  *property, *expression, *temp;
7969
7970
7.38k
    temp = parser->target;
7971
7.38k
    accessor = (njs_token_type_t) (uintptr_t) temp->right;
7972
7973
7.38k
    name = token;
7974
7975
7.38k
    token = njs_lexer_peek_token(parser->lexer, token, 0);
7976
7.38k
    if (token == NULL) {
7977
0
        return NJS_ERROR;
7978
0
    }
7979
7980
7.38k
    switch (token->type) {
7981
    /* IdentifierReference */
7982
2.99k
    case NJS_TOKEN_NAME:
7983
2.99k
    case NJS_TOKEN_STRING:
7984
4.12k
    case NJS_TOKEN_ESCAPE_STRING:
7985
4.27k
    case NJS_TOKEN_NUMBER:
7986
4.27k
        break;
7987
7988
507
    case NJS_TOKEN_OPEN_BRACKET:
7989
507
        njs_lexer_consume_token(parser->lexer, 2);
7990
7991
507
        njs_parser_next(parser, njs_parser_assignment_expression);
7992
7993
507
        return njs_parser_after(parser, current, temp, 1,
7994
4.12k
                                njs_parser_get_set_after);
7995
7996
2.60k
    default:
7997
2.60k
        if (njs_lexer_token_is_identifier_name(token)) {
7998
2.44k
            break;
7999
2.44k
        }
8000
8001
159
        return njs_parser_property_definition_ident(parser, name, temp);
8002
7.38k
    }
8003
8004
6.72k
    property = njs_parser_property_name_node(parser, token);
8005
6.72k
    if (property == NULL) {
8006
940
        return NJS_ERROR;
8007
940
    }
8008
8009
5.78k
    njs_lexer_consume_token(parser->lexer, 2);
8010
8011
5.78k
    token = njs_lexer_token(parser->lexer, 0);
8012
5.78k
    if (token == NULL) {
8013
0
        return NJS_ERROR;
8014
0
    }
8015
8016
5.78k
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
8017
184
        return njs_parser_failed(parser);
8018
184
    }
8019
8020
5.59k
    expression = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION);
8021
5.59k
    if (expression == NULL) {
8022
0
        return NJS_ERROR;
8023
0
    }
8024
8025
5.59k
    expression->token_line = token->line;
8026
8027
5.59k
    temp->right = property;
8028
8029
5.59k
    parser->node = expression;
8030
8031
5.59k
    njs_lexer_consume_token(parser->lexer, 1);
8032
5.59k
    njs_parser_next(parser, njs_parser_function_lambda);
8033
8034
5.59k
    if (accessor == NJS_TOKEN_PROPERTY_GETTER) {
8035
2.60k
        return njs_parser_after(parser, current, temp, 1, njs_parser_get_after);
8036
2.60k
    }
8037
8038
2.99k
    return njs_parser_after(parser, current, temp, 1, njs_parser_set_after);
8039
5.59k
}
8040
8041
8042
static njs_int_t
8043
njs_parser_get_set_after(njs_parser_t *parser, njs_lexer_token_t *token,
8044
    njs_queue_link_t *current)
8045
507
{
8046
507
    njs_token_type_t   accessor;
8047
507
    njs_parser_node_t  *expression, *temp;
8048
8049
507
    if (token->type != NJS_TOKEN_CLOSE_BRACKET) {
8050
161
        return njs_parser_failed(parser);
8051
161
    }
8052
8053
346
    njs_lexer_consume_token(parser->lexer, 1);
8054
8055
346
    token = njs_lexer_token(parser->lexer, 0);
8056
346
    if (token == NULL) {
8057
0
        return NJS_ERROR;
8058
0
    }
8059
8060
346
    if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
8061
128
        return njs_parser_failed(parser);
8062
128
    }
8063
8064
218
    expression = njs_parser_node_new(parser, NJS_TOKEN_FUNCTION);
8065
218
    if (expression == NULL) {
8066
0
        return NJS_ERROR;
8067
0
    }
8068
8069
218
    expression->token_line = token->line;
8070
8071
218
    temp = parser->target;
8072
8073
218
    accessor = (njs_token_type_t) (uintptr_t) temp->right;
8074
218
    temp->right = parser->node;
8075
8076
218
    parser->node = expression;
8077
8078
218
    njs_lexer_consume_token(parser->lexer, 1);
8079
218
    njs_parser_next(parser, njs_parser_function_lambda);
8080
8081
218
    if (accessor == NJS_TOKEN_PROPERTY_GETTER) {
8082
218
        return njs_parser_after(parser, current, temp, 1, njs_parser_get_after);
8083
218
    }
8084
8085
0
    return njs_parser_after(parser, current, temp, 1, njs_parser_set_after);
8086
218
}
8087
8088
8089
static njs_int_t
8090
njs_parser_get_after(njs_parser_t *parser, njs_lexer_token_t *token,
8091
    njs_queue_link_t *current)
8092
159
{
8093
159
    njs_int_t              ret;
8094
159
    njs_parser_node_t      *expression, *temp;
8095
159
    njs_function_lambda_t  *lambda;
8096
8097
159
    temp = parser->target;
8098
8099
159
    expression = parser->node;
8100
159
    lambda = expression->u.value.data.u.lambda;
8101
8102
159
    if (lambda->nargs != 0) {
8103
0
        njs_parser_syntax_error(parser,
8104
0
                                "Getter must not have any formal parameters");
8105
0
        return NJS_DONE;
8106
0
    }
8107
8108
159
    ret = njs_parser_property_accessor(parser, temp->left, temp->right,
8109
159
                                       expression, NJS_TOKEN_PROPERTY_GETTER);
8110
159
    if (ret != NJS_OK) {
8111
0
        return NJS_ERROR;
8112
0
    }
8113
8114
159
    parser->node = temp->left;
8115
159
    parser->target = NULL;
8116
8117
159
    return njs_parser_stack_pop(parser);
8118
159
}
8119
8120
8121
static njs_int_t
8122
njs_parser_set_after(njs_parser_t *parser, njs_lexer_token_t *token,
8123
    njs_queue_link_t *current)
8124
1.49k
{
8125
1.49k
    njs_int_t              ret;
8126
1.49k
    njs_parser_node_t      *expression, *temp;
8127
1.49k
    njs_function_lambda_t  *lambda;
8128
8129
1.49k
    temp = parser->target;
8130
8131
1.49k
    expression = parser->node;
8132
1.49k
    lambda = expression->u.value.data.u.lambda;
8133
8134
1.49k
    if (lambda->nargs != 1) {
8135
899
        njs_parser_syntax_error(parser,
8136
899
                               "Setter must have exactly one formal parameter");
8137
899
        return NJS_DONE;
8138
899
    }
8139
8140
593
    ret = njs_parser_property_accessor(parser, temp->left, temp->right,
8141
593
                                       expression, NJS_TOKEN_PROPERTY_SETTER);
8142
593
    if (ret != NJS_OK) {
8143
0
        return NJS_ERROR;
8144
0
    }
8145
8146
593
    parser->node = temp->left;
8147
593
    parser->target = NULL;
8148
8149
593
    return njs_parser_stack_pop(parser);
8150
593
}
8151
8152
8153
static njs_int_t
8154
njs_parser_function_lambda(njs_parser_t *parser,
8155
    njs_lexer_token_t *token, njs_queue_link_t *current)
8156
10.6k
{
8157
10.6k
    njs_int_t              ret;
8158
10.6k
    njs_parser_node_t      *expr;
8159
10.6k
    njs_function_lambda_t  *lambda;
8160
8161
10.6k
    lambda = njs_function_lambda_alloc(parser->vm, 0);
8162
10.6k
    if (lambda == NULL) {
8163
0
        return NJS_ERROR;
8164
0
    }
8165
8166
10.6k
    expr = parser->node;
8167
10.6k
    expr->u.value.data.u.lambda = lambda;
8168
8169
10.6k
    ret = njs_parser_scope_begin(parser, NJS_SCOPE_FUNCTION, 1);
8170
10.6k
    if (ret != NJS_OK) {
8171
0
        return NJS_ERROR;
8172
0
    }
8173
8174
10.6k
    parser->scope->async =
8175
10.6k
                        (parser->node->token_type == NJS_TOKEN_ASYNC_FUNCTION);
8176
8177
10.6k
    parser->node = NULL;
8178
10.6k
    parser->target = expr;
8179
8180
10.6k
    njs_parser_next(parser, njs_parser_unique_formal_parameters);
8181
8182
10.6k
    return njs_parser_after(parser, current, expr, 1,
8183
10.6k
                            njs_parser_function_lambda_args_after);
8184
10.6k
}
8185
8186
8187
static njs_int_t
8188
njs_parser_function_lambda_args_after(njs_parser_t *parser,
8189
    njs_lexer_token_t *token, njs_queue_link_t *current)
8190
273k
{
8191
273k
    if (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
8192
4.15k
        return njs_parser_failed(parser);
8193
4.15k
    }
8194
8195
269k
    njs_lexer_consume_token(parser->lexer, 1);
8196
8197
269k
    token = njs_lexer_token(parser->lexer, 0);
8198
269k
    if (token == NULL) {
8199
0
        return NJS_ERROR;
8200
0
    }
8201
8202
269k
    if (token->type != NJS_TOKEN_OPEN_BRACE) {
8203
143
        return njs_parser_failed(parser);
8204
143
    }
8205
8206
269k
    njs_lexer_consume_token(parser->lexer, 1);
8207
8208
269k
    token = njs_lexer_token(parser->lexer, 0);
8209
269k
    if (token == NULL) {
8210
0
        return NJS_ERROR;
8211
0
    }
8212
8213
269k
    if (token->type == NJS_TOKEN_CLOSE_BRACE) {
8214
6.32k
        parser->node = NULL;
8215
8216
6.32k
        njs_parser_next(parser, njs_parser_function_lambda_body_after);
8217
8218
6.32k
        return NJS_OK;
8219
6.32k
    }
8220
8221
263k
    parser->node = NULL;
8222
8223
263k
    njs_parser_next(parser, njs_parser_statement_list);
8224
8225
263k
    return njs_parser_after(parser, current, parser->target, 1,
8226
269k
                            njs_parser_function_lambda_body_after);
8227
269k
}
8228
8229
8230
static njs_int_t
8231
njs_parser_function_lambda_body_after(njs_parser_t *parser,
8232
    njs_lexer_token_t *token, njs_queue_link_t *current)
8233
154k
{
8234
154k
    njs_parser_node_t *body, *last, *parent;
8235
8236
154k
    if (token->type != NJS_TOKEN_CLOSE_BRACE) {
8237
6.71k
        return njs_parser_failed(parser);
8238
6.71k
    }
8239
8240
147k
    parent = parser->target;
8241
8242
147k
    last = NULL;
8243
147k
    body = njs_parser_chain_top(parser);
8244
8245
147k
    if (body != NULL) {
8246
        /* Take the last function body statement. */
8247
140k
        last = body->right;
8248
8249
140k
        if (last == NULL) {
8250
            /*
8251
             * The last statement is terminated by semicolon.
8252
             * Take the last statement itself.
8253
             */
8254
0
            last = body->left;
8255
0
        }
8256
140k
    }
8257
8258
147k
    if (last == NULL || last->token_type != NJS_TOKEN_RETURN) {
8259
        /*
8260
         * There is no function body or the last function body
8261
         * body statement is not "return" statement.
8262
         */
8263
146k
        body = njs_parser_return_set(parser, NULL);
8264
146k
        if (body == NULL) {
8265
0
            return NJS_ERROR;
8266
0
        }
8267
8268
146k
        body->right->token_line = token->line;
8269
146k
    }
8270
8271
147k
    parent->right = body;
8272
147k
    parser->node = parent;
8273
8274
147k
    njs_parser_scope_end(parser);
8275
8276
147k
    njs_lexer_consume_token(parser->lexer, 1);
8277
8278
147k
    return njs_parser_stack_pop(parser);
8279
147k
}
8280
8281
8282
static njs_int_t
8283
njs_parser_export(njs_parser_t *parser, njs_lexer_token_t *token,
8284
    njs_queue_link_t *current)
8285
979
{
8286
979
    njs_parser_node_t  *node;
8287
979
    njs_lexer_token_t  *peek;
8288
8289
979
    static const njs_str_t  as_string = njs_str("as");
8290
8291
979
    if (!parser->module) {
8292
979
        njs_parser_syntax_error(parser, "Illegal export statement");
8293
979
        return NJS_DONE;
8294
979
    }
8295
8296
0
    if (token->type != NJS_TOKEN_DEFAULT) {
8297
8298
0
        if (token->type != NJS_TOKEN_OPEN_BRACE) {
8299
0
            njs_parser_syntax_error(parser,
8300
0
                                    "Non-default export is not supported");
8301
0
            return NJS_DONE;
8302
0
        }
8303
8304
        /*
8305
         * 'export {'
8306
         *    supported only: export {identifier as default};
8307
         */
8308
8309
0
        njs_lexer_consume_token(parser->lexer, 1);
8310
8311
0
        token = njs_lexer_token(parser->lexer, 0);
8312
0
        if (njs_slow_path(token == NULL)) {
8313
0
            return NJS_ERROR;
8314
0
        }
8315
8316
0
        if (token->type != NJS_TOKEN_NAME) {
8317
0
            njs_parser_syntax_error(parser, "Identifier expected");
8318
0
            return NJS_DONE;
8319
0
        }
8320
8321
0
        peek = njs_lexer_peek_token(parser->lexer, token, 0);
8322
0
        if (njs_slow_path(peek == NULL)) {
8323
0
            return NJS_ERROR;
8324
0
        }
8325
8326
0
        if (peek->type != NJS_TOKEN_NAME ||
8327
0
            !njs_strstr_eq(&peek->text, &as_string))
8328
0
        {
8329
0
            njs_parser_syntax_error(parser, "'as' expected");
8330
0
            return NJS_DONE;
8331
0
        }
8332
8333
0
        peek = njs_lexer_peek_token(parser->lexer, peek, 0);
8334
0
        if (njs_slow_path(peek == NULL)) {
8335
0
            return NJS_ERROR;
8336
0
        }
8337
8338
0
        if (peek->type != NJS_TOKEN_DEFAULT) {
8339
0
            njs_parser_syntax_error(parser,
8340
0
                                    "Non-default export is not supported");
8341
0
            return NJS_DONE;
8342
0
        }
8343
8344
0
        peek = njs_lexer_peek_token(parser->lexer, peek, 0);
8345
0
        if (njs_slow_path(peek == NULL)) {
8346
0
            return NJS_ERROR;
8347
0
        }
8348
8349
0
        if (peek->type != NJS_TOKEN_CLOSE_BRACE) {
8350
0
            njs_parser_syntax_error(parser, "Close brace is expected");
8351
0
            return NJS_DONE;
8352
0
        }
8353
8354
0
        node = njs_parser_node_new(parser, NJS_TOKEN_EXPORT);
8355
0
        if (node == NULL) {
8356
0
            return NJS_ERROR;
8357
0
        }
8358
8359
0
        node->token_line = parser->line;
8360
0
        node->right = njs_parser_reference(parser, token);
8361
0
        if (node->right == NULL) {
8362
0
            return NJS_ERROR;
8363
0
        }
8364
8365
0
        parser->node = node;
8366
8367
0
        njs_lexer_consume_token(parser->lexer, 4);
8368
8369
0
        return njs_parser_stack_pop(parser);
8370
0
    }
8371
8372
0
    njs_lexer_consume_token(parser->lexer, 1);
8373
8374
0
    node = njs_parser_node_new(parser, NJS_TOKEN_EXPORT);
8375
0
    if (node == NULL) {
8376
0
        return NJS_ERROR;
8377
0
    }
8378
8379
0
    node->token_line = parser->line;
8380
0
    parser->node = node;
8381
8382
0
    njs_parser_next(parser, njs_parser_assignment_expression);
8383
8384
0
    return njs_parser_after(parser, current, node, 1, njs_parser_export_after);
8385
0
}
8386
8387
8388
static njs_int_t
8389
njs_parser_export_after(njs_parser_t *parser, njs_lexer_token_t *token,
8390
    njs_queue_link_t *current)
8391
0
{
8392
0
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
8393
0
        return njs_parser_failed(parser);
8394
0
    }
8395
8396
0
    return njs_parser_right_link_pop(parser);
8397
0
}
8398
8399
8400
static njs_mod_t *
8401
njs_parser_module(njs_parser_t *parser, njs_str_t *name)
8402
0
{
8403
0
    njs_vm_t   *vm;
8404
0
    njs_mod_t  *module;
8405
8406
0
    vm = parser->vm;
8407
8408
0
    if (name->length == 0) {
8409
0
        njs_parser_ref_error(parser, "Cannot load module \"%V\"", name);
8410
0
        return NULL;
8411
0
    }
8412
8413
0
    module = njs_module_find(vm, name, 1);
8414
0
    if (module != NULL) {
8415
0
        goto done;
8416
0
    }
8417
8418
0
    if (vm->module_loader == NULL) {
8419
0
        njs_parser_ref_error(parser, "Module loader callback is not provided");
8420
0
        return NULL;
8421
0
    }
8422
8423
0
    module = vm->module_loader(vm, vm->module_loader_opaque, name);
8424
0
    if (module == NULL) {
8425
0
        if (!njs_is_valid(&vm->exception)) {
8426
0
            njs_parser_ref_error(parser, "Cannot load module \"%V\"", name);
8427
0
        }
8428
8429
0
        return NULL;
8430
0
    }
8431
8432
0
done:
8433
8434
0
    return module;
8435
0
}
8436
8437
8438
static njs_int_t
8439
njs_parser_import(njs_parser_t *parser, njs_lexer_token_t *token,
8440
    njs_queue_link_t *current)
8441
2.36k
{
8442
2.36k
    njs_variable_t     *var;
8443
2.36k
    njs_parser_node_t  *name, *import;
8444
8445
2.36k
    if (parser->scope->parent != NULL) {
8446
185
        njs_parser_syntax_error(parser, "Illegal import statement");
8447
185
        return NJS_DONE;
8448
185
    }
8449
8450
2.18k
    if (token->type == NJS_TOKEN_MULTIPLICATION
8451
773
        || token->type == NJS_TOKEN_OPEN_BRACE
8452
616
        || token->type == NJS_TOKEN_STRING)
8453
1.79k
    {
8454
1.79k
        njs_parser_syntax_error(parser, "Non-default import is not supported");
8455
1.79k
        return NJS_DONE;
8456
1.79k
    }
8457
8458
387
    if (token->type != NJS_TOKEN_NAME) {
8459
157
        return njs_parser_failed(parser);
8460
157
     }
8461
8462
230
    name = njs_parser_variable_node(parser, token->atom_id, NJS_VARIABLE_LET,
8463
230
                                    &var);
8464
230
    if (name == NULL) {
8465
0
        return NJS_ERROR;
8466
0
    }
8467
8468
230
    var->init = 1;
8469
8470
230
    name->token_line = token->line;
8471
8472
230
    njs_lexer_consume_token(parser->lexer, 1);
8473
8474
230
    token = njs_lexer_token(parser->lexer, 0);
8475
230
    if (token == NULL) {
8476
0
        return NJS_ERROR;
8477
0
    }
8478
8479
230
    if (token->type != NJS_TOKEN_FROM) {
8480
230
        return njs_parser_failed(parser);
8481
230
    }
8482
8483
0
    njs_lexer_consume_token(parser->lexer, 1);
8484
8485
0
    token = njs_lexer_token(parser->lexer, 0);
8486
0
    if (token == NULL) {
8487
0
        return NJS_ERROR;
8488
0
    }
8489
8490
0
    if (token->type != NJS_TOKEN_STRING) {
8491
0
        return njs_parser_failed(parser);
8492
0
    }
8493
8494
0
    import = njs_parser_node_new(parser, NJS_TOKEN_IMPORT);
8495
0
    if (import == NULL) {
8496
0
        return NJS_ERROR;
8497
0
    }
8498
8499
0
    import->hoist = 1;
8500
0
    import->token_line = parser->line;
8501
0
    import->left = name;
8502
8503
0
    import->u.module = njs_parser_module(parser, &token->text);
8504
0
    if (njs_slow_path(import->u.module == NULL)) {
8505
0
        return NJS_ERROR;
8506
0
    }
8507
8508
0
    njs_lexer_consume_token(parser->lexer, 1);
8509
8510
0
    token = njs_lexer_token(parser->lexer, 0);
8511
0
    if (token == NULL) {
8512
0
        return NJS_ERROR;
8513
0
    }
8514
8515
0
    if (njs_parser_expect_semicolon(parser, token) != NJS_OK) {
8516
0
        return njs_parser_failed(parser);
8517
0
    }
8518
8519
0
    parser->node = import;
8520
8521
0
    return njs_parser_stack_pop(parser);
8522
0
}
8523
8524
8525
static njs_int_t
8526
njs_parser_export_sink(njs_parser_t *parser)
8527
0
{
8528
0
    njs_uint_t         n;
8529
0
    njs_parser_node_t  *node, *prev;
8530
8531
0
    n = 0;
8532
8533
0
    for (node = njs_parser_chain_top(parser);
8534
0
         node != NULL;
8535
0
         node = node->left)
8536
0
    {
8537
0
        if (node->right != NULL
8538
0
            && node->right->token_type == NJS_TOKEN_EXPORT)
8539
0
        {
8540
0
            n++;
8541
0
        }
8542
0
    }
8543
8544
0
    if (n != 1) {
8545
0
        njs_parser_syntax_error(parser,
8546
0
             (n == 0) ? "export statement is required"
8547
0
                      : "Identifier \"default\" has already been declared");
8548
0
        return NJS_ERROR;
8549
0
    }
8550
8551
0
    node = njs_parser_chain_top(parser);
8552
8553
0
    if (node->right && node->right->token_type == NJS_TOKEN_EXPORT) {
8554
0
        return NJS_OK;
8555
0
    }
8556
8557
0
    prev = njs_parser_chain_top(parser);
8558
8559
0
    while (prev->left != NULL) {
8560
0
        node = prev->left;
8561
8562
0
        if (node->right != NULL
8563
0
            && node->right->token_type == NJS_TOKEN_EXPORT)
8564
0
        {
8565
0
            prev->left = node->left;
8566
0
            break;
8567
0
        }
8568
8569
0
        prev = prev->left;
8570
0
    }
8571
8572
0
    node->left = njs_parser_chain_top(parser);
8573
0
    njs_parser_chain_top_set(parser, node);
8574
8575
0
    return NJS_OK;
8576
0
}
8577
8578
8579
static njs_parser_node_t *
8580
njs_parser_return_set(njs_parser_t *parser, njs_parser_node_t *expr)
8581
486k
{
8582
486k
    njs_parser_node_t  *stmt, *node;
8583
8584
486k
    node = njs_parser_node_new(parser, NJS_TOKEN_RETURN);
8585
486k
    if (njs_slow_path(node == NULL)) {
8586
0
        return NULL;
8587
0
    }
8588
8589
486k
    if (expr != NULL) {
8590
340k
        node->token_line = expr->token_line;
8591
340k
    }
8592
8593
486k
    node->right = expr;
8594
8595
486k
    stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
8596
486k
    if (njs_slow_path(stmt == NULL)) {
8597
0
        return NULL;
8598
0
    }
8599
8600
486k
    stmt->left = njs_parser_chain_top(parser);
8601
486k
    stmt->right = node;
8602
8603
486k
    njs_parser_chain_top_set(parser, stmt);
8604
8605
486k
    return stmt;
8606
486k
}
8607
8608
8609
static njs_parser_node_t *
8610
njs_parser_variable_node(njs_parser_t *parser, uintptr_t atom_id,
8611
    njs_variable_type_t type, njs_variable_t  **retvar)
8612
121k
{
8613
121k
    njs_int_t          ret;
8614
121k
    njs_variable_t     *var;
8615
121k
    njs_parser_node_t  *node;
8616
8617
121k
    var = njs_variable_add(parser, parser->scope, atom_id, type);
8618
121k
    if (njs_slow_path(var == NULL)) {
8619
1.47k
        return NULL;
8620
1.47k
    }
8621
8622
119k
    if (retvar != NULL) {
8623
77.4k
        *retvar = var;
8624
77.4k
    }
8625
8626
119k
    node = njs_parser_node_new(parser, NJS_TOKEN_NAME);
8627
119k
    if (njs_slow_path(node == NULL)) {
8628
0
        return NULL;
8629
0
    }
8630
8631
119k
    ret = njs_parser_variable_reference(parser, parser->scope, node, atom_id,
8632
119k
                                        NJS_DECLARATION);
8633
119k
    if (njs_slow_path(ret != NJS_OK)) {
8634
0
        return NULL;
8635
0
    }
8636
8637
119k
    return node;
8638
119k
}
8639
8640
8641
static njs_parser_node_t *
8642
njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token)
8643
2.49M
{
8644
2.49M
    njs_int_t           ret;
8645
2.49M
    njs_index_t         index;
8646
2.49M
    njs_variable_t      *var;
8647
2.49M
    njs_parser_node_t   *node;
8648
2.49M
    njs_parser_scope_t  *scope;
8649
8650
2.49M
    node = njs_parser_node_new(parser, token->type);
8651
2.49M
    if (njs_slow_path(node == NULL)) {
8652
0
        return NULL;
8653
0
    }
8654
8655
2.49M
    switch (token->type) {
8656
8657
1.14k
    case NJS_TOKEN_NULL:
8658
1.14k
        njs_thread_log_debug("JS: null");
8659
1.14k
        break;
8660
8661
5.41k
    case NJS_TOKEN_THIS:
8662
5.41k
        njs_thread_log_debug("JS: this");
8663
8664
5.41k
        scope = njs_function_scope(parser->scope);
8665
5.41k
        if (njs_slow_path(scope == NULL)) {
8666
0
            njs_parser_syntax_error(parser,
8667
0
                                    "function or global scope not found");
8668
0
            return NULL;
8669
0
        }
8670
8671
5.41k
        if (parser->vm->options.module) {
8672
0
            token->atom_id = NJS_ATOM_STRING_undefined;
8673
8674
5.41k
        } else if (!scope->arrow_function) {
8675
4.83k
            index = njs_scope_index(scope->type, 0, NJS_LEVEL_LOCAL,
8676
4.83k
                                    NJS_VARIABLE_VAR);
8677
8678
4.83k
            var = njs_variable_scope_add(parser, scope, scope, token->atom_id,
8679
4.83k
                                         NJS_VARIABLE_VAR, index);
8680
4.83k
            if (njs_slow_path(var == NULL)) {
8681
0
                return NULL;
8682
0
            }
8683
4.83k
        }
8684
8685
5.41k
        node->token_type = NJS_TOKEN_THIS;
8686
5.41k
        node->token_line = token->line;
8687
8688
5.41k
        ret = njs_parser_variable_reference(parser, parser->scope, node,
8689
5.41k
                                            token->atom_id, NJS_REFERENCE);
8690
5.41k
        if (njs_slow_path(ret != NJS_OK)) {
8691
0
            return NULL;
8692
0
        }
8693
8694
5.41k
        break;
8695
8696
5.41k
    case NJS_TOKEN_ARGUMENTS:
8697
2.53k
        njs_thread_log_debug("JS: arguments");
8698
8699
2.53k
        scope = njs_function_scope(parser->scope);
8700
8701
3.99k
        while (scope->arrow_function) {
8702
1.46k
            scope = njs_function_scope(scope->parent);
8703
1.46k
        }
8704
8705
2.53k
        if (scope->parent == NULL) {
8706
130
            njs_parser_syntax_error(parser, "\"%V\" object in global scope",
8707
130
                                    &token->text);
8708
130
            return NULL;
8709
130
        }
8710
8711
2.40k
        node->token_line = token->line;
8712
8713
2.40k
        ret = njs_parser_variable_reference(parser, parser->scope, node,
8714
2.40k
                                            token->atom_id, NJS_REFERENCE);
8715
2.40k
        if (njs_slow_path(ret != NJS_OK)) {
8716
0
            return NULL;
8717
0
        }
8718
8719
2.40k
        var = njs_variable_add(parser, scope, token->atom_id,
8720
2.40k
                               NJS_VARIABLE_VAR);
8721
2.40k
        if (njs_slow_path(var == NULL)) {
8722
0
            return NULL;
8723
0
        }
8724
8725
2.40k
        var->arguments_object = 1;
8726
8727
2.40k
        break;
8728
8729
2.48M
    default:
8730
2.48M
        if (token->type == NJS_TOKEN_EVAL
8731
2.48M
            || njs_lexer_token_is_identifier_reference(token))
8732
2.48M
        {
8733
2.48M
            njs_thread_log_debug("JS: %V", name);
8734
8735
2.48M
            if (token->type != NJS_TOKEN_EVAL) {
8736
2.48M
                node->token_type = NJS_TOKEN_NAME;
8737
2.48M
            }
8738
8739
2.48M
            node->token_line = token->line;
8740
8741
2.48M
            ret = njs_parser_variable_reference(parser, parser->scope, node,
8742
2.48M
                                               token->atom_id, NJS_REFERENCE);
8743
2.48M
            if (njs_slow_path(ret != NJS_OK)) {
8744
0
                return NULL;
8745
0
            }
8746
8747
2.48M
            break;
8748
2.48M
        }
8749
8750
0
        (void) njs_parser_unexpected_token(parser->vm, parser, &token->text,
8751
0
                                           token->type);
8752
0
        return NULL;
8753
2.49M
    }
8754
8755
2.49M
    return node;
8756
2.49M
}
8757
8758
8759
static njs_parser_node_t *
8760
njs_parser_object_value(njs_parser_t *parser, njs_parser_node_t *parent,
8761
    uint32_t token_line)
8762
1.96M
{
8763
1.96M
    njs_parser_node_t  *object;
8764
8765
1.96M
    njs_assert(parent->token_type == NJS_TOKEN_OBJECT
8766
1.96M
               || parent->token_type == NJS_TOKEN_ARRAY);
8767
8768
1.96M
    object = njs_parser_node_new(parser, NJS_TOKEN_OBJECT_VALUE);
8769
1.96M
    if (njs_slow_path(object == NULL)) {
8770
0
        return NULL;
8771
0
    }
8772
8773
1.96M
    object->token_line = token_line;
8774
1.96M
    object->u.object = parent;
8775
8776
1.96M
    return object;
8777
1.96M
}
8778
8779
8780
static njs_parser_node_t *
8781
njs_parser_argument(njs_parser_t *parser, njs_parser_node_t *expr,
8782
    njs_index_t index)
8783
999k
{
8784
999k
    njs_parser_node_t  *node;
8785
8786
999k
    node = njs_parser_node_new(parser, NJS_TOKEN_ARGUMENT);
8787
999k
    if (njs_slow_path(node == NULL)) {
8788
0
        return NULL;
8789
0
    }
8790
8791
999k
    node->token_line = expr->token_line;
8792
999k
    node->index = index;
8793
8794
999k
    node->left = expr;
8795
999k
    expr->dest = node;
8796
8797
999k
    return node;
8798
999k
}
8799
8800
8801
static njs_int_t
8802
njs_parser_object_property(njs_parser_t *parser, njs_parser_node_t *parent,
8803
    njs_parser_node_t *property, njs_parser_node_t *value,
8804
    njs_bool_t proto_init)
8805
1.96M
{
8806
1.96M
    njs_token_type_t   type;
8807
1.96M
    njs_parser_node_t  *stmt, *assign, *object, *propref;
8808
8809
1.96M
    object = njs_parser_object_value(parser, parent, value->token_line);
8810
1.96M
    if (njs_slow_path(object == NULL)) {
8811
0
        return NJS_TOKEN_ERROR;
8812
0
    }
8813
8814
1.96M
    type = proto_init ? NJS_TOKEN_PROTO_INIT : NJS_TOKEN_PROPERTY_INIT;
8815
8816
1.96M
    propref = njs_parser_node_new(parser, type);
8817
1.96M
    if (njs_slow_path(propref == NULL)) {
8818
0
        return NJS_ERROR;
8819
0
    }
8820
8821
1.96M
    propref->token_line = value->token_line;
8822
1.96M
    propref->left = object;
8823
1.96M
    propref->right = property;
8824
8825
1.96M
    assign = njs_parser_node_new(parser, NJS_TOKEN_ASSIGNMENT);
8826
1.96M
    if (njs_slow_path(assign == NULL)) {
8827
0
        return NJS_ERROR;
8828
0
    }
8829
8830
1.96M
    assign->token_line = value->token_line;
8831
1.96M
    assign->u.operation = NJS_VMCODE_MOVE;
8832
1.96M
    assign->left = propref;
8833
1.96M
    assign->right = value;
8834
8835
1.96M
    stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
8836
1.96M
    if (njs_slow_path(stmt == NULL)) {
8837
0
        return NJS_ERROR;
8838
0
    }
8839
8840
1.96M
    stmt->right = assign;
8841
1.96M
    stmt->left = parent->left;
8842
1.96M
    parent->left = stmt;
8843
8844
1.96M
    return NJS_OK;
8845
1.96M
}
8846
8847
8848
static njs_int_t
8849
njs_parser_property_accessor(njs_parser_t *parser, njs_parser_node_t *parent,
8850
    njs_parser_node_t *property, njs_parser_node_t *value,
8851
    njs_token_type_t accessor)
8852
752
{
8853
752
    njs_parser_node_t  *node, *stmt, *object, *propref;
8854
8855
752
    object = njs_parser_object_value(parser, parent, value->token_line);
8856
752
    if (njs_slow_path(object == NULL)) {
8857
0
        return NJS_TOKEN_ERROR;
8858
0
    }
8859
8860
752
    propref = njs_parser_node_new(parser, 0);
8861
752
    if (njs_slow_path(propref == NULL)) {
8862
0
        return NJS_ERROR;
8863
0
    }
8864
8865
752
    propref->left = object;
8866
752
    propref->right = property;
8867
8868
752
    node = njs_parser_node_new(parser, accessor);
8869
752
    if (njs_slow_path(node == NULL)) {
8870
0
        return NJS_ERROR;
8871
0
    }
8872
8873
752
    node->token_line = value->token_line;
8874
752
    node->left = propref;
8875
752
    node->right = value;
8876
8877
752
    stmt = njs_parser_node_new(parser, NJS_TOKEN_STATEMENT);
8878
752
    if (njs_slow_path(stmt == NULL)) {
8879
0
        return NJS_ERROR;
8880
0
    }
8881
8882
752
    stmt->right = node;
8883
752
    stmt->left = parent->left;
8884
752
    parent->left = stmt;
8885
8886
752
    return NJS_OK;
8887
752
}
8888
8889
8890
static njs_int_t
8891
njs_parser_array_item(njs_parser_t *parser, njs_parser_node_t *array,
8892
    njs_parser_node_t *value)
8893
1.94M
{
8894
1.94M
    njs_int_t          ret;
8895
1.94M
    njs_parser_node_t  *number;
8896
8897
1.94M
    number = njs_parser_node_new(parser, NJS_TOKEN_NUMBER);
8898
1.94M
    if (njs_slow_path(number == NULL)) {
8899
0
        return NJS_ERROR;
8900
0
    }
8901
8902
1.94M
    njs_set_number(&number->u.value, array->u.length);
8903
8904
1.94M
    number->token_line = value->token_line;
8905
8906
1.94M
    ret = njs_parser_object_property(parser, array, number, value, 0);
8907
1.94M
    if (njs_slow_path(ret != NJS_OK)) {
8908
0
        return NJS_ERROR;
8909
0
    }
8910
8911
1.94M
    array->ctor = 0;
8912
1.94M
    array->u.length++;
8913
8914
1.94M
    return NJS_OK;
8915
1.94M
}
8916
8917
8918
static njs_int_t
8919
njs_parser_template_string(njs_parser_t *parser, njs_lexer_token_t *token)
8920
1.03M
{
8921
1.03M
    u_char             *p, c;
8922
1.03M
    njs_int_t          ret;
8923
1.03M
    njs_str_t          *text;
8924
1.03M
    njs_bool_t         escape;
8925
1.03M
    njs_lexer_t        *lexer;
8926
1.03M
    njs_parser_node_t  *node;
8927
8928
1.03M
    lexer = parser->lexer;
8929
1.03M
    text = &token->text;
8930
8931
1.03M
    escape = 0;
8932
1.03M
    p = text->start;
8933
8934
1.03M
    if (p == NULL) {
8935
0
        return NJS_ERROR;
8936
0
    }
8937
8938
6.80M
    while (p < lexer->end) {
8939
8940
6.80M
        c = *p++;
8941
8942
6.80M
        switch (c) {
8943
75.7k
        case '\\':
8944
75.7k
            if (p == lexer->end) {
8945
0
                return NJS_ERROR;
8946
0
            }
8947
8948
75.7k
            p++;
8949
75.7k
            escape = 1;
8950
8951
75.7k
            continue;
8952
8953
1.01M
        case '`':
8954
1.01M
            text->length = p - text->start - 1;
8955
1.01M
            goto done;
8956
8957
64.0k
        case '$':
8958
64.0k
            if (p < lexer->end && *p == '{') {
8959
21.7k
                p++;
8960
21.7k
                text->length = p - text->start - 2;
8961
8962
21.7k
                ret = njs_lexer_in_stack_push(lexer);
8963
21.7k
                if (njs_slow_path(ret != NJS_OK)) {
8964
0
                    return NJS_ERROR;
8965
0
                }
8966
8967
21.7k
                goto done;
8968
21.7k
            }
8969
8970
42.2k
            break;
8971
8972
176k
        case '\n':
8973
176k
            parser->lexer->line++;
8974
176k
            break;
8975
6.80M
        }
8976
6.80M
    }
8977
8978
143
    return NJS_ERROR;
8979
8980
1.03M
done:
8981
8982
1.03M
    node = njs_parser_node_new(parser, NJS_TOKEN_STRING);
8983
1.03M
    if (njs_slow_path(node == NULL)) {
8984
0
        return NJS_ERROR;
8985
0
    }
8986
8987
1.03M
    node->token_line = token->line;
8988
8989
1.03M
    if (escape) {
8990
27.3k
        ret = njs_parser_escape_string_create(parser, token, &node->u.value);
8991
27.3k
        if (njs_slow_path(ret != NJS_TOKEN_STRING)) {
8992
2.25k
            return NJS_ERROR;
8993
2.25k
        }
8994
8995
1.00M
    } else {
8996
1.00M
        ret = njs_parser_string_create(parser->vm, token, &node->u.value);
8997
1.00M
        if (njs_slow_path(ret != NJS_OK)) {
8998
0
            return NJS_ERROR;
8999
0
        }
9000
1.00M
    }
9001
9002
1.03M
    lexer->start = p;
9003
1.03M
    parser->node = node;
9004
9005
1.03M
    return c == '`' ? NJS_DONE : NJS_OK;
9006
1.03M
}
9007
9008
9009
njs_int_t
9010
njs_parser_string_create(njs_vm_t *vm, njs_lexer_token_t *token,
9011
    njs_value_t *value)
9012
1.26M
{
9013
1.26M
    size_t     length;
9014
1.26M
    njs_int_t  ret;
9015
1.26M
    njs_str_t  dst;
9016
9017
1.26M
    length = njs_decode_utf8_length(&token->text, &dst.length);
9018
1.26M
    dst.start = njs_string_alloc(vm, value, dst.length, length);
9019
1.26M
    if (njs_slow_path(dst.start == NULL)) {
9020
0
        return NJS_ERROR;
9021
0
    }
9022
9023
1.26M
    njs_decode_utf8(&dst, &token->text);
9024
9025
1.26M
    if (length > NJS_STRING_MAP_STRIDE && dst.length != length) {
9026
14.1k
        njs_string_utf8_offset_map_init(value->string.data->start,
9027
14.1k
                                        dst.length);
9028
14.1k
    }
9029
9030
1.26M
    ret = njs_atom_atomize_key(vm, value);
9031
1.26M
    if (njs_slow_path(ret != NJS_OK)) {
9032
0
        return NJS_TOKEN_ERROR;
9033
0
    }
9034
9035
1.26M
    return NJS_OK;
9036
1.26M
}
9037
9038
9039
static njs_token_type_t
9040
njs_parser_escape_string_create(njs_parser_t *parser, njs_lexer_token_t *token,
9041
    njs_value_t *value)
9042
31.9k
{
9043
31.9k
    u_char                c, *start, *dst;
9044
31.9k
    size_t                size, length, hex_length;
9045
31.9k
    uint64_t              cp, cp_pair;
9046
31.9k
    njs_int_t             ret;
9047
31.9k
    njs_str_t             *string;
9048
31.9k
    const u_char          *src, *end, *hex_end;
9049
31.9k
    njs_unicode_decode_t  ctx;
9050
9051
31.9k
    ret = njs_parser_escape_string_calc_length(parser, token, &size, &length);
9052
31.9k
    if (njs_slow_path(ret != NJS_OK)) {
9053
2.90k
        return NJS_TOKEN_ILLEGAL;
9054
2.90k
    }
9055
9056
28.9k
    start = njs_string_alloc(parser->vm, value, size, length);
9057
28.9k
    if (njs_slow_path(start == NULL)) {
9058
0
        return NJS_TOKEN_ERROR;
9059
0
    }
9060
9061
28.9k
    dst = start;
9062
28.9k
    cp_pair = 0;
9063
9064
28.9k
    string = &token->text;
9065
28.9k
    src = string->start;
9066
28.9k
    end = src + string->length;
9067
9068
3.13M
    while (src < end) {
9069
3.10M
        c = *src++;
9070
9071
3.10M
        if (c == '\\') {
9072
            /*
9073
             * Testing "src == end" is not required here
9074
             * since this has been already tested by lexer.
9075
             */
9076
9077
74.3k
            c = *src++;
9078
9079
74.3k
            switch (c) {
9080
10.0k
            case 'u':
9081
                /*
9082
                 * A character after "u" can be safely tested here
9083
                 * because there is always a closing quote at the
9084
                 * end of string: ...\u".
9085
                 */
9086
9087
10.0k
                if (*src != '{') {
9088
9.90k
                    hex_length = 4;
9089
9.90k
                    goto hex_length;
9090
9.90k
                }
9091
9092
150
                src++;
9093
150
                hex_length = 0;
9094
150
                hex_end = end;
9095
9096
150
                goto hex;
9097
9098
1.57k
            case 'x':
9099
1.57k
                hex_length = 2;
9100
1.57k
                goto hex_length;
9101
9102
902
            case '0':
9103
902
                c = '\0';
9104
902
                break;
9105
9106
841
            case '1':
9107
1.23k
            case '2':
9108
1.25k
            case '3':
9109
1.79k
            case '4':
9110
4.07k
            case '5':
9111
4.11k
            case '6':
9112
4.37k
            case '7':
9113
4.37k
                if (parser->node != NULL) {
9114
4.23k
                    switch (parser->node->token_type) {
9115
296
                    case NJS_TOKEN_METHOD_CALL:
9116
3.62k
                    case NJS_TOKEN_FUNCTION_CALL:
9117
4.14k
                    case NJS_TOKEN_FUNCTION_EXPRESSION:
9118
4.22k
                    case NJS_TOKEN_EVAL:
9119
4.22k
                        goto next_char;
9120
9121
10
                    default:
9122
10
                        break;
9123
4.23k
                    }
9124
4.23k
                }
9125
9126
154
                njs_parser_syntax_error(parser,
9127
154
                                        "Octal escape sequences can't be used "
9128
154
                                        "in untagged template literals "
9129
154
                                        "or in strict mode code");
9130
9131
154
                return NJS_TOKEN_ILLEGAL;
9132
9133
453
            case '8':
9134
2.45k
            case '9':
9135
2.45k
                if (parser->node != NULL) {
9136
2.30k
                    switch (parser->node->token_type) {
9137
133
                    case NJS_TOKEN_METHOD_CALL:
9138
1.94k
                    case NJS_TOKEN_FUNCTION_CALL:
9139
1.94k
                    case NJS_TOKEN_FUNCTION_EXPRESSION:
9140
2.03k
                    case NJS_TOKEN_EVAL:
9141
2.03k
                        goto next_char;
9142
9143
270
                    default:
9144
270
                        break;
9145
2.30k
                    }
9146
2.30k
                }
9147
9148
421
                njs_parser_syntax_error(parser,
9149
421
                                        "The escapes \\8 and \\9 can't be used "
9150
421
                                        "in untagged template literals "
9151
421
                                        "or in strict mode code");
9152
9153
421
                return NJS_TOKEN_ILLEGAL;
9154
9155
6.25k
next_char:
9156
9157
6.25k
                break;
9158
9159
834
            case 'b':
9160
834
                c = '\b';
9161
834
                break;
9162
9163
1.33k
            case 'f':
9164
1.33k
                c = '\f';
9165
1.33k
                break;
9166
9167
732
            case 'n':
9168
732
                c = '\n';
9169
732
                break;
9170
9171
390
            case 'r':
9172
390
                c = '\r';
9173
390
                break;
9174
9175
367
            case 't':
9176
367
                c = '\t';
9177
367
                break;
9178
9179
440
            case 'v':
9180
440
                c = '\v';
9181
440
                break;
9182
9183
485
            case '\r':
9184
                /*
9185
                 * A character after "\r" can be safely tested here
9186
                 * because there is always a closing quote at the
9187
                 * end of string: ...\\r".
9188
                 */
9189
9190
485
                if (*src == '\n') {
9191
36
                    src++;
9192
36
                }
9193
9194
485
                continue;
9195
9196
10.0k
            case '\n':
9197
10.0k
                continue;
9198
9199
40.3k
            default:
9200
40.3k
                if (c >= 0x80) {
9201
5.60k
                    goto utf8_copy;
9202
5.60k
                }
9203
9204
34.7k
                break;
9205
74.3k
            }
9206
74.3k
        }
9207
9208
3.07M
        if (c < 0x80) {
9209
2.41M
            *dst++ = c;
9210
9211
2.41M
            continue;
9212
2.41M
        }
9213
9214
662k
    utf8_copy:
9215
9216
662k
        src--;
9217
9218
662k
        njs_utf8_decode_init(&ctx);
9219
9220
662k
        cp = njs_utf8_decode(&ctx, &src, end);
9221
662k
        if (cp > NJS_UNICODE_MAX_CODEPOINT) {
9222
604k
            cp = NJS_UNICODE_REPLACEMENT;
9223
604k
        }
9224
9225
662k
        dst = njs_utf8_encode(dst, cp);
9226
9227
662k
        continue;
9228
9229
11.4k
    hex_length:
9230
9231
11.4k
        hex_end = src + hex_length;
9232
9233
11.6k
    hex:
9234
11.6k
        cp = njs_number_hex_parse(&src, hex_end, 0);
9235
9236
        /* Skip '}' character. */
9237
9238
11.6k
        if (hex_length == 0) {
9239
150
            src++;
9240
150
        }
9241
9242
11.6k
        if (cp_pair != 0) {
9243
2.49k
            if (njs_fast_path(njs_surrogate_trailing(cp))) {
9244
12
                cp = njs_surrogate_pair(cp_pair, cp);
9245
9246
2.48k
            } else if (njs_slow_path(njs_surrogate_leading(cp))) {
9247
1.96k
                cp = NJS_UNICODE_REPLACEMENT;
9248
9249
1.96k
                dst = njs_utf8_encode(dst, (uint32_t) cp);
9250
9251
1.96k
            } else {
9252
517
                dst = njs_utf8_encode(dst, NJS_UNICODE_REPLACEMENT);
9253
517
            }
9254
9255
2.49k
            cp_pair = 0;
9256
9257
9.13k
        } else if (njs_surrogate_any(cp)) {
9258
7.28k
            if (cp <= 0xdbff && (end - src) >= 2
9259
5.81k
                && src[0] == '\\' && src[1] == 'u')
9260
2.49k
            {
9261
2.49k
                cp_pair = cp;
9262
2.49k
                continue;
9263
2.49k
            }
9264
9265
4.78k
            cp = NJS_UNICODE_REPLACEMENT;
9266
4.78k
        }
9267
9268
9.13k
        dst = njs_utf8_encode(dst, (uint32_t) cp);
9269
9.13k
        if (njs_slow_path(dst == NULL)) {
9270
130
            njs_parser_syntax_error(parser, "Invalid Unicode code point \"%V\"",
9271
130
                                    &token->text);
9272
9273
130
            return NJS_TOKEN_ILLEGAL;
9274
130
        }
9275
9.13k
    }
9276
9277
28.2k
    if (length > NJS_STRING_MAP_STRIDE && length != size) {
9278
13.3k
        njs_string_utf8_offset_map_init(start, size);
9279
13.3k
    }
9280
9281
28.2k
    ret = njs_atom_atomize_key(parser->vm, value);
9282
28.2k
    if (njs_slow_path(ret != NJS_OK)) {
9283
0
        return NJS_TOKEN_ERROR;
9284
0
    }
9285
9286
28.2k
    return NJS_TOKEN_STRING;
9287
28.2k
}
9288
9289
9290
static njs_int_t
9291
njs_parser_escape_string_calc_length(njs_parser_t *parser,
9292
    njs_lexer_token_t *token, size_t *out_size, size_t *out_length)
9293
31.9k
{
9294
31.9k
    size_t                size, length, hex_length;
9295
31.9k
    uint64_t              cp, cp_pair;
9296
31.9k
    njs_str_t             *string;
9297
31.9k
    const u_char          *ptr, *src, *end, *hex_end;
9298
31.9k
    njs_unicode_decode_t  ctx;
9299
9300
31.9k
    size = 0;
9301
31.9k
    length = 0;
9302
31.9k
    cp_pair = 0;
9303
9304
31.9k
    string = &token->text;
9305
31.9k
    src = string->start;
9306
31.9k
    end = src + string->length;
9307
9308
3.20M
    while (src < end) {
9309
9310
3.17M
        if (*src == '\\') {
9311
80.9k
            src++;
9312
9313
80.9k
            switch (*src) {
9314
15.4k
            case 'u':
9315
15.4k
                src++;
9316
9317
15.4k
                if (*src != '{') {
9318
14.6k
                    hex_length = 4;
9319
14.6k
                    goto hex_length;
9320
14.6k
                }
9321
9322
810
                src++;
9323
810
                hex_length = 0;
9324
810
                hex_end = end;
9325
9326
810
                goto hex;
9327
9328
1.57k
            case 'x':
9329
1.57k
                src++;
9330
1.57k
                hex_length = 2;
9331
1.57k
                goto hex_length;
9332
9333
799
            case '\r':
9334
799
                src++;
9335
9336
799
                if (*src == '\n') {
9337
36
                    src++;
9338
36
                }
9339
9340
799
                continue;
9341
9342
10.0k
            case '\n':
9343
10.0k
                src++;
9344
10.0k
                continue;
9345
9346
53.0k
            default:
9347
53.0k
                break;
9348
80.9k
            }
9349
80.9k
        }
9350
9351
3.14M
        if (*src >= 0x80) {
9352
678k
            njs_utf8_decode_init(&ctx);
9353
9354
678k
            cp = njs_utf8_decode(&ctx, &src, end);
9355
678k
            if (cp > NJS_UNICODE_MAX_CODEPOINT) {
9356
604k
                cp = NJS_UNICODE_REPLACEMENT;
9357
604k
            }
9358
9359
678k
            size += njs_utf8_size(cp);
9360
678k
            length++;
9361
9362
678k
            continue;
9363
678k
        }
9364
9365
2.46M
        src++;
9366
2.46M
        size++;
9367
2.46M
        length++;
9368
9369
2.46M
        continue;
9370
9371
16.2k
    hex_length:
9372
9373
16.2k
        hex_end = src + hex_length;
9374
9375
16.2k
        if (njs_slow_path(hex_end > end)) {
9376
795
            goto invalid;
9377
795
        }
9378
9379
16.2k
    hex:
9380
9381
16.2k
        ptr = src;
9382
16.2k
        cp = njs_number_hex_parse(&src, hex_end, 0);
9383
9384
16.2k
        if (hex_length != 0) {
9385
15.4k
            if (src != hex_end) {
9386
1.45k
                goto invalid;
9387
1.45k
            }
9388
9389
15.4k
        } else {
9390
810
            if (src == ptr || (src - ptr) > 6) {
9391
570
                goto invalid;
9392
570
            }
9393
9394
240
            if (src == end || *src++ != '}') {
9395
90
                goto invalid;
9396
90
            }
9397
240
        }
9398
9399
14.1k
        if (cp_pair != 0) {
9400
3.03k
            if (njs_fast_path(njs_surrogate_trailing(cp))) {
9401
12
                cp = njs_surrogate_pair(cp_pair, cp);
9402
9403
3.01k
            } else if (njs_slow_path(njs_surrogate_leading(cp))) {
9404
1.96k
                cp = NJS_UNICODE_REPLACEMENT;
9405
9406
1.96k
                size += njs_utf8_size(cp);
9407
1.96k
                length++;
9408
9409
1.96k
            } else {
9410
1.04k
                size += njs_utf8_size(NJS_UNICODE_REPLACEMENT);
9411
1.04k
                length++;
9412
1.04k
            }
9413
9414
3.03k
            cp_pair = 0;
9415
9416
11.1k
        } else if (njs_surrogate_any(cp)) {
9417
9.27k
            if (cp <= 0xdbff && (end - src) >= 2
9418
7.63k
                && src[0] == '\\' && src[1] == 'u')
9419
4.32k
            {
9420
4.32k
                cp_pair = cp;
9421
4.32k
                continue;
9422
4.32k
            }
9423
9424
4.94k
            cp = NJS_UNICODE_REPLACEMENT;
9425
4.94k
        }
9426
9427
9.82k
        size += njs_utf8_size(cp);
9428
9.82k
        length++;
9429
9.82k
    }
9430
9431
28.9k
    *out_size = size;
9432
28.9k
    *out_length = length;
9433
9434
28.9k
    return NJS_OK;
9435
9436
2.90k
invalid:
9437
9438
2.90k
    njs_parser_syntax_error(parser, "Invalid Unicode code point \"%V\"",
9439
2.90k
                            &token->text);
9440
2.90k
    return NJS_ERROR;
9441
31.9k
}
9442
9443
9444
njs_bool_t
9445
njs_parser_has_side_effect(njs_parser_node_t *node)
9446
8.48M
{
9447
8.48M
    njs_bool_t  side_effect;
9448
9449
8.48M
    if (node == NULL) {
9450
4.79M
        return 0;
9451
4.79M
    }
9452
9453
3.69M
    if (node->token_type >= NJS_TOKEN_ASSIGNMENT
9454
3.68M
        && node->token_type <= NJS_TOKEN_LAST_ASSIGNMENT)
9455
198k
    {
9456
198k
        return 1;
9457
198k
    }
9458
9459
3.49M
    if (node->token_type == NJS_TOKEN_FUNCTION_CALL
9460
3.46M
        || node->token_type == NJS_TOKEN_METHOD_CALL)
9461
35.0k
    {
9462
35.0k
        return 1;
9463
35.0k
    }
9464
9465
3.45M
    side_effect = njs_parser_has_side_effect(node->left);
9466
9467
3.45M
    if (njs_fast_path(!side_effect)) {
9468
2.60M
        return njs_parser_has_side_effect(node->right);
9469
2.60M
    }
9470
9471
855k
    return side_effect;
9472
3.45M
}
9473
9474
9475
njs_int_t
9476
njs_parser_variable_reference(njs_parser_t *parser, njs_parser_scope_t *scope,
9477
    njs_parser_node_t *node, uintptr_t atom_id, njs_reference_type_t type)
9478
3.24M
{
9479
3.24M
    njs_rbtree_node_t         *rb_node;
9480
3.24M
    njs_variable_reference_t  *vr;
9481
3.24M
    njs_parser_rbtree_node_t  parse_node, *rb_parse_node;
9482
9483
3.24M
    vr = &node->u.reference;
9484
9485
3.24M
    vr->atom_id = atom_id;
9486
3.24M
    vr->type = type;
9487
9488
3.24M
    parse_node.key = atom_id;
9489
9490
3.24M
    rb_node = njs_rbtree_find(&scope->references, &parse_node.node);
9491
3.24M
    if (rb_node != NULL) {
9492
653k
        return NJS_OK;
9493
653k
    }
9494
9495
2.59M
    rb_parse_node = njs_mp_alloc(parser->vm->mem_pool,
9496
2.59M
                                 sizeof(njs_parser_rbtree_node_t));
9497
2.59M
    if (njs_slow_path(rb_parse_node == NULL)) {
9498
0
        return NJS_ERROR;
9499
0
    }
9500
9501
2.59M
    rb_parse_node->key = atom_id;
9502
2.59M
    rb_parse_node->index = NJS_INDEX_NONE;
9503
9504
2.59M
    njs_rbtree_insert(&scope->references, &rb_parse_node->node);
9505
9506
2.59M
    return NJS_OK;
9507
2.59M
}
9508
9509
9510
njs_token_type_t
9511
njs_parser_unexpected_token(njs_vm_t *vm, njs_parser_t *parser,
9512
    njs_str_t *name, njs_token_type_t type)
9513
0
{
9514
0
    if (type != NJS_TOKEN_END) {
9515
0
        njs_parser_syntax_error(parser, "Unexpected token \"%V\"", name);
9516
9517
0
    } else {
9518
0
        njs_parser_syntax_error(parser, "Unexpected end of input");
9519
0
    }
9520
9521
0
    return NJS_DONE;
9522
0
}
9523
9524
9525
static void
9526
njs_parser_error(njs_vm_t *vm, njs_object_type_t type, njs_str_t *file,
9527
    uint32_t line, const char *fmt, va_list args)
9528
136k
{
9529
136k
    u_char       msg[NJS_MAX_ERROR_STR];
9530
136k
    u_char       *p, *end;
9531
136k
    njs_value_t  error;
9532
9533
136k
    if (njs_slow_path(vm->top_frame == NULL)) {
9534
0
        njs_vm_runtime_init(vm);
9535
0
    }
9536
9537
136k
    p = msg;
9538
136k
    end = msg + NJS_MAX_ERROR_STR;
9539
9540
136k
    p = njs_vsprintf(p, end, fmt, args);
9541
9542
136k
    njs_error_new(vm, &error, njs_vm_proto(vm, type), msg, p - msg);
9543
9544
136k
    if (!vm->options.quiet && file->length != 0) {
9545
136k
        njs_error_stack_set(vm, &error, file, line);
9546
136k
    }
9547
9548
136k
    njs_vm_throw(vm, &error);
9549
136k
}
9550
9551
9552
void
9553
njs_parser_lexer_error(njs_parser_t *parser, njs_object_type_t type,
9554
    const char *fmt, ...)
9555
129k
{
9556
129k
    va_list  args;
9557
9558
129k
    if (njs_is_error(&parser->vm->exception)) {
9559
4.95k
        return;
9560
4.95k
    }
9561
9562
129k
    va_start(args, fmt);
9563
124k
    njs_parser_error(parser->vm, type, &parser->lexer->file,
9564
124k
                     parser->lexer->line, fmt, args);
9565
124k
    va_end(args);
9566
124k
}
9567
9568
9569
void
9570
njs_parser_node_error(njs_vm_t *vm, njs_object_type_t type,
9571
    njs_parser_node_t *node, njs_str_t *file, const char *fmt, ...)
9572
11.8k
{
9573
11.8k
    va_list  args;
9574
9575
11.8k
    va_start(args, fmt);
9576
11.8k
    njs_parser_error(vm, type, file, node->token_line, fmt, args);
9577
11.8k
    va_end(args);
9578
11.8k
}
9579
9580
9581
njs_int_t
9582
njs_parser_traverse(njs_vm_t *vm, njs_parser_node_t *root, void *ctx,
9583
    njs_parser_traverse_cb_t cb)
9584
40.5k
{
9585
40.5k
    njs_int_t          ret;
9586
40.5k
    njs_arr_t          *stack;
9587
40.5k
    njs_parser_node_t  *node, **ref;
9588
9589
40.5k
    if (root == NULL) {
9590
11.9k
        return NJS_OK;
9591
11.9k
    }
9592
9593
28.5k
    stack = njs_arr_create(vm->mem_pool, 8, sizeof(njs_parser_node_t *));
9594
28.5k
    if (njs_slow_path(stack == NULL)) {
9595
0
        return NJS_ERROR;
9596
9597
0
    }
9598
9599
28.5k
    ref = njs_arr_add(stack);
9600
28.5k
    if (njs_slow_path(ref == NULL)) {
9601
0
        goto failed;
9602
0
    }
9603
9604
28.5k
    *ref = root;
9605
9606
127k
    while (1) {
9607
127k
        if (njs_arr_is_empty(stack)) {
9608
28.5k
            break;
9609
28.5k
        }
9610
9611
99.3k
        ref = njs_arr_remove_last(stack);
9612
99.3k
        node = *ref;
9613
9614
99.3k
        ret = cb(vm, node, ctx);
9615
99.3k
        if (njs_slow_path(ret != NJS_OK)) {
9616
0
            goto failed;
9617
0
        }
9618
9619
99.3k
        if (node->left != NULL) {
9620
28.5k
            ref = njs_arr_add(stack);
9621
28.5k
            if (njs_slow_path(ref == NULL)) {
9622
0
                goto failed;
9623
0
            }
9624
9625
28.5k
            *ref = node->left;
9626
28.5k
        }
9627
9628
99.3k
        if (node->right != NULL) {
9629
42.2k
            ref = njs_arr_add(stack);
9630
42.2k
            if (njs_slow_path(ref == NULL)) {
9631
0
                goto failed;
9632
0
            }
9633
9634
42.2k
            *ref = node->right;
9635
42.2k
        }
9636
99.3k
    }
9637
9638
28.5k
    njs_arr_destroy(stack);
9639
9640
28.5k
    return NJS_OK;
9641
9642
0
failed:
9643
9644
0
    njs_arr_destroy(stack);
9645
9646
0
    return NJS_ERROR;
9647
28.5k
}
9648
9649
9650
njs_int_t
9651
njs_parser_serialize_ast(njs_parser_node_t *node, njs_chb_t *chain)
9652
0
{
9653
0
    njs_int_t  ret;
9654
9655
0
    ret = NJS_OK;
9656
9657
0
    njs_parser_serialize_tree(chain, node, &ret, 0);
9658
0
    njs_chb_append_literal(chain, "\n");
9659
9660
0
    return ret;
9661
0
}
9662
9663
9664
njs_inline void
9665
njs_parser_serialize_indent(njs_chb_t *chain, size_t indent)
9666
0
{
9667
0
    size_t  i;
9668
9669
0
    for (i = 0; i < indent; i++) {
9670
0
        njs_chb_append_literal(chain, "  ");
9671
0
    }
9672
0
}
9673
9674
9675
static void
9676
njs_parser_serialize_tree(njs_chb_t *chain, njs_parser_node_t *node,
9677
    njs_int_t *ret, size_t indent)
9678
0
{
9679
0
    njs_str_t  str;
9680
9681
0
    njs_chb_append_literal(chain, "{\"name\": \"");
9682
9683
0
    *ret |= njs_parser_serialize_node(chain, node);
9684
9685
0
    njs_chb_append_literal(chain, "\",\n");
9686
0
    njs_parser_serialize_indent(chain, indent);
9687
0
    njs_chb_sprintf(chain, 32, " \"line\": %d", node->token_line);
9688
9689
0
    switch (node->token_type) {
9690
0
    case NJS_TOKEN_NUMBER:
9691
0
    case NJS_TOKEN_STRING:
9692
0
    case NJS_TOKEN_NAME:
9693
0
    case NJS_TOKEN_FUNCTION_CALL:
9694
0
        njs_chb_append_literal(chain, ",\n");
9695
0
        njs_parser_serialize_indent(chain, indent);
9696
0
        njs_chb_sprintf(chain, 32, " \"index\": \"%p\"", node->index);
9697
9698
0
        switch (node->token_type) {
9699
0
        case NJS_TOKEN_NUMBER:
9700
0
        case NJS_TOKEN_STRING:
9701
0
            njs_chb_append_literal(chain, ",\n");
9702
0
            njs_parser_serialize_indent(chain, indent);
9703
9704
0
            if (node->token_type == NJS_TOKEN_NUMBER) {
9705
0
                njs_chb_sprintf(chain, 32, " \"value\": %f",
9706
0
                                njs_number(&node->u.value));
9707
9708
0
            } else {
9709
0
                njs_string_get_unsafe(&node->u.value, &str);
9710
0
                njs_chb_append_literal(chain, " \"value\": \"");
9711
0
                njs_chb_append_str(chain, &str);
9712
0
                njs_chb_append_literal(chain, "\"");
9713
0
            }
9714
9715
0
            break;
9716
9717
0
        default:
9718
0
            break;
9719
0
        }
9720
9721
0
        break;
9722
9723
0
    default:
9724
0
        break;
9725
0
    }
9726
9727
0
    if (node->left != NULL) {
9728
0
        njs_chb_append_literal(chain, ",\n");
9729
0
        njs_parser_serialize_indent(chain, indent);
9730
0
        njs_chb_append_literal(chain, " \"left\": ");
9731
9732
0
        njs_parser_serialize_tree(chain, node->left, ret, indent + 1);
9733
0
    }
9734
9735
0
    if (node->right != NULL) {
9736
0
        njs_chb_append_literal(chain, ",\n");
9737
0
        njs_parser_serialize_indent(chain, indent);
9738
0
        njs_chb_append_literal(chain, " \"right\": ");
9739
9740
0
        njs_parser_serialize_tree(chain, node->right, ret, indent + 1);
9741
0
    }
9742
9743
0
    njs_chb_append_literal(chain, "}");
9744
0
}
9745
9746
9747
static njs_int_t
9748
njs_parser_serialize_node(njs_chb_t *chain, njs_parser_node_t *node)
9749
0
{
9750
0
    const char  *name;
9751
9752
0
#define njs_token_serialize(token)                                          \
9753
0
    case token:                                                             \
9754
0
        name = &njs_stringify(token)[njs_length("NJS_TOKEN_")];             \
9755
0
        njs_chb_append(chain, name, njs_strlen(name));                      \
9756
0
        break
9757
9758
0
    switch (node->token_type) {
9759
0
    njs_token_serialize(NJS_TOKEN_END);
9760
    /* FIXME: NJS_TOKEN_ILLEGAL should not be present in AST */
9761
0
    njs_token_serialize(NJS_TOKEN_ILLEGAL);
9762
0
    njs_token_serialize(NJS_TOKEN_COMMA);
9763
0
    njs_token_serialize(NJS_TOKEN_CONDITIONAL);
9764
0
    njs_token_serialize(NJS_TOKEN_ASSIGNMENT);
9765
0
    njs_token_serialize(NJS_TOKEN_ADDITION_ASSIGNMENT);
9766
0
    njs_token_serialize(NJS_TOKEN_SUBTRACTION_ASSIGNMENT);
9767
0
    njs_token_serialize(NJS_TOKEN_MULTIPLICATION_ASSIGNMENT);
9768
0
    njs_token_serialize(NJS_TOKEN_EXPONENTIATION_ASSIGNMENT);
9769
0
    njs_token_serialize(NJS_TOKEN_DIVISION_ASSIGNMENT);
9770
0
    njs_token_serialize(NJS_TOKEN_REMAINDER_ASSIGNMENT);
9771
0
    njs_token_serialize(NJS_TOKEN_LEFT_SHIFT_ASSIGNMENT);
9772
0
    njs_token_serialize(NJS_TOKEN_RIGHT_SHIFT_ASSIGNMENT);
9773
0
    njs_token_serialize(NJS_TOKEN_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT);
9774
0
    njs_token_serialize(NJS_TOKEN_BITWISE_OR_ASSIGNMENT);
9775
0
    njs_token_serialize(NJS_TOKEN_BITWISE_XOR_ASSIGNMENT);
9776
0
    njs_token_serialize(NJS_TOKEN_BITWISE_AND_ASSIGNMENT);
9777
0
    njs_token_serialize(NJS_TOKEN_LOGICAL_OR_ASSIGNMENT);
9778
0
    njs_token_serialize(NJS_TOKEN_LOGICAL_AND_ASSIGNMENT);
9779
0
    njs_token_serialize(NJS_TOKEN_COALESCE_ASSIGNMENT);
9780
0
    njs_token_serialize(NJS_TOKEN_EQUAL);
9781
0
    njs_token_serialize(NJS_TOKEN_NOT_EQUAL);
9782
0
    njs_token_serialize(NJS_TOKEN_STRICT_EQUAL);
9783
0
    njs_token_serialize(NJS_TOKEN_STRICT_NOT_EQUAL);
9784
0
    njs_token_serialize(NJS_TOKEN_ADDITION);
9785
0
    njs_token_serialize(NJS_TOKEN_UNARY_PLUS);
9786
0
    njs_token_serialize(NJS_TOKEN_INCREMENT);
9787
0
    njs_token_serialize(NJS_TOKEN_POST_INCREMENT);
9788
0
    njs_token_serialize(NJS_TOKEN_SUBTRACTION);
9789
0
    njs_token_serialize(NJS_TOKEN_UNARY_NEGATION);
9790
0
    njs_token_serialize(NJS_TOKEN_DECREMENT);
9791
0
    njs_token_serialize(NJS_TOKEN_POST_DECREMENT);
9792
0
    njs_token_serialize(NJS_TOKEN_MULTIPLICATION);
9793
0
    njs_token_serialize(NJS_TOKEN_EXPONENTIATION);
9794
0
    njs_token_serialize(NJS_TOKEN_DIVISION);
9795
0
    njs_token_serialize(NJS_TOKEN_REMAINDER);
9796
0
    njs_token_serialize(NJS_TOKEN_LESS);
9797
0
    njs_token_serialize(NJS_TOKEN_LESS_OR_EQUAL);
9798
0
    njs_token_serialize(NJS_TOKEN_LEFT_SHIFT);
9799
0
    njs_token_serialize(NJS_TOKEN_GREATER);
9800
0
    njs_token_serialize(NJS_TOKEN_GREATER_OR_EQUAL);
9801
0
    njs_token_serialize(NJS_TOKEN_RIGHT_SHIFT);
9802
0
    njs_token_serialize(NJS_TOKEN_UNSIGNED_RIGHT_SHIFT);
9803
0
    njs_token_serialize(NJS_TOKEN_BITWISE_OR);
9804
0
    njs_token_serialize(NJS_TOKEN_LOGICAL_OR);
9805
0
    njs_token_serialize(NJS_TOKEN_BITWISE_XOR);
9806
0
    njs_token_serialize(NJS_TOKEN_BITWISE_AND);
9807
0
    njs_token_serialize(NJS_TOKEN_LOGICAL_AND);
9808
0
    njs_token_serialize(NJS_TOKEN_BITWISE_NOT);
9809
0
    njs_token_serialize(NJS_TOKEN_LOGICAL_NOT);
9810
0
    njs_token_serialize(NJS_TOKEN_COALESCE);
9811
0
    njs_token_serialize(NJS_TOKEN_OPTIONAL_CHAIN);
9812
0
    njs_token_serialize(NJS_TOKEN_IN);
9813
0
    njs_token_serialize(NJS_TOKEN_OF);
9814
0
    njs_token_serialize(NJS_TOKEN_INSTANCEOF);
9815
0
    njs_token_serialize(NJS_TOKEN_TYPEOF);
9816
0
    njs_token_serialize(NJS_TOKEN_VOID);
9817
0
    njs_token_serialize(NJS_TOKEN_NEW);
9818
0
    njs_token_serialize(NJS_TOKEN_DELETE);
9819
0
    njs_token_serialize(NJS_TOKEN_YIELD);
9820
9821
0
    njs_token_serialize(NJS_TOKEN_NULL);
9822
0
    njs_token_serialize(NJS_TOKEN_NUMBER);
9823
0
    njs_token_serialize(NJS_TOKEN_TRUE);
9824
0
    njs_token_serialize(NJS_TOKEN_FALSE);
9825
0
    njs_token_serialize(NJS_TOKEN_STRING);
9826
0
    njs_token_serialize(NJS_TOKEN_TEMPLATE_LITERAL);
9827
0
    njs_token_serialize(NJS_TOKEN_NAME);
9828
0
    njs_token_serialize(NJS_TOKEN_OBJECT);
9829
0
    njs_token_serialize(NJS_TOKEN_OBJECT_VALUE);
9830
0
    njs_token_serialize(NJS_TOKEN_OPTIONAL_PRESERVE);
9831
0
    njs_token_serialize(NJS_TOKEN_ARRAY);
9832
0
    njs_token_serialize(NJS_TOKEN_REGEXP);
9833
9834
0
    njs_token_serialize(NJS_TOKEN_PROPERTY);
9835
0
    njs_token_serialize(NJS_TOKEN_PROPERTY_REF);
9836
0
    njs_token_serialize(NJS_TOKEN_PROPERTY_INIT);
9837
0
    njs_token_serialize(NJS_TOKEN_PROPERTY_DELETE);
9838
0
    njs_token_serialize(NJS_TOKEN_PROPERTY_GETTER);
9839
0
    njs_token_serialize(NJS_TOKEN_PROPERTY_SETTER);
9840
9841
0
    njs_token_serialize(NJS_TOKEN_PROTO_INIT);
9842
9843
0
    njs_token_serialize(NJS_TOKEN_FUNCTION);
9844
0
    njs_token_serialize(NJS_TOKEN_ASYNC_FUNCTION);
9845
0
    njs_token_serialize(NJS_TOKEN_FUNCTION_DECLARATION);
9846
0
    njs_token_serialize(NJS_TOKEN_ASYNC_FUNCTION_DECLARATION);
9847
0
    njs_token_serialize(NJS_TOKEN_FUNCTION_EXPRESSION);
9848
0
    njs_token_serialize(NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION);
9849
0
    njs_token_serialize(NJS_TOKEN_FUNCTION_CALL);
9850
0
    njs_token_serialize(NJS_TOKEN_METHOD_CALL);
9851
9852
0
    njs_token_serialize(NJS_TOKEN_ARGUMENT);
9853
0
    njs_token_serialize(NJS_TOKEN_RETURN);
9854
0
    njs_token_serialize(NJS_TOKEN_STATEMENT);
9855
0
    njs_token_serialize(NJS_TOKEN_BLOCK);
9856
0
    njs_token_serialize(NJS_TOKEN_VAR);
9857
0
    njs_token_serialize(NJS_TOKEN_LET);
9858
0
    njs_token_serialize(NJS_TOKEN_CONST);
9859
0
    njs_token_serialize(NJS_TOKEN_IF);
9860
0
    njs_token_serialize(NJS_TOKEN_ELSE);
9861
0
    njs_token_serialize(NJS_TOKEN_BRANCHING);
9862
0
    njs_token_serialize(NJS_TOKEN_WHILE);
9863
0
    njs_token_serialize(NJS_TOKEN_DO);
9864
0
    njs_token_serialize(NJS_TOKEN_FOR);
9865
0
    njs_token_serialize(NJS_TOKEN_FOR_IN);
9866
0
    njs_token_serialize(NJS_TOKEN_BREAK);
9867
0
    njs_token_serialize(NJS_TOKEN_CONTINUE);
9868
0
    njs_token_serialize(NJS_TOKEN_SWITCH);
9869
0
    njs_token_serialize(NJS_TOKEN_CASE);
9870
0
    njs_token_serialize(NJS_TOKEN_DEFAULT);
9871
0
    njs_token_serialize(NJS_TOKEN_WITH);
9872
0
    njs_token_serialize(NJS_TOKEN_TRY);
9873
0
    njs_token_serialize(NJS_TOKEN_CATCH);
9874
0
    njs_token_serialize(NJS_TOKEN_FINALLY);
9875
0
    njs_token_serialize(NJS_TOKEN_THROW);
9876
0
    njs_token_serialize(NJS_TOKEN_THIS);
9877
0
    njs_token_serialize(NJS_TOKEN_ARGUMENTS);
9878
0
    njs_token_serialize(NJS_TOKEN_EVAL);
9879
0
    njs_token_serialize(NJS_TOKEN_IMPORT);
9880
0
    njs_token_serialize(NJS_TOKEN_EXPORT);
9881
0
    njs_token_serialize(NJS_TOKEN_DEBUGGER);
9882
9883
#if 0
9884
9885
    njs_token_serialize(NJS_TOKEN_TARGET);
9886
    njs_token_serialize(NJS_TOKEN_META);
9887
    njs_token_serialize(NJS_TOKEN_ASYNC);
9888
    njs_token_serialize(NJS_TOKEN_AWAIT);
9889
    njs_token_serialize(NJS_TOKEN_ENUM);
9890
9891
    njs_token_serialize(NJS_TOKEN_CLASS);
9892
    njs_token_serialize(NJS_TOKEN_EXTENDS);
9893
    njs_token_serialize(NJS_TOKEN_IMPLEMENTS);
9894
    njs_token_serialize(NJS_TOKEN_INTERFACE);
9895
    njs_token_serialize(NJS_TOKEN_PACKAGE);
9896
    njs_token_serialize(NJS_TOKEN_PRIVATE);
9897
    njs_token_serialize(NJS_TOKEN_PROTECTED);
9898
    njs_token_serialize(NJS_TOKEN_PUBLIC);
9899
    njs_token_serialize(NJS_TOKEN_STATIC);
9900
    njs_token_serialize(NJS_TOKEN_SUPER);
9901
9902
#endif
9903
9904
0
    default:
9905
0
        njs_chb_sprintf(chain, 32, "#UNDEF(%d)", (int) node->token_type);
9906
0
        return NJS_DECLINED;
9907
0
    }
9908
9909
0
    return NJS_OK;
9910
0
}