Coverage Report

Created: 2025-11-15 06:54

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