Coverage Report

Created: 2026-10-12 06:31

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