/src/njs/src/njs_vmcode.c
Line | Count | Source |
1 | | |
2 | | /* |
3 | | * Copyright (C) Igor Sysoev |
4 | | * Copyright (C) NGINX, Inc. |
5 | | */ |
6 | | |
7 | | |
8 | | #include <njs_main.h> |
9 | | |
10 | | |
11 | | struct njs_property_next_s { |
12 | | uint32_t index; |
13 | | njs_array_t *array; |
14 | | }; |
15 | | |
16 | | static njs_jump_off_t njs_vmcode_object(njs_vm_t *vm, njs_value_t *retval); |
17 | | static njs_jump_off_t njs_vmcode_array(njs_vm_t *vm, u_char *pc, |
18 | | njs_value_t *retval); |
19 | | static njs_jump_off_t njs_vmcode_function(njs_vm_t *vm, u_char *pc); |
20 | | static njs_jump_off_t njs_vmcode_arguments(njs_vm_t *vm, u_char *pc); |
21 | | static njs_jump_off_t njs_vmcode_regexp(njs_vm_t *vm, u_char *pc, |
22 | | njs_value_t *retval); |
23 | | static njs_jump_off_t njs_vmcode_template_literal(njs_vm_t *vm, |
24 | | njs_value_t *retval); |
25 | | |
26 | | static njs_jump_off_t njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, |
27 | | njs_value_t *key, njs_value_t *retval); |
28 | | static njs_jump_off_t njs_vmcode_array_init(njs_vm_t *vm, u_char *pc, |
29 | | njs_value_t *array, njs_value_t *value); |
30 | | static njs_jump_off_t njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, |
31 | | njs_value_t *key, njs_value_t *retval); |
32 | | static njs_jump_off_t njs_vmcode_property_in(njs_vm_t *vm, |
33 | | njs_value_t *value, njs_value_t *key, njs_value_t *retval); |
34 | | static njs_jump_off_t njs_vmcode_property_foreach(njs_vm_t *vm, |
35 | | njs_value_t *object, u_char *pc, njs_value_t *retval); |
36 | | static njs_jump_off_t njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object, |
37 | | njs_value_t *constructor, njs_value_t *retval); |
38 | | static njs_jump_off_t njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, |
39 | | njs_value_t *retval); |
40 | | static njs_jump_off_t njs_vmcode_debugger(njs_vm_t *vm, njs_value_t *retval); |
41 | | |
42 | | static void njs_vmcode_return(njs_vm_t *vm, njs_value_t *dst, |
43 | | njs_value_t *retval); |
44 | | static njs_jump_off_t njs_vmcode_import(njs_vm_t *vm, njs_mod_t *module, |
45 | | njs_value_t *retval); |
46 | | |
47 | | static njs_int_t njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await, |
48 | | njs_value_t *dst, njs_promise_capability_t *pcap, njs_async_ctx_t *actx); |
49 | | |
50 | | static njs_jump_off_t njs_vmcode_try_start(njs_vm_t *vm, njs_value_t *value, |
51 | | njs_value_t *offset, u_char *pc); |
52 | | static njs_jump_off_t njs_vmcode_try_break(njs_vm_t *vm, njs_value_t *value, |
53 | | njs_value_t *offset); |
54 | | static njs_jump_off_t njs_vmcode_try_continue(njs_vm_t *vm, njs_value_t *value, |
55 | | njs_value_t *offset); |
56 | | static njs_jump_off_t njs_vmcode_try_end(njs_vm_t *vm, njs_value_t *invld, |
57 | | njs_value_t *offset); |
58 | | static njs_jump_off_t njs_vmcode_finally(njs_vm_t *vm, njs_value_t *dst, |
59 | | njs_value_t *retval, u_char *pc); |
60 | | static void njs_vmcode_error(njs_vm_t *vm, u_char *pc); |
61 | | static njs_int_t njs_throw_cannot_property(njs_vm_t *vm, njs_value_t *object, |
62 | | njs_value_t *key, const char *what); |
63 | | |
64 | | static njs_jump_off_t njs_string_concat(njs_vm_t *vm, njs_value_t *val1, |
65 | | njs_value_t *val2, njs_value_t *retval); |
66 | | static njs_jump_off_t njs_values_equal(njs_vm_t *vm, njs_value_t *val1, |
67 | | njs_value_t *val2); |
68 | | static njs_jump_off_t njs_primitive_values_compare(njs_vm_t *vm, |
69 | | njs_value_t *val1, njs_value_t *val2); |
70 | | static njs_jump_off_t njs_function_frame_create(njs_vm_t *vm, |
71 | | njs_value_t *value, const njs_value_t *this, uintptr_t nargs, |
72 | | njs_bool_t ctor); |
73 | | |
74 | | |
75 | | #define njs_vmcode_operand(vm, index, _retval) \ |
76 | 9.61M | do { \ |
77 | 9.61M | _retval = njs_scope_valid_value(vm, index); \ |
78 | 9.61M | if (njs_slow_path(_retval == NULL)) { \ |
79 | 0 | goto error; \ |
80 | 0 | } \ |
81 | 9.61M | } while (0) |
82 | | |
83 | | |
84 | | njs_int_t |
85 | | njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc, njs_value_t *rval, |
86 | | void *promise_cap, void *async_ctx) |
87 | 77.6k | { |
88 | 77.6k | u_char *catch; |
89 | 77.6k | double num, exponent; |
90 | 77.6k | int32_t i32; |
91 | 77.6k | uint32_t u32; |
92 | 77.6k | njs_bool_t valid, lambda_call; |
93 | 77.6k | njs_value_t *retval, *value1, *value2; |
94 | 77.6k | njs_value_t *src, *s1, *s2, dst; |
95 | 77.6k | njs_value_t *function, name; |
96 | 77.6k | njs_value_t numeric1, numeric2, primitive1, primitive2; |
97 | 77.6k | njs_frame_t *frame; |
98 | 77.6k | njs_jump_off_t ret; |
99 | 77.6k | njs_vmcode_1addr_t *put_arg; |
100 | 77.6k | njs_vmcode_await_t *await; |
101 | 77.6k | njs_native_frame_t *previous, *native; |
102 | 77.6k | njs_property_next_t *next; |
103 | 77.6k | njs_vmcode_import_t *import; |
104 | 77.6k | njs_vmcode_array_init_t *array_init; |
105 | 77.6k | njs_vmcode_generic_t *vmcode; |
106 | 77.6k | njs_vmcode_variable_t *var; |
107 | 77.6k | njs_vmcode_prop_get_t *get; |
108 | 77.6k | njs_vmcode_prop_set_t *set; |
109 | 77.6k | njs_vmcode_prop_next_t *pnext; |
110 | 77.6k | njs_vmcode_test_jump_t *test_jump; |
111 | 77.6k | njs_vmcode_equal_jump_t *equal; |
112 | 77.6k | njs_vmcode_try_return_t *try_return; |
113 | 77.6k | njs_vmcode_method_frame_t *method_frame; |
114 | 77.6k | njs_vmcode_prop_accessor_t *accessor; |
115 | 77.6k | njs_vmcode_try_trampoline_t *try_trampoline; |
116 | 77.6k | njs_vmcode_function_frame_t *function_frame; |
117 | | |
118 | 77.6k | njs_vmcode_debug(vm, pc, "ENTER"); |
119 | | |
120 | | #if !defined(NJS_HAVE_COMPUTED_GOTO) |
121 | | #define SWITCH(op) switch (op) |
122 | | #define CASE(op) case op |
123 | | #define BREAK pc += ret; NEXT |
124 | | |
125 | | #define NEXT vmcode = (njs_vmcode_generic_t *) pc; \ |
126 | | goto next |
127 | | |
128 | | #define NEXT_LBL next: |
129 | | #define FALLTHROUGH NJS_FALLTHROUGH |
130 | | |
131 | | #else |
132 | 5.52M | #define SWITCH(op) goto *switch_tbl[(uint8_t) op]; |
133 | 5.20M | #define CASE(op) case_ ## op |
134 | 3.76M | #define BREAK pc += ret; NEXT |
135 | | |
136 | 5.45M | #define NEXT vmcode = (njs_vmcode_generic_t *) pc; \ |
137 | 5.45M | SWITCH (vmcode->code) |
138 | | |
139 | 77.6k | #define NEXT_LBL |
140 | 77.6k | #define FALLTHROUGH |
141 | | |
142 | 6.67M | #define NJS_GOTO_ROW(name) [ (uint8_t) name ] = &&case_ ## name |
143 | | |
144 | 77.6k | static const void * const switch_tbl[NJS_VMCODES] = { |
145 | | |
146 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PUT_ARG), |
147 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_STOP), |
148 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_JUMP), |
149 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_SET), |
150 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_SET), |
151 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ACCESSOR), |
152 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_IF_TRUE_JUMP), |
153 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_IF_FALSE_JUMP), |
154 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_IF_EQUAL_JUMP), |
155 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_INIT), |
156 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ARRAY_INIT), |
157 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_RETURN), |
158 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_FUNCTION_FRAME), |
159 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_METHOD_FRAME), |
160 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_FUNCTION_CALL), |
161 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_NEXT), |
162 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ARGUMENTS), |
163 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROTO_INIT), |
164 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TO_PROPERTY_KEY), |
165 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TO_PROPERTY_KEY_CHK), |
166 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_SET_FUNCTION_NAME), |
167 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_IMPORT), |
168 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_AWAIT), |
169 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TRY_START), |
170 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_THROW), |
171 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TRY_BREAK), |
172 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TRY_CONTINUE), |
173 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TRY_END), |
174 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_CATCH), |
175 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_FINALLY), |
176 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LET), |
177 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LET_UPDATE), |
178 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_INITIALIZATION_TEST), |
179 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_NOT_INITIALIZED), |
180 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ASSIGNMENT_ERROR), |
181 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ERROR), |
182 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_MOVE), |
183 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_ATOM_GET), |
184 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_GET), |
185 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_INCREMENT), |
186 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_POST_INCREMENT), |
187 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_DECREMENT), |
188 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_POST_DECREMENT), |
189 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TRY_RETURN), |
190 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_GLOBAL_GET), |
191 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LESS), |
192 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_GREATER), |
193 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LESS_OR_EQUAL), |
194 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_GREATER_OR_EQUAL), |
195 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ADDITION), |
196 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_EQUAL), |
197 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_NOT_EQUAL), |
198 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_SUBTRACTION), |
199 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_MULTIPLICATION), |
200 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_EXPONENTIATION), |
201 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_DIVISION), |
202 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_REMAINDER), |
203 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_BITWISE_AND), |
204 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_BITWISE_OR), |
205 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_BITWISE_XOR), |
206 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LEFT_SHIFT), |
207 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_RIGHT_SHIFT), |
208 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_UNSIGNED_RIGHT_SHIFT), |
209 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TEMPLATE_LITERAL), |
210 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_IN), |
211 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_DELETE), |
212 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_PROPERTY_FOREACH), |
213 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_STRICT_EQUAL), |
214 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_STRICT_NOT_EQUAL), |
215 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TEST_IF_TRUE), |
216 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TEST_IF_FALSE), |
217 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_COALESCE), |
218 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_OPTIONAL_CHAIN), |
219 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_UNARY_PLUS), |
220 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_UNARY_NEGATION), |
221 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_BITWISE_NOT), |
222 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_LOGICAL_NOT), |
223 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_OBJECT), |
224 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_ARRAY), |
225 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_FUNCTION), |
226 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_REGEXP), |
227 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_INSTANCE_OF), |
228 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_TYPEOF), |
229 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_VOID), |
230 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_DELETE), |
231 | 77.6k | NJS_GOTO_ROW(NJS_VMCODE_DEBUGGER), |
232 | 77.6k | }; |
233 | | |
234 | 77.6k | #endif |
235 | | |
236 | 77.6k | if (async_ctx != NULL && ((njs_async_ctx_t *) async_ctx)->throw_flag) { |
237 | 0 | goto error; |
238 | 0 | } |
239 | | |
240 | 77.6k | vmcode = (njs_vmcode_generic_t *) pc; |
241 | | |
242 | 77.6k | NEXT_LBL; |
243 | | |
244 | 77.6k | SWITCH (vmcode->code) { |
245 | | |
246 | 320k | CASE (NJS_VMCODE_MOVE): |
247 | 320k | njs_vmcode_debug_opcode(); |
248 | | |
249 | 320k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
250 | 320k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
251 | 320k | *retval = *value1; |
252 | | |
253 | 320k | pc += sizeof(njs_vmcode_move_t); |
254 | 320k | NEXT; |
255 | | |
256 | 331k | CASE (NJS_VMCODE_PROPERTY_ATOM_GET): |
257 | 331k | njs_vmcode_debug_opcode(); |
258 | | |
259 | 331k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
260 | 331k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
261 | 331k | get = (njs_vmcode_prop_get_t *) pc; |
262 | 331k | njs_vmcode_operand(vm, get->value, retval); |
263 | | |
264 | 331k | ret = njs_value_property(vm, value1, value2->atom_id, retval); |
265 | 331k | if (njs_slow_path(ret == NJS_ERROR)) { |
266 | 18 | goto error; |
267 | 18 | } |
268 | | |
269 | 331k | pc += sizeof(njs_vmcode_prop_get_t); |
270 | 331k | NEXT; |
271 | | |
272 | 331k | CASE (NJS_VMCODE_PROPERTY_GET): |
273 | 18.3k | njs_vmcode_debug_opcode(); |
274 | | |
275 | 18.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
276 | 18.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
277 | | |
278 | 18.3k | get = (njs_vmcode_prop_get_t *) pc; |
279 | 18.3k | njs_vmcode_operand(vm, get->value, retval); |
280 | | |
281 | 18.3k | if (njs_slow_path(!njs_is_index_or_key(value2))) { |
282 | 0 | if (njs_slow_path(njs_is_null_or_undefined(value1))) { |
283 | 0 | (void) njs_throw_cannot_property(vm, value1, value2, "get"); |
284 | 0 | goto error; |
285 | 0 | } |
286 | | |
287 | 0 | ret = njs_value_to_key(vm, &primitive1, value2); |
288 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
289 | 0 | goto error; |
290 | 0 | } |
291 | | |
292 | 0 | value2 = &primitive1; |
293 | 0 | } |
294 | | |
295 | 18.3k | if (value2->atom_id == NJS_ATOM_STRING_unknown) { |
296 | 18.3k | num = njs_number(value2); |
297 | | |
298 | 18.3k | if (njs_fast_path(njs_number_is_atom_index(num, &u32))) { |
299 | 18.3k | value2->atom_id = njs_number_atom(u32); |
300 | | |
301 | 18.3k | } else { |
302 | 0 | ret = njs_atom_atomize_key(vm, value2); |
303 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
304 | 0 | goto error; |
305 | 0 | } |
306 | 0 | } |
307 | 18.3k | } |
308 | | |
309 | 18.3k | ret = njs_value_property(vm, value1, value2->atom_id, retval); |
310 | 18.3k | if (njs_slow_path(ret == NJS_ERROR)) { |
311 | 0 | goto error; |
312 | 0 | } |
313 | | |
314 | 18.3k | pc += sizeof(njs_vmcode_prop_get_t); |
315 | 18.3k | NEXT; |
316 | | |
317 | 18.3k | CASE (NJS_VMCODE_INCREMENT): |
318 | 0 | njs_vmcode_debug_opcode(); |
319 | |
|
320 | 0 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
321 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
322 | | |
323 | 0 | if (njs_slow_path(!njs_is_numeric(value2))) { |
324 | 0 | ret = njs_value_to_numeric(vm, value2, &numeric1); |
325 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
326 | 0 | goto error; |
327 | 0 | } |
328 | | |
329 | 0 | num = njs_number(&numeric1); |
330 | |
|
331 | 0 | } else { |
332 | 0 | num = njs_number(value2); |
333 | 0 | } |
334 | | |
335 | 0 | njs_set_number(value1, num + 1); |
336 | |
|
337 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
338 | | |
339 | 0 | *retval = *value1; |
340 | |
|
341 | 0 | pc += sizeof(njs_vmcode_3addr_t); |
342 | 0 | NEXT; |
343 | |
|
344 | 18.3k | CASE (NJS_VMCODE_POST_INCREMENT): |
345 | 18.3k | njs_vmcode_debug_opcode(); |
346 | | |
347 | 18.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
348 | 18.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
349 | | |
350 | 18.3k | if (njs_slow_path(!njs_is_numeric(value2))) { |
351 | 18.3k | ret = njs_value_to_numeric(vm, value2, &numeric1); |
352 | 18.3k | if (njs_slow_path(ret != NJS_OK)) { |
353 | 0 | goto error; |
354 | 0 | } |
355 | | |
356 | 18.3k | num = njs_number(&numeric1); |
357 | | |
358 | 18.3k | } else { |
359 | 35 | num = njs_number(value2); |
360 | 35 | } |
361 | | |
362 | 18.3k | njs_set_number(value1, num + 1); |
363 | | |
364 | 18.3k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
365 | | |
366 | 18.3k | njs_set_number(retval, num); |
367 | | |
368 | 18.3k | pc += sizeof(njs_vmcode_3addr_t); |
369 | 18.3k | NEXT; |
370 | | |
371 | 18.3k | CASE (NJS_VMCODE_DECREMENT): |
372 | 2.16k | njs_vmcode_debug_opcode(); |
373 | | |
374 | 2.16k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
375 | 2.16k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
376 | | |
377 | 2.16k | if (njs_slow_path(!njs_is_numeric(value2))) { |
378 | 2.16k | ret = njs_value_to_numeric(vm, value2, &numeric1); |
379 | 2.16k | if (njs_slow_path(ret != NJS_OK)) { |
380 | 0 | goto error; |
381 | 0 | } |
382 | | |
383 | 2.16k | num = njs_number(&numeric1); |
384 | | |
385 | 2.16k | } else { |
386 | 0 | num = njs_number(value2); |
387 | 0 | } |
388 | | |
389 | 2.16k | njs_set_number(value1, num - 1); |
390 | | |
391 | 2.16k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
392 | | |
393 | 2.16k | *retval = *value1; |
394 | | |
395 | 2.16k | pc += sizeof(njs_vmcode_3addr_t); |
396 | 2.16k | NEXT; |
397 | | |
398 | 20.4k | CASE (NJS_VMCODE_POST_DECREMENT): |
399 | 20.4k | njs_vmcode_debug_opcode(); |
400 | | |
401 | 20.4k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
402 | 20.4k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
403 | | |
404 | 20.4k | if (njs_slow_path(!njs_is_numeric(value2))) { |
405 | 2.16k | ret = njs_value_to_numeric(vm, value2, &numeric1); |
406 | 2.16k | if (njs_slow_path(ret != NJS_OK)) { |
407 | 0 | goto error; |
408 | 0 | } |
409 | | |
410 | 2.16k | num = njs_number(&numeric1); |
411 | | |
412 | 18.3k | } else { |
413 | 18.3k | num = njs_number(value2); |
414 | 18.3k | } |
415 | | |
416 | 20.4k | njs_set_number(value1, num - 1); |
417 | | |
418 | 20.4k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
419 | | |
420 | 20.4k | njs_set_number(retval, num); |
421 | | |
422 | 20.4k | pc += sizeof(njs_vmcode_3addr_t); |
423 | 20.4k | NEXT; |
424 | | |
425 | 282k | CASE (NJS_VMCODE_GLOBAL_GET): |
426 | 282k | njs_vmcode_debug_opcode(); |
427 | | |
428 | 282k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
429 | 282k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
430 | | |
431 | 282k | get = (njs_vmcode_prop_get_t *) pc; |
432 | 282k | njs_vmcode_operand(vm, get->value, retval); |
433 | | |
434 | 282k | ret = njs_value_property_val(vm, value1, value2, retval); |
435 | 282k | if (njs_slow_path(ret == NJS_ERROR)) { |
436 | 0 | goto error; |
437 | 0 | } |
438 | | |
439 | 282k | pc += sizeof(njs_vmcode_prop_get_t); |
440 | | |
441 | 282k | if (ret == NJS_OK) { |
442 | 260k | pc += sizeof(njs_vmcode_error_t); |
443 | 260k | } |
444 | | |
445 | 282k | NEXT; |
446 | | |
447 | | /* |
448 | | * njs_vmcode_try_return() saves a return value to use it later by |
449 | | * njs_vmcode_finally(), and jumps to the nearest try_break block. |
450 | | */ |
451 | 282k | CASE (NJS_VMCODE_TRY_RETURN): |
452 | 0 | njs_vmcode_debug_opcode(); |
453 | |
|
454 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
455 | | |
456 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
457 | 0 | *retval = *value1; |
458 | |
|
459 | 0 | try_return = (njs_vmcode_try_return_t *) pc; |
460 | 0 | pc += try_return->offset; |
461 | 0 | NEXT; |
462 | |
|
463 | 2.23k | CASE (NJS_VMCODE_LESS): |
464 | 2.23k | njs_vmcode_debug_opcode(); |
465 | | |
466 | 2.23k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
467 | 2.23k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
468 | | |
469 | 2.23k | if (njs_slow_path(!njs_is_primitive(value1))) { |
470 | 0 | ret = njs_value_to_primitive(vm, &primitive1, value1, |
471 | 0 | NJS_HINT_NUMBER); |
472 | 0 | if (ret != NJS_OK) { |
473 | 0 | goto error; |
474 | 0 | } |
475 | | |
476 | 0 | value1 = &primitive1; |
477 | 0 | } |
478 | | |
479 | 2.23k | if (njs_slow_path(!njs_is_primitive(value2))) { |
480 | 0 | ret = njs_value_to_primitive(vm, &primitive2, value2, |
481 | 0 | NJS_HINT_NUMBER); |
482 | 0 | if (ret != NJS_OK) { |
483 | 0 | goto error; |
484 | 0 | } |
485 | | |
486 | 0 | value2 = &primitive2; |
487 | 0 | } |
488 | | |
489 | 2.23k | if (njs_slow_path(njs_is_symbol(value1) |
490 | 2.23k | || njs_is_symbol(value2))) |
491 | 0 | { |
492 | 0 | njs_symbol_conversion_failed(vm, 0); |
493 | 0 | goto error; |
494 | 0 | } |
495 | | |
496 | 2.23k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
497 | | |
498 | 2.23k | njs_set_boolean(retval, |
499 | 2.23k | njs_primitive_values_compare(vm, value1, value2) > 0); |
500 | | |
501 | 2.23k | pc += sizeof(njs_vmcode_3addr_t); |
502 | 2.23k | NEXT; |
503 | | |
504 | 18.5k | CASE (NJS_VMCODE_GREATER): |
505 | 18.5k | njs_vmcode_debug_opcode(); |
506 | | |
507 | 18.5k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
508 | 18.5k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
509 | | |
510 | 18.5k | if (njs_slow_path(!njs_is_primitive(value1))) { |
511 | 0 | ret = njs_value_to_primitive(vm, &primitive1, value1, |
512 | 0 | NJS_HINT_NUMBER); |
513 | 0 | if (ret != NJS_OK) { |
514 | 0 | goto error; |
515 | 0 | } |
516 | | |
517 | 0 | value1 = &primitive1; |
518 | 0 | } |
519 | | |
520 | 18.5k | if (njs_slow_path(!njs_is_primitive(value2))) { |
521 | 9 | ret = njs_value_to_primitive(vm, &primitive2, value2, |
522 | 9 | NJS_HINT_NUMBER); |
523 | 9 | if (ret != NJS_OK) { |
524 | 0 | goto error; |
525 | 0 | } |
526 | | |
527 | 9 | value2 = &primitive2; |
528 | 9 | } |
529 | | |
530 | 18.5k | if (njs_slow_path(njs_is_symbol(value1) |
531 | 18.5k | || njs_is_symbol(value2))) |
532 | 0 | { |
533 | 0 | njs_symbol_conversion_failed(vm, 0); |
534 | 0 | goto error; |
535 | 0 | } |
536 | | |
537 | 18.5k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
538 | | |
539 | 18.5k | njs_set_boolean(retval, |
540 | 18.5k | njs_primitive_values_compare(vm, value2, value1) > 0); |
541 | | |
542 | 18.5k | pc += sizeof(njs_vmcode_3addr_t); |
543 | 18.5k | NEXT; |
544 | | |
545 | 28.3k | CASE (NJS_VMCODE_LESS_OR_EQUAL): |
546 | 28.3k | njs_vmcode_debug_opcode(); |
547 | | |
548 | 28.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
549 | 28.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
550 | | |
551 | 28.3k | if (njs_slow_path(!njs_is_primitive(value1))) { |
552 | 63 | ret = njs_value_to_primitive(vm, &primitive1, value1, |
553 | 63 | NJS_HINT_NUMBER); |
554 | 63 | if (ret != NJS_OK) { |
555 | 0 | goto error; |
556 | 0 | } |
557 | | |
558 | 63 | value1 = &primitive1; |
559 | 63 | } |
560 | | |
561 | 28.3k | if (njs_slow_path(!njs_is_primitive(value2))) { |
562 | 28.3k | ret = njs_value_to_primitive(vm, &primitive2, value2, |
563 | 28.3k | NJS_HINT_NUMBER); |
564 | 28.3k | if (ret != NJS_OK) { |
565 | 0 | goto error; |
566 | 0 | } |
567 | | |
568 | 28.3k | value2 = &primitive2; |
569 | 28.3k | } |
570 | | |
571 | 28.3k | if (njs_slow_path(njs_is_symbol(value1) |
572 | 28.3k | || njs_is_symbol(value2))) |
573 | 0 | { |
574 | 0 | njs_symbol_conversion_failed(vm, 0); |
575 | 0 | goto error; |
576 | 0 | } |
577 | | |
578 | 28.3k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
579 | | |
580 | 28.3k | njs_set_boolean(retval, |
581 | 28.3k | njs_primitive_values_compare(vm, value2, value1) == 0); |
582 | | |
583 | 28.3k | pc += sizeof(njs_vmcode_3addr_t); |
584 | 28.3k | NEXT; |
585 | | |
586 | 39.1k | CASE (NJS_VMCODE_GREATER_OR_EQUAL): |
587 | 39.1k | njs_vmcode_debug_opcode(); |
588 | | |
589 | 39.1k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
590 | 39.1k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
591 | | |
592 | 39.1k | if (njs_slow_path(!njs_is_primitive(value1))) { |
593 | 28.2k | ret = njs_value_to_primitive(vm, &primitive1, value1, |
594 | 28.2k | NJS_HINT_NUMBER); |
595 | 28.2k | if (ret != NJS_OK) { |
596 | 0 | goto error; |
597 | 0 | } |
598 | | |
599 | 28.2k | value1 = &primitive1; |
600 | 28.2k | } |
601 | | |
602 | 39.1k | if (njs_slow_path(!njs_is_primitive(value2))) { |
603 | 2.16k | ret = njs_value_to_primitive(vm, &primitive2, value2, |
604 | 2.16k | NJS_HINT_NUMBER); |
605 | 2.16k | if (ret != NJS_OK) { |
606 | 0 | goto error; |
607 | 0 | } |
608 | | |
609 | 2.16k | value2 = &primitive2; |
610 | 2.16k | } |
611 | | |
612 | 39.1k | if (njs_slow_path(njs_is_symbol(value1) |
613 | 39.1k | || njs_is_symbol(value2))) |
614 | 0 | { |
615 | 0 | njs_symbol_conversion_failed(vm, 0); |
616 | 0 | goto error; |
617 | 0 | } |
618 | | |
619 | 39.1k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
620 | | |
621 | 39.1k | njs_set_boolean(retval, |
622 | 39.1k | njs_primitive_values_compare(vm, value1, value2) == 0); |
623 | | |
624 | 39.1k | pc += sizeof(njs_vmcode_3addr_t); |
625 | 39.1k | NEXT; |
626 | | |
627 | 202k | CASE (NJS_VMCODE_ADDITION): |
628 | 202k | njs_vmcode_debug_opcode(); |
629 | | |
630 | 202k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
631 | 202k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
632 | | |
633 | 202k | if (njs_slow_path(!njs_is_primitive(value1))) { |
634 | 3.02k | ret = njs_value_to_primitive(vm, &primitive1, value1, |
635 | 3.02k | NJS_HINT_NONE); |
636 | 3.02k | if (ret != NJS_OK) { |
637 | 0 | goto error; |
638 | 0 | } |
639 | | |
640 | 3.02k | value1 = &primitive1; |
641 | 3.02k | } |
642 | | |
643 | 202k | if (njs_slow_path(!njs_is_primitive(value2))) { |
644 | 58.8k | ret = njs_value_to_primitive(vm, &primitive2, value2, |
645 | 58.8k | NJS_HINT_NONE); |
646 | 58.8k | if (ret != NJS_OK) { |
647 | 0 | goto error; |
648 | 0 | } |
649 | | |
650 | 58.8k | value2 = &primitive2; |
651 | 58.8k | } |
652 | | |
653 | 202k | if (njs_slow_path(njs_is_symbol(value1) |
654 | 202k | || njs_is_symbol(value2))) |
655 | 0 | { |
656 | 0 | njs_symbol_conversion_failed(vm, |
657 | 0 | (njs_is_string(value1) || njs_is_string(value2))); |
658 | |
|
659 | 0 | goto error; |
660 | 0 | } |
661 | | |
662 | 202k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
663 | | |
664 | 202k | if (njs_fast_path(njs_is_numeric(value1) |
665 | 202k | && njs_is_numeric(value2))) |
666 | 34.7k | { |
667 | 34.7k | njs_set_number(retval, njs_number(value1) |
668 | 34.7k | + njs_number(value2)); |
669 | 34.7k | pc += sizeof(njs_vmcode_3addr_t); |
670 | 34.7k | NEXT; |
671 | 34.7k | } |
672 | | |
673 | 202k | if (njs_is_string(value1)) { |
674 | 47.5k | s1 = value1; |
675 | 47.5k | s2 = &dst; |
676 | 47.5k | src = value2; |
677 | | |
678 | 155k | } else { |
679 | 155k | s1 = &dst; |
680 | 155k | s2 = value2; |
681 | 155k | src = value1; |
682 | 155k | } |
683 | | |
684 | 202k | if (njs_is_number(src)) { |
685 | 163k | size_t size; |
686 | 163k | njs_string_t sp; |
687 | 163k | char buf[64]; |
688 | | |
689 | | /* Alloc free path for "str" + int or int + "str" concatenation. */ |
690 | | |
691 | 163k | num = njs_number(src); |
692 | | |
693 | 163k | if (isnan(num)) { |
694 | 146 | njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_NaN); |
695 | | |
696 | 163k | } else if (isinf(num)) { |
697 | |
|
698 | 0 | if (num < 0) { |
699 | 0 | njs_atom_to_value(vm, &dst, NJS_ATOM_STRING__Infinity); |
700 | |
|
701 | 0 | } else { |
702 | 0 | njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_Infinity); |
703 | 0 | } |
704 | |
|
705 | 163k | } else { |
706 | 163k | size = njs_dtoa(num, buf); |
707 | | |
708 | 163k | sp.start = (u_char *) buf; |
709 | 163k | sp.size = size; |
710 | 163k | sp.length = size; |
711 | | |
712 | 163k | dst.string.data = &sp; |
713 | 163k | } |
714 | | |
715 | 163k | ret = njs_string_concat(vm, s1, s2, &name); |
716 | 163k | if (njs_slow_path(ret == NJS_ERROR)) { |
717 | 0 | goto error; |
718 | 0 | } |
719 | | |
720 | 163k | } else { |
721 | 38.8k | ret = njs_primitive_value_to_string(vm, &dst, src); |
722 | 38.8k | if (njs_slow_path(ret != NJS_OK)) { |
723 | 0 | goto error; |
724 | 0 | } |
725 | | |
726 | 38.8k | ret = njs_string_concat(vm, s1, s2, &name); |
727 | 38.8k | if (njs_slow_path(ret == NJS_ERROR)) { |
728 | 0 | goto error; |
729 | 0 | } |
730 | 38.8k | } |
731 | | |
732 | 202k | njs_value_assign(retval, &name); |
733 | | |
734 | 202k | BREAK; |
735 | | |
736 | 202k | CASE (NJS_VMCODE_EQUAL): |
737 | 0 | njs_vmcode_debug_opcode(); |
738 | |
|
739 | 0 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
740 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
741 | | |
742 | 0 | ret = njs_values_equal(vm, value1, value2); |
743 | 0 | if (njs_slow_path(ret < 0)) { |
744 | 0 | goto error; |
745 | 0 | } |
746 | | |
747 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
748 | 0 | njs_set_boolean(retval, ret); |
749 | |
|
750 | 0 | pc += sizeof(njs_vmcode_3addr_t); |
751 | 0 | NEXT; |
752 | |
|
753 | 10.6k | CASE (NJS_VMCODE_NOT_EQUAL): |
754 | 10.6k | njs_vmcode_debug_opcode(); |
755 | | |
756 | 10.6k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
757 | 10.6k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
758 | | |
759 | 10.6k | ret = njs_values_equal(vm, value1, value2); |
760 | 10.6k | if (njs_slow_path(ret < 0)) { |
761 | 0 | goto error; |
762 | 0 | } |
763 | | |
764 | 10.6k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
765 | 10.6k | njs_set_boolean(retval, !ret); |
766 | | |
767 | 10.6k | pc += sizeof(njs_vmcode_3addr_t); |
768 | 10.6k | NEXT; |
769 | | |
770 | 10.6k | #define NJS_PRE_NUMERIC \ |
771 | 10.6k | \ |
772 | 408k | if (njs_slow_path(!njs_is_numeric(value1))) { \ |
773 | 118k | ret = njs_value_to_numeric(vm, value1, &numeric1); \ |
774 | 118k | if (njs_slow_path(ret != NJS_OK)) { \ |
775 | 0 | goto error; \ |
776 | 0 | } \ |
777 | 118k | \ |
778 | 118k | value1 = &numeric1; \ |
779 | 118k | } \ |
780 | 408k | \ |
781 | 408k | if (njs_slow_path(!njs_is_numeric(value2))) { \ |
782 | 155k | ret = njs_value_to_numeric(vm, value2, &numeric2); \ |
783 | 155k | if (njs_slow_path(ret != NJS_OK)) { \ |
784 | 0 | goto error; \ |
785 | 0 | } \ |
786 | 155k | \ |
787 | 155k | value2 = &numeric2; \ |
788 | 155k | } \ |
789 | 408k | \ |
790 | 408k | num = njs_number(value1); \ |
791 | 408k | \ |
792 | 408k | njs_vmcode_operand(vm, vmcode->operand1, retval); \ |
793 | 408k | pc += sizeof(njs_vmcode_3addr_t) |
794 | | |
795 | 147k | CASE (NJS_VMCODE_SUBTRACTION): |
796 | 147k | njs_vmcode_debug_opcode(); |
797 | | |
798 | 147k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
799 | 147k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
800 | | |
801 | 591k | NJS_PRE_NUMERIC; |
802 | | |
803 | 591k | num -= njs_number(value2); |
804 | | |
805 | 591k | njs_set_number(retval, num); |
806 | 591k | NEXT; |
807 | | |
808 | 591k | CASE (NJS_VMCODE_MULTIPLICATION): |
809 | 34.7k | njs_vmcode_debug_opcode(); |
810 | | |
811 | 34.7k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
812 | 34.7k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
813 | | |
814 | 139k | NJS_PRE_NUMERIC; |
815 | | |
816 | 139k | num *= njs_number(value2); |
817 | | |
818 | 139k | njs_set_number(retval, num); |
819 | 139k | NEXT; |
820 | | |
821 | 139k | CASE (NJS_VMCODE_EXPONENTIATION): |
822 | 26.0k | njs_vmcode_debug_opcode(); |
823 | | |
824 | 26.0k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
825 | 26.0k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
826 | | |
827 | 104k | NJS_PRE_NUMERIC; |
828 | | |
829 | 104k | exponent = njs_number(value2); |
830 | | /* |
831 | | * According to ES7: |
832 | | * 1. If exponent is NaN, the result should be NaN; |
833 | | * 2. The result of +/-1 ** +/-Infinity should be NaN. |
834 | | */ |
835 | 104k | valid = njs_expect(1, fabs(num) != 1 |
836 | 104k | || (!isnan(exponent) |
837 | 104k | && !isinf(exponent))); |
838 | | |
839 | 104k | num = valid ? pow(num, exponent) : NAN; |
840 | | |
841 | 104k | njs_set_number(retval, num); |
842 | 104k | NEXT; |
843 | | |
844 | 104k | CASE (NJS_VMCODE_DIVISION): |
845 | 39.1k | njs_vmcode_debug_opcode(); |
846 | | |
847 | 39.1k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
848 | 39.1k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
849 | | |
850 | 156k | NJS_PRE_NUMERIC; |
851 | | |
852 | 156k | num /= njs_number(value2); |
853 | | |
854 | 156k | njs_set_number(retval, num); |
855 | 156k | NEXT; |
856 | | |
857 | 156k | CASE (NJS_VMCODE_REMAINDER): |
858 | 87.6k | njs_vmcode_debug_opcode(); |
859 | | |
860 | 87.6k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
861 | 87.6k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
862 | | |
863 | 350k | NJS_PRE_NUMERIC; |
864 | | |
865 | 350k | num = fmod(num, njs_number(value2)); |
866 | | |
867 | 350k | njs_set_number(retval, num); |
868 | 350k | NEXT; |
869 | | |
870 | 350k | CASE (NJS_VMCODE_BITWISE_AND): |
871 | 18.7k | njs_vmcode_debug_opcode(); |
872 | | |
873 | 18.7k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
874 | 18.7k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
875 | | |
876 | 75.1k | NJS_PRE_NUMERIC; |
877 | | |
878 | 75.1k | i32 = njs_number_to_int32(njs_number(value2)); |
879 | 75.1k | i32 &= njs_number_to_int32(num); |
880 | | |
881 | 75.1k | njs_set_int32(retval, i32); |
882 | 75.1k | NEXT; |
883 | | |
884 | 75.1k | CASE (NJS_VMCODE_BITWISE_OR): |
885 | 6.56k | njs_vmcode_debug_opcode(); |
886 | | |
887 | 6.56k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
888 | 6.56k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
889 | | |
890 | 26.2k | NJS_PRE_NUMERIC; |
891 | | |
892 | 26.2k | i32 = njs_number_to_int32(njs_number(value2)); |
893 | 26.2k | i32 |= njs_number_to_int32(num); |
894 | | |
895 | 26.2k | njs_set_int32(retval, i32); |
896 | 26.2k | NEXT; |
897 | | |
898 | 26.2k | CASE (NJS_VMCODE_BITWISE_XOR): |
899 | 26.1k | njs_vmcode_debug_opcode(); |
900 | | |
901 | 26.1k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
902 | 26.1k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
903 | | |
904 | 104k | NJS_PRE_NUMERIC; |
905 | | |
906 | 104k | i32 = njs_number_to_int32(njs_number(value2)); |
907 | 104k | i32 ^= njs_number_to_int32(num); |
908 | | |
909 | 104k | njs_set_int32(retval, i32); |
910 | 104k | NEXT; |
911 | | |
912 | 104k | CASE (NJS_VMCODE_LEFT_SHIFT): |
913 | 6 | njs_vmcode_debug_opcode(); |
914 | | |
915 | 6 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
916 | 6 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
917 | | |
918 | 24 | NJS_PRE_NUMERIC; |
919 | | |
920 | 24 | u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f; |
921 | 24 | i32 = njs_number_to_int32(num); |
922 | | |
923 | | /* Shifting of negative numbers is undefined. */ |
924 | 24 | i32 = (uint32_t) i32 << u32; |
925 | | |
926 | 24 | njs_set_int32(retval, i32); |
927 | 24 | NEXT; |
928 | | |
929 | 12.0k | CASE (NJS_VMCODE_RIGHT_SHIFT): |
930 | 12.0k | njs_vmcode_debug_opcode(); |
931 | | |
932 | 12.0k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
933 | 12.0k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
934 | | |
935 | 48.2k | NJS_PRE_NUMERIC; |
936 | | |
937 | 48.2k | u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f; |
938 | 48.2k | i32 = njs_number_to_int32(num); |
939 | | |
940 | 48.2k | i32 >>= u32; |
941 | | |
942 | 48.2k | njs_set_int32(retval, i32); |
943 | 48.2k | NEXT; |
944 | | |
945 | 48.2k | CASE (NJS_VMCODE_UNSIGNED_RIGHT_SHIFT): |
946 | 9.50k | njs_vmcode_debug_opcode(); |
947 | | |
948 | 9.50k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
949 | 9.50k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
950 | | |
951 | 38.0k | NJS_PRE_NUMERIC; |
952 | | |
953 | 38.0k | u32 = njs_number_to_uint32(njs_number(value2)) & 0x1f; |
954 | 38.0k | njs_set_uint32(retval, njs_number_to_uint32(num) >> u32); |
955 | 38.0k | NEXT; |
956 | | |
957 | 117k | CASE (NJS_VMCODE_TEMPLATE_LITERAL): |
958 | 117k | njs_vmcode_debug_opcode(); |
959 | | |
960 | 117k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
961 | | |
962 | 117k | ret = njs_vmcode_template_literal(vm, retval); |
963 | | |
964 | 117k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
965 | 0 | goto error; |
966 | 0 | } |
967 | | |
968 | 117k | BREAK; |
969 | | |
970 | 117k | CASE (NJS_VMCODE_PROPERTY_IN): |
971 | 1 | njs_vmcode_debug_opcode(); |
972 | | |
973 | 1 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
974 | 1 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
975 | 1 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
976 | | |
977 | 1 | ret = njs_vmcode_property_in(vm, value1, value2, retval); |
978 | 1 | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
979 | 1 | goto error; |
980 | 1 | } |
981 | | |
982 | 0 | BREAK; |
983 | |
|
984 | 1.53k | CASE (NJS_VMCODE_PROPERTY_DELETE): |
985 | 1.53k | njs_vmcode_debug_opcode(); |
986 | | |
987 | 1.53k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
988 | 1.53k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
989 | | |
990 | 1.53k | if (njs_slow_path(!njs_is_index_or_key(value2))) { |
991 | 0 | if (njs_slow_path(njs_is_null_or_undefined(value1))) { |
992 | 0 | (void) njs_throw_cannot_property(vm, value1, value2, "delete"); |
993 | 0 | goto error; |
994 | 0 | } |
995 | | |
996 | 0 | ret = njs_value_to_key(vm, &primitive1, value2); |
997 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
998 | 0 | goto error; |
999 | 0 | } |
1000 | | |
1001 | 0 | value2 = &primitive1; |
1002 | 0 | } |
1003 | | |
1004 | 1.53k | ret = njs_value_property_val_delete(vm, value1, value2, NULL, 1); |
1005 | 1.53k | if (njs_slow_path(ret == NJS_ERROR)) { |
1006 | 0 | goto error; |
1007 | 0 | } |
1008 | | |
1009 | 1.53k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1010 | 1.53k | njs_value_assign(retval, &njs_value_true); |
1011 | 1.53k | ret = sizeof(njs_vmcode_3addr_t); |
1012 | | |
1013 | 1.53k | BREAK; |
1014 | | |
1015 | 1.97k | CASE (NJS_VMCODE_PROPERTY_FOREACH): |
1016 | 1.97k | njs_vmcode_debug_opcode(); |
1017 | | |
1018 | 1.97k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1019 | 1.97k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1020 | | |
1021 | 1.97k | ret = njs_vmcode_property_foreach(vm, value1, pc, retval); |
1022 | 1.97k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1023 | 0 | goto error; |
1024 | 0 | } |
1025 | | |
1026 | 1.97k | BREAK; |
1027 | | |
1028 | 1.97k | CASE (NJS_VMCODE_STRICT_EQUAL): |
1029 | 0 | njs_vmcode_debug_opcode(); |
1030 | |
|
1031 | 0 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1032 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1033 | | |
1034 | 0 | ret = njs_values_strict_equal(vm, value1, value2); |
1035 | |
|
1036 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1037 | 0 | njs_set_boolean(retval, ret); |
1038 | |
|
1039 | 0 | pc += sizeof(njs_vmcode_3addr_t); |
1040 | 0 | NEXT; |
1041 | |
|
1042 | 10.3k | CASE (NJS_VMCODE_STRICT_NOT_EQUAL): |
1043 | 10.3k | njs_vmcode_debug_opcode(); |
1044 | | |
1045 | 10.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1046 | 10.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1047 | | |
1048 | 10.3k | ret = njs_values_strict_equal(vm, value1, value2); |
1049 | | |
1050 | 10.3k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1051 | 10.3k | njs_set_boolean(retval, !ret); |
1052 | | |
1053 | 10.3k | pc += sizeof(njs_vmcode_3addr_t); |
1054 | 10.3k | NEXT; |
1055 | | |
1056 | 10.3k | CASE (NJS_VMCODE_TEST_IF_TRUE): |
1057 | 5 | njs_vmcode_debug_opcode(); |
1058 | | |
1059 | 5 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1060 | | |
1061 | 5 | ret = njs_is_true(value1); |
1062 | | |
1063 | 5 | if (ret) { |
1064 | 0 | test_jump = (njs_vmcode_test_jump_t *) pc; |
1065 | 0 | ret = test_jump->offset; |
1066 | |
|
1067 | 5 | } else { |
1068 | 5 | ret = sizeof(njs_vmcode_3addr_t); |
1069 | 5 | } |
1070 | | |
1071 | 5 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1072 | 5 | *retval = *value1; |
1073 | | |
1074 | 5 | BREAK; |
1075 | | |
1076 | 89 | CASE (NJS_VMCODE_TEST_IF_FALSE): |
1077 | 89 | njs_vmcode_debug_opcode(); |
1078 | | |
1079 | 89 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1080 | | |
1081 | 89 | ret = !njs_is_true(value1); |
1082 | | |
1083 | 89 | if (ret) { |
1084 | 89 | test_jump = (njs_vmcode_test_jump_t *) pc; |
1085 | 89 | ret = test_jump->offset; |
1086 | | |
1087 | 89 | } else { |
1088 | 0 | ret = sizeof(njs_vmcode_3addr_t); |
1089 | 0 | } |
1090 | | |
1091 | 89 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1092 | 89 | *retval = *value1; |
1093 | | |
1094 | 89 | BREAK; |
1095 | | |
1096 | 89 | CASE (NJS_VMCODE_COALESCE): |
1097 | 0 | njs_vmcode_debug_opcode(); |
1098 | |
|
1099 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1100 | | |
1101 | 0 | ret = !njs_is_null_or_undefined(value1); |
1102 | |
|
1103 | 0 | if (ret) { |
1104 | 0 | test_jump = (njs_vmcode_test_jump_t *) pc; |
1105 | 0 | ret = test_jump->offset; |
1106 | |
|
1107 | 0 | } else { |
1108 | 0 | ret = sizeof(njs_vmcode_3addr_t); |
1109 | 0 | } |
1110 | |
|
1111 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1112 | 0 | *retval = *value1; |
1113 | |
|
1114 | 0 | BREAK; |
1115 | |
|
1116 | 170 | CASE (NJS_VMCODE_OPTIONAL_CHAIN): |
1117 | 170 | njs_vmcode_debug_opcode(); |
1118 | | |
1119 | 170 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1120 | | |
1121 | 170 | if (njs_is_null_or_undefined(value1)) { |
1122 | 168 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1123 | 168 | njs_set_undefined(retval); |
1124 | 168 | test_jump = (njs_vmcode_test_jump_t *) pc; |
1125 | 168 | ret = test_jump->offset; |
1126 | | |
1127 | 168 | } else { |
1128 | 2 | ret = sizeof(njs_vmcode_3addr_t); |
1129 | 2 | } |
1130 | | |
1131 | 170 | BREAK; |
1132 | | |
1133 | 170 | #define NJS_PRE_UNARY \ |
1134 | 62.6k | if (njs_slow_path(!njs_is_numeric(value1))) { \ |
1135 | 42.3k | ret = njs_value_to_numeric(vm, value1, &numeric1); \ |
1136 | 42.3k | if (njs_slow_path(ret != NJS_OK)) { \ |
1137 | 0 | goto error; \ |
1138 | 0 | } \ |
1139 | 42.3k | \ |
1140 | 42.3k | value1 = &numeric1; \ |
1141 | 42.3k | } \ |
1142 | 62.6k | \ |
1143 | 62.6k | num = njs_number(value1); \ |
1144 | 62.6k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1145 | | |
1146 | 24.8k | CASE (NJS_VMCODE_UNARY_NEGATION): |
1147 | 24.8k | njs_vmcode_debug_opcode(); |
1148 | | |
1149 | 24.8k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1150 | | |
1151 | 74.5k | NJS_PRE_UNARY; |
1152 | | |
1153 | 74.5k | num = -num; |
1154 | | |
1155 | 74.5k | njs_set_number(retval, num); |
1156 | | |
1157 | 74.5k | pc += sizeof(njs_vmcode_2addr_t); |
1158 | 74.5k | NEXT; |
1159 | | |
1160 | 74.5k | CASE (NJS_VMCODE_UNARY_PLUS): |
1161 | 2.33k | njs_vmcode_debug_opcode(); |
1162 | | |
1163 | 2.33k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1164 | | |
1165 | 7.00k | NJS_PRE_UNARY; |
1166 | | |
1167 | 7.00k | njs_set_number(retval, num); |
1168 | | |
1169 | 7.00k | pc += sizeof(njs_vmcode_2addr_t); |
1170 | 7.00k | NEXT; |
1171 | | |
1172 | 35.4k | CASE (NJS_VMCODE_BITWISE_NOT): |
1173 | 35.4k | njs_vmcode_debug_opcode(); |
1174 | | |
1175 | 35.4k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1176 | | |
1177 | 106k | NJS_PRE_UNARY; |
1178 | | |
1179 | 106k | njs_set_int32(retval, ~njs_number_to_uint32(num)); |
1180 | | |
1181 | 106k | pc += sizeof(njs_vmcode_2addr_t); |
1182 | 106k | NEXT; |
1183 | | |
1184 | 106k | CASE (NJS_VMCODE_LOGICAL_NOT): |
1185 | 2.11k | njs_vmcode_debug_opcode(); |
1186 | | |
1187 | 2.11k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1188 | 2.11k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1189 | | |
1190 | 2.11k | njs_set_boolean(retval, !njs_is_true(value1)); |
1191 | | |
1192 | 2.11k | pc += sizeof(njs_vmcode_2addr_t); |
1193 | 2.11k | NEXT; |
1194 | | |
1195 | 5.22k | CASE (NJS_VMCODE_OBJECT): |
1196 | 5.22k | njs_vmcode_debug_opcode(); |
1197 | | |
1198 | 5.22k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1199 | | |
1200 | 5.22k | ret = njs_vmcode_object(vm, retval); |
1201 | 5.22k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1202 | 0 | goto error; |
1203 | 0 | } |
1204 | | |
1205 | 5.22k | BREAK; |
1206 | | |
1207 | 332k | CASE (NJS_VMCODE_ARRAY): |
1208 | 332k | njs_vmcode_debug_opcode(); |
1209 | | |
1210 | 332k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1211 | | |
1212 | 332k | ret = njs_vmcode_array(vm, pc, retval); |
1213 | 332k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1214 | 0 | goto error; |
1215 | 0 | } |
1216 | | |
1217 | 332k | BREAK; |
1218 | | |
1219 | 332k | CASE (NJS_VMCODE_FUNCTION): |
1220 | 109k | njs_vmcode_debug_opcode(); |
1221 | | |
1222 | 109k | ret = njs_vmcode_function(vm, pc); |
1223 | 109k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1224 | 0 | goto error; |
1225 | 0 | } |
1226 | | |
1227 | 109k | BREAK; |
1228 | | |
1229 | 109k | CASE (NJS_VMCODE_REGEXP): |
1230 | 24.0k | njs_vmcode_debug_opcode(); |
1231 | | |
1232 | 24.0k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1233 | | |
1234 | 24.0k | ret = njs_vmcode_regexp(vm, pc, retval); |
1235 | 24.0k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1236 | 0 | goto error; |
1237 | 0 | } |
1238 | | |
1239 | 24.0k | BREAK; |
1240 | | |
1241 | 24.0k | CASE (NJS_VMCODE_INSTANCE_OF): |
1242 | 0 | njs_vmcode_debug_opcode(); |
1243 | |
|
1244 | 0 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1245 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1246 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1247 | | |
1248 | 0 | ret = njs_vmcode_instance_of(vm, value1, value2, retval); |
1249 | 0 | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1250 | 0 | goto error; |
1251 | 0 | } |
1252 | | |
1253 | 0 | BREAK; |
1254 | |
|
1255 | 0 | CASE (NJS_VMCODE_TYPEOF): |
1256 | 0 | njs_vmcode_debug_opcode(); |
1257 | |
|
1258 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1259 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1260 | | |
1261 | 0 | ret = njs_vmcode_typeof(vm, value1, retval); |
1262 | 0 | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1263 | 0 | goto error; |
1264 | 0 | } |
1265 | | |
1266 | 0 | BREAK; |
1267 | |
|
1268 | 721 | CASE (NJS_VMCODE_VOID): |
1269 | 721 | njs_vmcode_debug_opcode(); |
1270 | | |
1271 | 721 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1272 | | |
1273 | 721 | njs_set_undefined(retval); |
1274 | | |
1275 | 721 | ret = sizeof(njs_vmcode_2addr_t); |
1276 | | |
1277 | 721 | BREAK; |
1278 | | |
1279 | 721 | CASE (NJS_VMCODE_DELETE): |
1280 | 0 | njs_vmcode_debug_opcode(); |
1281 | |
|
1282 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1283 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1284 | | |
1285 | 0 | njs_set_boolean(retval, 1); |
1286 | |
|
1287 | 0 | ret = sizeof(njs_vmcode_2addr_t); |
1288 | |
|
1289 | 0 | BREAK; |
1290 | |
|
1291 | 0 | CASE (NJS_VMCODE_DEBUGGER): |
1292 | 0 | njs_vmcode_debug_opcode(); |
1293 | |
|
1294 | 0 | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1295 | | |
1296 | 0 | ret = njs_vmcode_debugger(vm, retval); |
1297 | |
|
1298 | 0 | BREAK; |
1299 | |
|
1300 | 481k | CASE (NJS_VMCODE_PUT_ARG): |
1301 | 481k | njs_vmcode_debug_opcode(); |
1302 | | |
1303 | 481k | put_arg = (njs_vmcode_1addr_t *) pc; |
1304 | 481k | native = vm->top_frame; |
1305 | | |
1306 | 481k | value1 = &native->arguments[native->put_args++]; |
1307 | 481k | njs_vmcode_operand(vm, put_arg->index, value2); |
1308 | | |
1309 | 481k | njs_value_assign(value1, value2); |
1310 | | |
1311 | 481k | ret = sizeof(njs_vmcode_1addr_t); |
1312 | 481k | BREAK; |
1313 | | |
1314 | 481k | CASE (NJS_VMCODE_STOP): |
1315 | 254 | njs_vmcode_debug_opcode(); |
1316 | | |
1317 | 254 | njs_vmcode_operand(vm, vmcode->operand1, value2); |
1318 | 254 | *rval = *value2; |
1319 | | |
1320 | 254 | njs_vmcode_debug(vm, pc, "EXIT STOP"); |
1321 | | |
1322 | 254 | return NJS_OK; |
1323 | | |
1324 | 137 | CASE (NJS_VMCODE_JUMP): |
1325 | 137 | njs_vmcode_debug_opcode(); |
1326 | | |
1327 | 137 | ret = (njs_jump_off_t) vmcode->operand1; |
1328 | 137 | BREAK; |
1329 | | |
1330 | 5.57k | CASE (NJS_VMCODE_PROPERTY_ATOM_SET): |
1331 | 5.57k | njs_vmcode_debug_opcode(); |
1332 | | |
1333 | 5.57k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1334 | 5.57k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1335 | 5.57k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1336 | | |
1337 | 5.57k | ret = njs_value_property_set(vm, value1, value2->atom_id, retval); |
1338 | 5.57k | if (njs_slow_path(ret == NJS_ERROR)) { |
1339 | 34 | goto error; |
1340 | 34 | } |
1341 | | |
1342 | 5.53k | ret = sizeof(njs_vmcode_prop_set_t); |
1343 | 5.53k | BREAK; |
1344 | | |
1345 | 18.3k | CASE (NJS_VMCODE_PROPERTY_SET): |
1346 | 18.3k | njs_vmcode_debug_opcode(); |
1347 | | |
1348 | 18.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1349 | 18.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1350 | 18.3k | njs_vmcode_operand(vm, vmcode->operand1, retval); |
1351 | | |
1352 | 18.3k | if (njs_slow_path(!njs_is_index_or_key(value2))) { |
1353 | 0 | if (njs_slow_path(njs_is_null_or_undefined(value1))) { |
1354 | 0 | (void) njs_throw_cannot_property(vm, value1, value2, "set"); |
1355 | 0 | goto error; |
1356 | 0 | } |
1357 | | |
1358 | 0 | njs_value_assign(&primitive1, value1); |
1359 | 0 | ret = njs_value_to_key(vm, &primitive2, value2); |
1360 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
1361 | 0 | goto error; |
1362 | 0 | } |
1363 | | |
1364 | 0 | value1 = &primitive1; |
1365 | 0 | value2 = &primitive2; |
1366 | 0 | } |
1367 | | |
1368 | 18.3k | if (value2->atom_id == NJS_ATOM_STRING_unknown) { |
1369 | 0 | num = njs_number(value2); |
1370 | |
|
1371 | 0 | if (njs_fast_path(njs_number_is_atom_index(num, &u32))) { |
1372 | 0 | value2->atom_id = njs_number_atom(u32); |
1373 | |
|
1374 | 0 | } else { |
1375 | 0 | ret = njs_atom_atomize_key(vm, value2); |
1376 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
1377 | 0 | goto error; |
1378 | 0 | } |
1379 | 0 | } |
1380 | 0 | } |
1381 | | |
1382 | 18.3k | ret = njs_value_property_set(vm, value1, value2->atom_id, retval); |
1383 | 18.3k | if (njs_slow_path(ret == NJS_ERROR)) { |
1384 | 0 | goto error; |
1385 | 0 | } |
1386 | | |
1387 | 18.3k | ret = sizeof(njs_vmcode_prop_set_t); |
1388 | 18.3k | BREAK; |
1389 | | |
1390 | 18.3k | CASE (NJS_VMCODE_PROPERTY_ACCESSOR): |
1391 | 712 | njs_vmcode_debug_opcode(); |
1392 | | |
1393 | 712 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1394 | 712 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1395 | | |
1396 | 712 | accessor = (njs_vmcode_prop_accessor_t *) pc; |
1397 | 712 | njs_vmcode_operand(vm, accessor->value, function); |
1398 | | |
1399 | 712 | ret = njs_value_to_key(vm, &name, value2); |
1400 | 712 | if (njs_slow_path(ret != NJS_OK)) { |
1401 | 0 | njs_internal_error(vm, "failed conversion of type \"%s\" " |
1402 | 0 | "to string while property define", |
1403 | 0 | njs_type_string(value2->type)); |
1404 | 0 | goto error; |
1405 | 0 | } |
1406 | | |
1407 | 712 | ret = njs_object_prop_define_val(vm, value1, &name, function, |
1408 | 712 | accessor->type); |
1409 | 712 | if (njs_slow_path(ret != NJS_OK)) { |
1410 | 0 | goto error; |
1411 | 0 | } |
1412 | | |
1413 | 712 | ret = sizeof(njs_vmcode_prop_accessor_t); |
1414 | 712 | BREAK; |
1415 | | |
1416 | 712 | CASE (NJS_VMCODE_IF_TRUE_JUMP): |
1417 | 124 | njs_vmcode_debug_opcode(); |
1418 | | |
1419 | 124 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1420 | 124 | value2 = (njs_value_t *) vmcode->operand1; |
1421 | | |
1422 | 124 | ret = njs_is_true(value1); |
1423 | | |
1424 | 124 | ret = ret ? (njs_jump_off_t) value2 |
1425 | 124 | : (njs_jump_off_t) sizeof(njs_vmcode_cond_jump_t); |
1426 | | |
1427 | 124 | BREAK; |
1428 | | |
1429 | 124 | CASE (NJS_VMCODE_IF_FALSE_JUMP): |
1430 | 10 | njs_vmcode_debug_opcode(); |
1431 | | |
1432 | 10 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1433 | 10 | value2 = (njs_value_t *) vmcode->operand1; |
1434 | | |
1435 | 10 | ret = njs_is_true(value1); |
1436 | | |
1437 | 10 | ret = !ret ? (njs_jump_off_t) value2 |
1438 | 10 | : (njs_jump_off_t) sizeof(njs_vmcode_cond_jump_t); |
1439 | | |
1440 | 10 | BREAK; |
1441 | | |
1442 | 10 | CASE (NJS_VMCODE_IF_EQUAL_JUMP): |
1443 | 0 | njs_vmcode_debug_opcode(); |
1444 | |
|
1445 | 0 | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1446 | 0 | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1447 | | |
1448 | 0 | if (njs_values_strict_equal(vm, value1, value2)) { |
1449 | 0 | equal = (njs_vmcode_equal_jump_t *) pc; |
1450 | 0 | ret = equal->offset; |
1451 | |
|
1452 | 0 | } else { |
1453 | 0 | ret = sizeof(njs_vmcode_3addr_t); |
1454 | 0 | } |
1455 | |
|
1456 | 0 | BREAK; |
1457 | |
|
1458 | 3.05k | CASE (NJS_VMCODE_PROPERTY_INIT): |
1459 | 3.05k | njs_vmcode_debug_opcode(); |
1460 | | |
1461 | 3.05k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1462 | 3.05k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1463 | | |
1464 | 3.05k | set = (njs_vmcode_prop_set_t *) pc; |
1465 | 3.05k | njs_vmcode_operand(vm, set->value, retval); |
1466 | 3.05k | ret = njs_vmcode_property_init(vm, value1, value2, retval); |
1467 | 3.05k | if (njs_slow_path(ret == NJS_ERROR)) { |
1468 | 0 | goto error; |
1469 | 0 | } |
1470 | | |
1471 | 3.05k | BREAK; |
1472 | | |
1473 | 924k | CASE (NJS_VMCODE_ARRAY_INIT): |
1474 | 924k | njs_vmcode_debug_opcode(); |
1475 | | |
1476 | 924k | array_init = (njs_vmcode_array_init_t *) pc; |
1477 | | |
1478 | 924k | njs_vmcode_operand(vm, array_init->array, value1); |
1479 | 924k | njs_vmcode_operand(vm, array_init->value, value2); |
1480 | | |
1481 | 924k | ret = njs_vmcode_array_init(vm, pc, value1, value2); |
1482 | 924k | if (njs_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { |
1483 | 0 | goto error; |
1484 | 0 | } |
1485 | | |
1486 | 924k | BREAK; |
1487 | | |
1488 | 924k | CASE (NJS_VMCODE_RETURN): |
1489 | 38.0k | njs_vmcode_debug_opcode(); |
1490 | | |
1491 | 38.0k | value2 = (njs_value_t *) vmcode->operand1; |
1492 | | |
1493 | 38.0k | njs_vmcode_operand(vm, (njs_index_t) value2, value2); |
1494 | | |
1495 | 38.0k | njs_vmcode_debug(vm, pc, "EXIT RETURN"); |
1496 | | |
1497 | 38.0k | njs_vmcode_return(vm, rval, value2); |
1498 | | |
1499 | 38.0k | return NJS_OK; |
1500 | | |
1501 | 211k | CASE (NJS_VMCODE_FUNCTION_FRAME): |
1502 | 211k | njs_vmcode_debug_opcode(); |
1503 | | |
1504 | 211k | value2 = (njs_value_t *) vmcode->operand1; |
1505 | 211k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1506 | | |
1507 | 211k | function_frame = (njs_vmcode_function_frame_t *) pc; |
1508 | | |
1509 | 211k | ret = njs_function_frame_create(vm, value1, &njs_value_undefined, |
1510 | 211k | (uintptr_t) value2, |
1511 | 211k | function_frame->ctor); |
1512 | | |
1513 | 211k | if (njs_slow_path(ret != NJS_OK)) { |
1514 | 48 | goto error; |
1515 | 48 | } |
1516 | | |
1517 | 211k | ret = sizeof(njs_vmcode_function_frame_t); |
1518 | 211k | BREAK; |
1519 | | |
1520 | 211k | CASE (NJS_VMCODE_METHOD_FRAME): |
1521 | 167k | njs_vmcode_debug_opcode(); |
1522 | | |
1523 | 167k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1524 | 167k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1525 | | |
1526 | 167k | method_frame = (njs_vmcode_method_frame_t *) pc; |
1527 | | |
1528 | 167k | ret = njs_function_frame_create(vm, value1, value2, |
1529 | 167k | method_frame->nargs, |
1530 | 167k | method_frame->ctor); |
1531 | | |
1532 | 167k | if (njs_slow_path(ret != NJS_OK)) { |
1533 | 7 | goto error; |
1534 | 7 | } |
1535 | | |
1536 | 167k | ret = sizeof(njs_vmcode_method_frame_t); |
1537 | 167k | BREAK; |
1538 | | |
1539 | 378k | CASE (NJS_VMCODE_FUNCTION_CALL): |
1540 | 378k | njs_vmcode_debug_opcode(); |
1541 | | |
1542 | 378k | value2 = (njs_value_t *) vmcode->operand1; |
1543 | | |
1544 | 378k | vm->active_frame->native.pc = pc; |
1545 | | |
1546 | 378k | njs_vmcode_operand(vm, (njs_index_t) value2, value2); |
1547 | | |
1548 | 378k | ret = njs_function_frame_invoke(vm, value2); |
1549 | 378k | if (njs_slow_path(ret == NJS_ERROR)) { |
1550 | 57.7k | goto error; |
1551 | 57.7k | } |
1552 | | |
1553 | 320k | njs_vmcode_debug(vm, pc, "RESUME"); |
1554 | | |
1555 | 320k | ret = sizeof(njs_vmcode_function_call_t); |
1556 | 320k | BREAK; |
1557 | | |
1558 | 320k | CASE (NJS_VMCODE_PROPERTY_NEXT): |
1559 | 289k | njs_vmcode_debug_opcode(); |
1560 | | |
1561 | 289k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1562 | 289k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1563 | | |
1564 | 289k | pnext = (njs_vmcode_prop_next_t *) pc; |
1565 | 289k | retval = njs_scope_value(vm, pnext->retval); |
1566 | | |
1567 | 289k | njs_assert(njs_is_data(value2, NJS_DATA_TAG_FOREACH_NEXT)); |
1568 | 289k | next = njs_data(value2); |
1569 | | |
1570 | 289k | if (next->index < next->array->length) { |
1571 | 287k | *retval = next->array->start[next->index++]; |
1572 | | |
1573 | 287k | ret = pnext->offset; |
1574 | 287k | BREAK; |
1575 | 287k | } |
1576 | | |
1577 | 289k | njs_mp_free(vm->mem_pool, next); |
1578 | | |
1579 | 289k | ret = sizeof(njs_vmcode_prop_next_t); |
1580 | 289k | BREAK; |
1581 | | |
1582 | 289k | CASE (NJS_VMCODE_ARGUMENTS): |
1583 | 3 | njs_vmcode_debug_opcode(); |
1584 | | |
1585 | 3 | ret = njs_vmcode_arguments(vm, pc); |
1586 | 3 | if (njs_slow_path(ret == NJS_ERROR)) { |
1587 | 0 | goto error; |
1588 | 0 | } |
1589 | | |
1590 | 3 | BREAK; |
1591 | | |
1592 | 1.83k | CASE (NJS_VMCODE_TO_PROPERTY_KEY): |
1593 | 1.83k | njs_vmcode_debug_opcode(); |
1594 | | |
1595 | 1.83k | value2 = (njs_value_t *) vmcode->operand1; |
1596 | 1.83k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1597 | | |
1598 | 1.83k | njs_vmcode_operand(vm, (njs_index_t) value2, retval); |
1599 | | |
1600 | 1.83k | ret = njs_value_to_key(vm, retval, value1); |
1601 | 1.83k | if (njs_fast_path(ret == NJS_ERROR)) { |
1602 | 0 | goto error; |
1603 | 0 | } |
1604 | | |
1605 | 1.83k | ret = sizeof(njs_vmcode_2addr_t); |
1606 | 1.83k | BREAK; |
1607 | | |
1608 | 18.3k | CASE (NJS_VMCODE_TO_PROPERTY_KEY_CHK): |
1609 | 18.3k | njs_vmcode_debug_opcode(); |
1610 | | |
1611 | 18.3k | value2 = (njs_value_t *) vmcode->operand1; |
1612 | 18.3k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1613 | | |
1614 | 18.3k | njs_vmcode_operand(vm, (njs_index_t) value2, retval); |
1615 | 18.3k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1616 | | |
1617 | 18.3k | if (njs_slow_path(njs_is_null_or_undefined(value2))) { |
1618 | 0 | (void) njs_throw_cannot_property(vm, value2, value1, "get"); |
1619 | 0 | goto error; |
1620 | 0 | } |
1621 | | |
1622 | 18.3k | ret = njs_value_to_key(vm, retval, value1); |
1623 | 18.3k | if (njs_fast_path(ret == NJS_ERROR)) { |
1624 | 0 | goto error; |
1625 | 0 | } |
1626 | | |
1627 | 18.3k | ret = sizeof(njs_vmcode_3addr_t); |
1628 | 18.3k | BREAK; |
1629 | | |
1630 | 18.3k | CASE (NJS_VMCODE_SET_FUNCTION_NAME): |
1631 | 1.83k | njs_vmcode_debug_opcode(); |
1632 | | |
1633 | 1.83k | value2 = (njs_value_t *) vmcode->operand1; |
1634 | 1.83k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1635 | | |
1636 | 1.83k | njs_vmcode_operand(vm, (njs_index_t) value2, value2); |
1637 | | |
1638 | 1.83k | njs_assert(njs_is_function(value2)); |
1639 | | |
1640 | 1.83k | ret = njs_function_name_set(vm, njs_function(value2), value1, NULL); |
1641 | 1.83k | if (njs_slow_path(ret == NJS_ERROR)) { |
1642 | 0 | goto error; |
1643 | 0 | } |
1644 | | |
1645 | 1.83k | ret = sizeof(njs_vmcode_2addr_t); |
1646 | 1.83k | BREAK; |
1647 | | |
1648 | | |
1649 | 1.83k | CASE (NJS_VMCODE_PROTO_INIT): |
1650 | 1.12k | njs_vmcode_debug_opcode(); |
1651 | | |
1652 | 1.12k | njs_vmcode_operand(vm, vmcode->operand3, value2); |
1653 | 1.12k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1654 | | |
1655 | 1.12k | set = (njs_vmcode_prop_set_t *) pc; |
1656 | 1.12k | njs_vmcode_operand(vm, set->value, retval); |
1657 | 1.12k | ret = njs_vmcode_proto_init(vm, value1, value2, retval); |
1658 | 1.12k | if (njs_slow_path(ret == NJS_ERROR)) { |
1659 | 0 | goto error; |
1660 | 0 | } |
1661 | | |
1662 | 1.12k | BREAK; |
1663 | | |
1664 | 1.12k | CASE (NJS_VMCODE_IMPORT): |
1665 | 0 | njs_vmcode_debug_opcode(); |
1666 | |
|
1667 | 0 | import = (njs_vmcode_import_t *) pc; |
1668 | 0 | retval = njs_scope_value(vm, import->retval); |
1669 | 0 | ret = njs_vmcode_import(vm, import->module, retval); |
1670 | 0 | if (njs_slow_path(ret == NJS_ERROR)) { |
1671 | 0 | goto error; |
1672 | 0 | } |
1673 | | |
1674 | 0 | BREAK; |
1675 | |
|
1676 | 5.71k | CASE (NJS_VMCODE_AWAIT): |
1677 | 5.71k | njs_vmcode_debug_opcode(); |
1678 | | |
1679 | 5.71k | await = (njs_vmcode_await_t *) pc; |
1680 | | |
1681 | 5.71k | ret = njs_vmcode_await(vm, await, rval, promise_cap, async_ctx); |
1682 | | |
1683 | 5.71k | njs_vmcode_debug(vm, pc, "EXIT AWAIT"); |
1684 | | |
1685 | 5.71k | if (njs_slow_path(ret == NJS_ERROR)) { |
1686 | 0 | goto error; |
1687 | 0 | } |
1688 | | |
1689 | 5.71k | return ret; |
1690 | | |
1691 | 76.1k | CASE (NJS_VMCODE_TRY_START): |
1692 | 76.1k | njs_vmcode_debug_opcode(); |
1693 | | |
1694 | 76.1k | value2 = (njs_value_t *) vmcode->operand1; |
1695 | 76.1k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1696 | | |
1697 | 76.1k | ret = njs_vmcode_try_start(vm, value1, value2, pc); |
1698 | 76.1k | if (njs_slow_path(ret == NJS_ERROR)) { |
1699 | 0 | goto error; |
1700 | 0 | } |
1701 | | |
1702 | 76.1k | BREAK; |
1703 | | |
1704 | 76.1k | CASE (NJS_VMCODE_THROW): |
1705 | 3 | njs_vmcode_debug_opcode(); |
1706 | | |
1707 | 3 | value2 = (njs_value_t *) vmcode->operand1; |
1708 | | |
1709 | 3 | njs_vmcode_operand(vm, (njs_index_t) value2, value2); |
1710 | 3 | njs_vm_throw(vm, value2); |
1711 | | |
1712 | 3 | goto error; |
1713 | | |
1714 | 0 | CASE (NJS_VMCODE_TRY_BREAK): |
1715 | 0 | njs_vmcode_debug_opcode(); |
1716 | |
|
1717 | 0 | value2 = (njs_value_t *) vmcode->operand1; |
1718 | |
|
1719 | 0 | try_trampoline = (njs_vmcode_try_trampoline_t *) pc; |
1720 | 0 | value1 = njs_scope_value(vm, try_trampoline->exit_value); |
1721 | |
|
1722 | 0 | ret = njs_vmcode_try_break(vm, value1, value2); |
1723 | 0 | BREAK; |
1724 | |
|
1725 | 6 | CASE (NJS_VMCODE_TRY_CONTINUE): |
1726 | 6 | njs_vmcode_debug_opcode(); |
1727 | | |
1728 | 6 | value2 = (njs_value_t *) vmcode->operand1; |
1729 | | |
1730 | 6 | try_trampoline = (njs_vmcode_try_trampoline_t *) pc; |
1731 | 6 | value1 = njs_scope_value(vm, try_trampoline->exit_value); |
1732 | | |
1733 | 6 | ret = njs_vmcode_try_continue(vm, value1, value2); |
1734 | 6 | BREAK; |
1735 | | |
1736 | 2.05k | CASE (NJS_VMCODE_TRY_END): |
1737 | 2.05k | njs_vmcode_debug_opcode(); |
1738 | | |
1739 | 2.05k | ret = njs_vmcode_try_end(vm, NULL, (njs_value_t *) vmcode->operand1); |
1740 | 2.05k | BREAK; |
1741 | | |
1742 | | /* |
1743 | | * njs_vmcode_catch() is set on the start of a "catch" block to |
1744 | | * store exception and to remove a "try" block if there is no |
1745 | | * "finally" block or to update a catch address to the start of |
1746 | | * a "finally" block. |
1747 | | * njs_vmcode_catch() is set on the start of a "finally" block |
1748 | | * to store uncaught exception and to remove a "try" block. |
1749 | | */ |
1750 | 74.6k | CASE (NJS_VMCODE_CATCH): |
1751 | 74.6k | njs_vmcode_debug_opcode(); |
1752 | | |
1753 | 74.6k | value2 = (njs_value_t *) vmcode->operand1; |
1754 | 74.6k | njs_vmcode_operand(vm, vmcode->operand2, value1); |
1755 | | |
1756 | 74.6k | *value1 = njs_vm_exception(vm); |
1757 | | |
1758 | 74.6k | if ((njs_jump_off_t) value2 == sizeof(njs_vmcode_catch_t)) { |
1759 | 74.1k | ret = njs_vmcode_try_end(vm, value1, value2); |
1760 | | |
1761 | 74.1k | } else { |
1762 | 516 | frame = (njs_frame_t *) vm->top_frame; |
1763 | 516 | frame->exception.catch = pc + (njs_jump_off_t) value2; |
1764 | 516 | ret = sizeof(njs_vmcode_catch_t); |
1765 | 516 | } |
1766 | | |
1767 | 74.6k | BREAK; |
1768 | | |
1769 | 74.6k | CASE (NJS_VMCODE_FINALLY): |
1770 | 1.09k | njs_vmcode_debug_opcode(); |
1771 | | |
1772 | 1.09k | value2 = (njs_value_t *) vmcode->operand1; |
1773 | | |
1774 | 1.09k | ret = njs_vmcode_finally(vm, rval, value2, pc); |
1775 | | |
1776 | 1.09k | switch (ret) { |
1777 | 0 | case NJS_OK: |
1778 | 0 | njs_vmcode_debug(vm, pc, "EXIT FINALLY"); |
1779 | |
|
1780 | 0 | return NJS_OK; |
1781 | 516 | case NJS_ERROR: |
1782 | 516 | goto error; |
1783 | 1.09k | } |
1784 | | |
1785 | 578 | BREAK; |
1786 | | |
1787 | 30.5k | CASE (NJS_VMCODE_LET): |
1788 | 30.5k | njs_vmcode_debug_opcode(); |
1789 | | |
1790 | 30.5k | var = (njs_vmcode_variable_t *) pc; |
1791 | 30.5k | value1 = njs_scope_value(vm, var->dst); |
1792 | | |
1793 | 30.5k | if (njs_is_valid(value1)) { |
1794 | 27.7k | value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t)); |
1795 | 27.7k | if (njs_slow_path(value1 == NULL)) { |
1796 | 0 | njs_memory_error(vm); |
1797 | 0 | goto error; |
1798 | 0 | } |
1799 | | |
1800 | 27.7k | njs_scope_value_set(vm, var->dst, value1); |
1801 | 27.7k | } |
1802 | | |
1803 | 30.5k | njs_set_undefined(value1); |
1804 | | |
1805 | 30.5k | ret = sizeof(njs_vmcode_variable_t); |
1806 | 30.5k | BREAK; |
1807 | | |
1808 | 52.2k | CASE (NJS_VMCODE_LET_UPDATE): |
1809 | 52.2k | njs_vmcode_debug_opcode(); |
1810 | | |
1811 | 52.2k | var = (njs_vmcode_variable_t *) pc; |
1812 | 52.2k | value2 = njs_scope_value(vm, var->dst); |
1813 | | |
1814 | 52.2k | value1 = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t)); |
1815 | 52.2k | if (njs_slow_path(value1 == NULL)) { |
1816 | 0 | njs_memory_error(vm); |
1817 | 0 | goto error; |
1818 | 0 | } |
1819 | | |
1820 | 52.2k | *value1 = *value2; |
1821 | | |
1822 | 52.2k | njs_scope_value_set(vm, var->dst, value1); |
1823 | | |
1824 | 52.2k | ret = sizeof(njs_vmcode_variable_t); |
1825 | 52.2k | BREAK; |
1826 | | |
1827 | 52.2k | CASE (NJS_VMCODE_INITIALIZATION_TEST): |
1828 | 0 | njs_vmcode_debug_opcode(); |
1829 | |
|
1830 | 0 | var = (njs_vmcode_variable_t *) pc; |
1831 | 0 | value1 = njs_scope_value(vm, var->dst); |
1832 | |
|
1833 | 0 | if (njs_is_valid(value1)) { |
1834 | 0 | ret = sizeof(njs_vmcode_variable_t); |
1835 | 0 | BREAK; |
1836 | 0 | } |
1837 | |
|
1838 | 0 | FALLTHROUGH; |
1839 | 0 | CASE (NJS_VMCODE_NOT_INITIALIZED): |
1840 | 0 | njs_vmcode_debug_opcode(); |
1841 | |
|
1842 | 0 | njs_reference_error(vm, "cannot access variable before initialization"); |
1843 | 0 | goto error; |
1844 | | |
1845 | 22.0k | CASE (NJS_VMCODE_ERROR): |
1846 | 22.0k | njs_vmcode_debug_opcode(); |
1847 | | |
1848 | 22.0k | njs_vmcode_error(vm, pc); |
1849 | 22.0k | goto error; |
1850 | | |
1851 | 27.7k | CASE (NJS_VMCODE_ASSIGNMENT_ERROR): |
1852 | 27.7k | njs_vmcode_debug_opcode(); |
1853 | | |
1854 | 27.7k | njs_type_error(vm, "assignment to constant variable"); |
1855 | 27.7k | goto error; |
1856 | |
|
1857 | 0 | } |
1858 | | |
1859 | 108k | error: |
1860 | | |
1861 | 108k | if (njs_is_error(&vm->exception)) { |
1862 | 108k | vm->active_frame->native.pc = pc; |
1863 | | |
1864 | 108k | njs_error_stack_attach(vm, vm->exception, 0); |
1865 | 108k | } |
1866 | | |
1867 | 161k | for ( ;; ) { |
1868 | 161k | native = vm->top_frame; |
1869 | | |
1870 | 161k | if (!native->native) { |
1871 | 108k | frame = (njs_frame_t *) native; |
1872 | 108k | catch = frame->exception.catch; |
1873 | | |
1874 | 108k | if (catch != NULL) { |
1875 | 74.6k | pc = catch; |
1876 | | |
1877 | 74.6k | NEXT; |
1878 | 74.6k | } |
1879 | 108k | } |
1880 | | |
1881 | 161k | previous = native->previous; |
1882 | 161k | if (previous == NULL) { |
1883 | 192 | break; |
1884 | 192 | } |
1885 | | |
1886 | 160k | lambda_call = (native == &vm->active_frame->native); |
1887 | | |
1888 | 160k | njs_vm_scopes_restore(vm, native); |
1889 | | |
1890 | 160k | if (native->size != 0) { |
1891 | 27 | vm->spare_stack_size += native->size; |
1892 | 27 | njs_mp_free(vm->mem_pool, native); |
1893 | 27 | } |
1894 | | |
1895 | 160k | if (lambda_call) { |
1896 | 33.3k | break; |
1897 | 33.3k | } |
1898 | 160k | } |
1899 | | |
1900 | 108k | njs_vmcode_debug(vm, pc, "EXIT ERROR"); |
1901 | | |
1902 | 108k | return NJS_ERROR; |
1903 | 0 | } |
1904 | | |
1905 | | |
1906 | | static njs_jump_off_t |
1907 | | njs_vmcode_object(njs_vm_t *vm, njs_value_t *retval) |
1908 | 5.22k | { |
1909 | 5.22k | njs_object_t *object; |
1910 | | |
1911 | 5.22k | object = njs_object_alloc(vm); |
1912 | | |
1913 | 5.22k | if (njs_fast_path(object != NULL)) { |
1914 | 5.22k | njs_set_object(retval, object); |
1915 | | |
1916 | 5.22k | return sizeof(njs_vmcode_object_t); |
1917 | 5.22k | } |
1918 | | |
1919 | 0 | return NJS_ERROR; |
1920 | 5.22k | } |
1921 | | |
1922 | | |
1923 | | static njs_jump_off_t |
1924 | | njs_vmcode_array(njs_vm_t *vm, u_char *pc, njs_value_t *retval) |
1925 | 332k | { |
1926 | 332k | uint32_t length; |
1927 | 332k | njs_array_t *array; |
1928 | 332k | njs_value_t *value; |
1929 | 332k | njs_vmcode_array_t *code; |
1930 | | |
1931 | 332k | code = (njs_vmcode_array_t *) pc; |
1932 | | |
1933 | 332k | array = njs_array_alloc(vm, code->flat, code->length, NJS_ARRAY_SPARE); |
1934 | | |
1935 | 332k | if (njs_fast_path(array != NULL)) { |
1936 | | |
1937 | 332k | if (code->ctor) { |
1938 | | /* Array of the form [,,,], [1,,]. */ |
1939 | 9.40k | if (array->object.fast_array) { |
1940 | 9.39k | value = array->start; |
1941 | 9.39k | length = array->length; |
1942 | | |
1943 | 39.8k | do { |
1944 | 39.8k | njs_set_invalid(value); |
1945 | 39.8k | value++; |
1946 | 39.8k | length--; |
1947 | 39.8k | } while (length != 0); |
1948 | 9.39k | } |
1949 | | |
1950 | 322k | } else { |
1951 | | /* Array of the form [], [,,1], [1,2,3]. */ |
1952 | 322k | array->length = 0; |
1953 | 322k | } |
1954 | | |
1955 | 332k | njs_set_array(retval, array); |
1956 | | |
1957 | 332k | return sizeof(njs_vmcode_array_t); |
1958 | 332k | } |
1959 | | |
1960 | 0 | return NJS_ERROR; |
1961 | 332k | } |
1962 | | |
1963 | | |
1964 | | static njs_jump_off_t |
1965 | | njs_vmcode_function(njs_vm_t *vm, u_char *pc) |
1966 | 109k | { |
1967 | 109k | njs_function_t *function; |
1968 | 109k | njs_vmcode_function_t *code; |
1969 | 109k | njs_function_lambda_t *lambda; |
1970 | | |
1971 | 109k | code = (njs_vmcode_function_t *) pc; |
1972 | 109k | lambda = code->lambda; |
1973 | | |
1974 | 109k | function = njs_function_alloc(vm, lambda, code->async); |
1975 | 109k | if (njs_slow_path(function == NULL)) { |
1976 | 0 | return NJS_ERROR; |
1977 | 0 | } |
1978 | | |
1979 | 109k | if (njs_function_capture_closure(vm, function, lambda) != NJS_OK) { |
1980 | 0 | return NJS_ERROR; |
1981 | 0 | } |
1982 | | |
1983 | 109k | function->args_count = lambda->nargs - lambda->rest_parameters; |
1984 | | |
1985 | 109k | njs_set_function(njs_scope_value(vm, code->retval), function); |
1986 | | |
1987 | 109k | return sizeof(njs_vmcode_function_t); |
1988 | 109k | } |
1989 | | |
1990 | | |
1991 | | static njs_jump_off_t |
1992 | | njs_vmcode_arguments(njs_vm_t *vm, u_char *pc) |
1993 | 3 | { |
1994 | 3 | njs_frame_t *frame; |
1995 | 3 | njs_value_t *value; |
1996 | 3 | njs_jump_off_t ret; |
1997 | 3 | njs_vmcode_arguments_t *code; |
1998 | | |
1999 | 3 | frame = (njs_frame_t *) vm->active_frame; |
2000 | | |
2001 | 3 | if (frame->native.arguments_object == NULL) { |
2002 | 3 | ret = njs_function_arguments_object_init(vm, &frame->native); |
2003 | 3 | if (njs_slow_path(ret != NJS_OK)) { |
2004 | 0 | return NJS_ERROR; |
2005 | 0 | } |
2006 | 3 | } |
2007 | | |
2008 | 3 | code = (njs_vmcode_arguments_t *) pc; |
2009 | | |
2010 | 3 | value = njs_scope_valid_value(vm, code->dst); |
2011 | 3 | if (njs_slow_path(value == NULL)) { |
2012 | 0 | return NJS_ERROR; |
2013 | 0 | } |
2014 | | |
2015 | 3 | njs_set_object(value, frame->native.arguments_object); |
2016 | | |
2017 | 3 | return sizeof(njs_vmcode_arguments_t); |
2018 | 3 | } |
2019 | | |
2020 | | |
2021 | | static njs_jump_off_t |
2022 | | njs_vmcode_regexp(njs_vm_t *vm, u_char *pc, njs_value_t *retval) |
2023 | 24.0k | { |
2024 | 24.0k | njs_regexp_t *regexp; |
2025 | 24.0k | njs_vmcode_regexp_t *code; |
2026 | | |
2027 | 24.0k | code = (njs_vmcode_regexp_t *) pc; |
2028 | | |
2029 | 24.0k | regexp = njs_regexp_alloc(vm, code->pattern); |
2030 | | |
2031 | 24.0k | if (njs_fast_path(regexp != NULL)) { |
2032 | 24.0k | njs_set_regexp(retval, regexp); |
2033 | | |
2034 | 24.0k | return sizeof(njs_vmcode_regexp_t); |
2035 | 24.0k | } |
2036 | | |
2037 | 0 | return NJS_ERROR; |
2038 | 24.0k | } |
2039 | | |
2040 | | |
2041 | | static njs_jump_off_t |
2042 | | njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *retval) |
2043 | 117k | { |
2044 | 117k | njs_array_t *array; |
2045 | 117k | njs_jump_off_t ret; |
2046 | 117k | njs_value_t arguments[1]; |
2047 | | |
2048 | 117k | static const njs_function_t concat = { |
2049 | 117k | .native = 1, |
2050 | 117k | .u.native = njs_string_prototype_concat |
2051 | 117k | }; |
2052 | | |
2053 | 117k | njs_assert(njs_is_array(retval)); |
2054 | | |
2055 | 117k | array = njs_array(retval); |
2056 | | |
2057 | 117k | njs_set_empty_string(vm, &arguments[0]); |
2058 | | |
2059 | 117k | ret = njs_function_call(vm, (njs_function_t *) &concat, &arguments[0], |
2060 | 117k | array->start, array->length, retval); |
2061 | 117k | if (njs_slow_path(ret != NJS_OK)) { |
2062 | 0 | return ret; |
2063 | 0 | } |
2064 | | |
2065 | 117k | njs_array_destroy(vm, array); |
2066 | | |
2067 | 117k | return sizeof(njs_vmcode_template_literal_t); |
2068 | 117k | } |
2069 | | |
2070 | | |
2071 | | static njs_jump_off_t |
2072 | | njs_vmcode_array_init(njs_vm_t *vm, u_char *pc, njs_value_t *value, |
2073 | | njs_value_t *init) |
2074 | 924k | { |
2075 | 924k | uint32_t index, size; |
2076 | 924k | njs_array_t *array; |
2077 | 924k | njs_value_t *entry; |
2078 | 924k | njs_object_prop_t *prop; |
2079 | 924k | njs_vmcode_array_init_t *code; |
2080 | | |
2081 | 924k | code = (njs_vmcode_array_init_t *) pc; |
2082 | 924k | index = code->index; |
2083 | | |
2084 | 924k | if (njs_slow_path(!njs_is_array(value))) { |
2085 | 0 | njs_internal_error(vm, "array initialization target is not an array"); |
2086 | 0 | return NJS_ERROR; |
2087 | 0 | } |
2088 | | |
2089 | 924k | array = njs_array(value); |
2090 | | |
2091 | 924k | if (njs_fast_path(array->object.fast_array)) { |
2092 | 506k | njs_assert(index < array->size); |
2093 | | |
2094 | 506k | if (index >= array->length) { |
2095 | 483k | entry = &array->start[array->length]; |
2096 | 483k | size = index - array->length; |
2097 | | |
2098 | 539k | while (size != 0) { |
2099 | 55.6k | njs_set_invalid(entry); |
2100 | 55.6k | entry++; |
2101 | 55.6k | size--; |
2102 | 55.6k | } |
2103 | | |
2104 | 483k | array->length = index + 1; |
2105 | 483k | } |
2106 | | |
2107 | 506k | njs_value_assign(&array->start[index], init); |
2108 | | |
2109 | 506k | } else { |
2110 | 418k | prop = njs_object_property_add(vm, value, njs_number_atom(index), 0); |
2111 | 418k | if (njs_slow_path(prop == NULL)) { |
2112 | 0 | return NJS_ERROR; |
2113 | 0 | } |
2114 | | |
2115 | 418k | njs_value_assign(njs_prop_value(prop), init); |
2116 | 418k | } |
2117 | | |
2118 | 924k | return sizeof(njs_vmcode_array_init_t); |
2119 | 924k | } |
2120 | | |
2121 | | |
2122 | | static njs_jump_off_t |
2123 | | njs_vmcode_property_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, |
2124 | | njs_value_t *init) |
2125 | 3.05k | { |
2126 | 3.05k | njs_int_t ret; |
2127 | 3.05k | njs_value_t name; |
2128 | 3.05k | njs_object_prop_t *prop; |
2129 | 3.05k | njs_flathsh_query_t fhq; |
2130 | | |
2131 | 3.05k | switch (value->type) { |
2132 | 3.05k | case NJS_OBJECT: |
2133 | 3.05k | if (key->type == NJS_STRING) { |
2134 | 1.02k | if (key->atom_id == NJS_ATOM_STRING_unknown) { |
2135 | 0 | ret = njs_atom_atomize_key(vm, key); |
2136 | 0 | if (ret != NJS_OK) { |
2137 | 0 | return ret; |
2138 | 0 | } |
2139 | 0 | } |
2140 | 1.02k | } |
2141 | | |
2142 | 3.05k | ret = njs_value_to_key(vm, &name, key); |
2143 | 3.05k | if (njs_slow_path(ret != NJS_OK)) { |
2144 | 0 | return NJS_ERROR; |
2145 | 0 | } |
2146 | | |
2147 | 3.05k | if (name.atom_id == NJS_ATOM_STRING_unknown) { |
2148 | 2.03k | ret = njs_atom_atomize_key(vm, &name); |
2149 | 2.03k | if (ret != NJS_OK) { |
2150 | 0 | return ret; |
2151 | 0 | } |
2152 | 2.03k | } |
2153 | | |
2154 | 3.05k | fhq.key_hash = name.atom_id; |
2155 | 3.05k | fhq.replace = 1; |
2156 | 3.05k | fhq.pool = vm->mem_pool; |
2157 | 3.05k | fhq.proto = &njs_object_hash_proto; |
2158 | | |
2159 | 3.05k | ret = njs_flathsh_unique_insert(njs_object_hash(value), &fhq); |
2160 | 3.05k | if (njs_slow_path(ret != NJS_OK)) { |
2161 | 0 | njs_internal_error(vm, "flathsh insert/replace failed"); |
2162 | 0 | return NJS_ERROR; |
2163 | 0 | } |
2164 | | |
2165 | 3.05k | prop = fhq.value; |
2166 | | |
2167 | 3.05k | prop->type = NJS_PROPERTY; |
2168 | 3.05k | prop->enumerable = 1; |
2169 | 3.05k | prop->configurable = 1; |
2170 | 3.05k | prop->writable = 1; |
2171 | 3.05k | prop->u.value = *init; |
2172 | | |
2173 | 3.05k | break; |
2174 | | |
2175 | 0 | default: |
2176 | 0 | njs_internal_error(vm, "unexpected object type \"%s\" " |
2177 | 0 | "while property initialization", |
2178 | 0 | njs_type_string(value->type)); |
2179 | |
|
2180 | 0 | return NJS_ERROR; |
2181 | 3.05k | } |
2182 | | |
2183 | 3.05k | return sizeof(njs_vmcode_prop_set_t); |
2184 | 3.05k | } |
2185 | | |
2186 | | |
2187 | | static njs_jump_off_t |
2188 | | njs_vmcode_proto_init(njs_vm_t *vm, njs_value_t *value, njs_value_t *unused, |
2189 | | njs_value_t *init) |
2190 | 1.12k | { |
2191 | 1.12k | njs_object_t *obj; |
2192 | 1.12k | njs_value_t retval; |
2193 | 1.12k | njs_jump_off_t ret; |
2194 | 1.12k | njs_object_prop_t *prop; |
2195 | 1.12k | njs_flathsh_query_t fhq; |
2196 | | |
2197 | 1.12k | fhq.key_hash = NJS_ATOM_STRING___proto__; |
2198 | 1.12k | fhq.proto = &njs_object_hash_proto; |
2199 | 1.12k | fhq.pool = vm->mem_pool; |
2200 | | |
2201 | 1.12k | obj = njs_object(value); |
2202 | | |
2203 | 1.12k | ret = njs_flathsh_unique_find(&obj->__proto__->shared_hash, &fhq); |
2204 | 1.12k | if (njs_slow_path(ret != NJS_OK)) { |
2205 | 0 | goto fail; |
2206 | 0 | } |
2207 | | |
2208 | 1.12k | prop = fhq.value; |
2209 | | |
2210 | 1.12k | if (prop->type != NJS_PROPERTY_HANDLER) { |
2211 | 0 | goto fail; |
2212 | 0 | } |
2213 | | |
2214 | 1.12k | ret = njs_prop_handler(prop)(vm, prop, fhq.key_hash, value, init, &retval); |
2215 | 1.12k | if (njs_slow_path(ret != NJS_OK)) { |
2216 | 0 | goto fail; |
2217 | 0 | } |
2218 | | |
2219 | 1.12k | return sizeof(njs_vmcode_prop_set_t); |
2220 | | |
2221 | 0 | fail: |
2222 | |
|
2223 | 0 | njs_internal_error(vm, "\"__proto__\" init failed"); |
2224 | 0 | return NJS_ERROR; |
2225 | 1.12k | } |
2226 | | |
2227 | | |
2228 | | static njs_jump_off_t |
2229 | | njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *value, njs_value_t *key, |
2230 | | njs_value_t *retval) |
2231 | 1 | { |
2232 | 1 | njs_int_t ret; |
2233 | 1 | njs_value_t primitive; |
2234 | 1 | njs_property_query_t pq; |
2235 | | |
2236 | 1 | if (njs_slow_path(njs_is_primitive(value))) { |
2237 | 1 | njs_type_error(vm, "property \"in\" on primitive %s type", |
2238 | 1 | njs_type_string(value->type)); |
2239 | 1 | return NJS_ERROR; |
2240 | 1 | } |
2241 | | |
2242 | 0 | if (njs_slow_path(!njs_is_index_or_key(key))) { |
2243 | 0 | ret = njs_value_to_key(vm, &primitive, key); |
2244 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
2245 | 0 | return NJS_ERROR; |
2246 | 0 | } |
2247 | | |
2248 | 0 | key = &primitive; |
2249 | 0 | } |
2250 | | |
2251 | 0 | njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0); |
2252 | |
|
2253 | 0 | ret = njs_property_query_val(vm, &pq, value, key); |
2254 | 0 | if (njs_slow_path(ret == NJS_ERROR)) { |
2255 | 0 | return ret; |
2256 | 0 | } |
2257 | | |
2258 | 0 | njs_set_boolean(retval, ret == NJS_OK); |
2259 | |
|
2260 | 0 | return sizeof(njs_vmcode_3addr_t); |
2261 | 0 | } |
2262 | | |
2263 | | |
2264 | | static njs_jump_off_t |
2265 | | njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object, |
2266 | | u_char *pc, njs_value_t *retval) |
2267 | 1.97k | { |
2268 | 1.97k | njs_property_next_t *next; |
2269 | 1.97k | njs_vmcode_prop_foreach_t *code; |
2270 | | |
2271 | 1.97k | next = njs_mp_alloc(vm->mem_pool, sizeof(njs_property_next_t)); |
2272 | 1.97k | if (njs_slow_path(next == NULL)) { |
2273 | 0 | njs_memory_error(vm); |
2274 | 0 | return NJS_ERROR; |
2275 | 0 | } |
2276 | | |
2277 | 1.97k | next->index = 0; |
2278 | 1.97k | next->array = njs_value_enumerate(vm, object, |
2279 | 1.97k | NJS_ENUM_KEYS |
2280 | 1.97k | | NJS_ENUM_STRING |
2281 | 1.97k | | NJS_ENUM_ENUMERABLE_ONLY); |
2282 | 1.97k | if (njs_slow_path(next->array == NULL)) { |
2283 | 0 | njs_memory_error(vm); |
2284 | 0 | return NJS_ERROR; |
2285 | 0 | } |
2286 | | |
2287 | 1.97k | njs_set_data(retval, next, NJS_DATA_TAG_FOREACH_NEXT); |
2288 | | |
2289 | 1.97k | code = (njs_vmcode_prop_foreach_t *) pc; |
2290 | | |
2291 | 1.97k | return code->offset; |
2292 | 1.97k | } |
2293 | | |
2294 | | |
2295 | | static njs_jump_off_t |
2296 | | njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object, |
2297 | | njs_value_t *constructor, njs_value_t *retval) |
2298 | 0 | { |
2299 | 0 | njs_value_t value, bound; |
2300 | 0 | njs_object_t *prototype, *proto; |
2301 | 0 | njs_function_t *function; |
2302 | 0 | njs_jump_off_t ret; |
2303 | |
|
2304 | 0 | if (!njs_is_function(constructor)) { |
2305 | 0 | njs_type_error(vm, "right argument is not callable"); |
2306 | 0 | return NJS_ERROR; |
2307 | 0 | } |
2308 | | |
2309 | 0 | function = njs_function(constructor); |
2310 | |
|
2311 | 0 | if (function->bound != NULL) { |
2312 | 0 | function = function->context; |
2313 | 0 | njs_set_function(&bound, function); |
2314 | 0 | constructor = &bound; |
2315 | 0 | } |
2316 | |
|
2317 | 0 | if (njs_is_object(object)) { |
2318 | 0 | ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype, |
2319 | 0 | &value); |
2320 | |
|
2321 | 0 | if (njs_slow_path(ret == NJS_ERROR)) { |
2322 | 0 | return ret; |
2323 | 0 | } |
2324 | | |
2325 | 0 | if (njs_fast_path(ret == NJS_OK)) { |
2326 | 0 | if (njs_slow_path(!njs_is_object(&value))) { |
2327 | 0 | njs_type_error(vm, "Function has non-object prototype " |
2328 | 0 | "in instanceof"); |
2329 | 0 | return NJS_ERROR; |
2330 | 0 | } |
2331 | | |
2332 | 0 | prototype = njs_object(&value); |
2333 | 0 | proto = njs_object(object); |
2334 | |
|
2335 | 0 | do { |
2336 | 0 | proto = proto->__proto__; |
2337 | |
|
2338 | 0 | if (proto == prototype) { |
2339 | 0 | njs_value_assign(retval, &njs_value_true); |
2340 | 0 | return sizeof(njs_vmcode_instance_of_t); |
2341 | 0 | } |
2342 | |
|
2343 | 0 | } while (proto != NULL); |
2344 | 0 | } |
2345 | 0 | } |
2346 | | |
2347 | 0 | njs_value_assign(retval, &njs_value_false); |
2348 | |
|
2349 | 0 | return sizeof(njs_vmcode_instance_of_t); |
2350 | 0 | } |
2351 | | |
2352 | | |
2353 | | static njs_jump_off_t |
2354 | | njs_vmcode_typeof(njs_vm_t *vm, njs_value_t *value, njs_value_t *retval) |
2355 | 0 | { |
2356 | | /* ECMAScript 5.1: null, array and regexp are objects. */ |
2357 | |
|
2358 | 0 | static const uint32_t types[NJS_VALUE_TYPE_MAX] = { |
2359 | 0 | NJS_ATOM_STRING_object, |
2360 | 0 | NJS_ATOM_STRING_undefined, |
2361 | 0 | NJS_ATOM_STRING_boolean, |
2362 | 0 | NJS_ATOM_STRING_number, |
2363 | 0 | NJS_ATOM_STRING_symbol, |
2364 | 0 | NJS_ATOM_STRING_string, |
2365 | 0 | NJS_ATOM_STRING_data, |
2366 | 0 | NJS_ATOM_STRING_external, |
2367 | 0 | NJS_ATOM_STRING_unknown, |
2368 | 0 | NJS_ATOM_STRING_undefined, |
2369 | 0 | NJS_ATOM_STRING_undefined, |
2370 | 0 | NJS_ATOM_STRING_undefined, |
2371 | 0 | NJS_ATOM_STRING_undefined, |
2372 | 0 | NJS_ATOM_STRING_undefined, |
2373 | 0 | NJS_ATOM_STRING_undefined, |
2374 | 0 | NJS_ATOM_STRING_undefined, |
2375 | |
|
2376 | 0 | NJS_ATOM_STRING_object, |
2377 | 0 | NJS_ATOM_STRING_object, |
2378 | 0 | NJS_ATOM_STRING_function, |
2379 | 0 | NJS_ATOM_STRING_object, |
2380 | 0 | NJS_ATOM_STRING_object, |
2381 | 0 | NJS_ATOM_STRING_object, |
2382 | 0 | NJS_ATOM_STRING_object, |
2383 | 0 | NJS_ATOM_STRING_object, |
2384 | 0 | NJS_ATOM_STRING_object, |
2385 | 0 | NJS_ATOM_STRING_object, |
2386 | 0 | }; |
2387 | |
|
2388 | 0 | njs_atom_to_value(vm, retval, types[value->type]); |
2389 | |
|
2390 | 0 | return sizeof(njs_vmcode_2addr_t); |
2391 | 0 | } |
2392 | | |
2393 | | |
2394 | | static njs_jump_off_t |
2395 | | njs_vmcode_debugger(njs_vm_t *vm, njs_value_t *retval) |
2396 | 0 | { |
2397 | | /* |
2398 | | * HOW TO DEBUG JS CODE: |
2399 | | * 1) put debugger instruction when certain condition is met |
2400 | | * in the JS code: |
2401 | | * function test() { |
2402 | | * if (<>) debugger; |
2403 | | * } |
2404 | | * 2) set a breakpoint to njs_vmcode_debugger() in gdb. |
2405 | | * |
2406 | | * To see the values of certain indices: |
2407 | | * 1) use njs -d test.js to dump the byte code |
2408 | | * 2) find an appropriate index around DEBUGGER instruction |
2409 | | * 3) in gdb: p *njs_scope_value_get(vm, <index as a hex literal>) |
2410 | | **/ |
2411 | |
|
2412 | 0 | njs_set_undefined(retval); |
2413 | |
|
2414 | 0 | return sizeof(njs_vmcode_debugger_t); |
2415 | 0 | } |
2416 | | |
2417 | | |
2418 | | static njs_jump_off_t |
2419 | | njs_string_concat(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2, |
2420 | | njs_value_t *retval) |
2421 | 167k | { |
2422 | 167k | u_char *start; |
2423 | 167k | size_t size, length; |
2424 | 167k | njs_string_prop_t string1, string2; |
2425 | | |
2426 | 167k | (void) njs_string_prop(vm, &string1, val1); |
2427 | 167k | (void) njs_string_prop(vm, &string2, val2); |
2428 | | |
2429 | 167k | length = string1.length + string2.length; |
2430 | 167k | size = string1.size + string2.size; |
2431 | | |
2432 | 167k | start = njs_string_alloc(vm, retval, size, length); |
2433 | 167k | if (njs_slow_path(start == NULL)) { |
2434 | 0 | return NJS_ERROR; |
2435 | 0 | } |
2436 | | |
2437 | 167k | (void) memcpy(start, string1.start, string1.size); |
2438 | 167k | (void) memcpy(start + string1.size, string2.start, string2.size); |
2439 | | |
2440 | 167k | return sizeof(njs_vmcode_3addr_t); |
2441 | 167k | } |
2442 | | |
2443 | | |
2444 | | static njs_jump_off_t |
2445 | | njs_values_equal(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) |
2446 | 10.6k | { |
2447 | 10.6k | njs_int_t ret; |
2448 | 10.6k | njs_bool_t nv1, nv2; |
2449 | 10.6k | njs_value_t primitive; |
2450 | 10.6k | njs_value_t *hv, *lv; |
2451 | | |
2452 | 10.6k | again: |
2453 | | |
2454 | 10.6k | nv1 = njs_is_null_or_undefined(val1); |
2455 | 10.6k | nv2 = njs_is_null_or_undefined(val2); |
2456 | | |
2457 | | /* Void and null are equal and not comparable with anything else. */ |
2458 | 10.6k | if (nv1 || nv2) { |
2459 | 283 | return (nv1 && nv2); |
2460 | 283 | } |
2461 | | |
2462 | 10.3k | if (njs_is_numeric(val1) && njs_is_numeric(val2)) { |
2463 | | /* NaNs and Infinities are handled correctly by comparision. */ |
2464 | 10.3k | return (njs_number(val1) == njs_number(val2)); |
2465 | 10.3k | } |
2466 | | |
2467 | 0 | if (val1->type == val2->type) { |
2468 | |
|
2469 | 0 | if (njs_is_string(val1)) { |
2470 | 0 | return njs_string_eq(vm, val1, val2); |
2471 | 0 | } |
2472 | | |
2473 | 0 | if (njs_is_symbol(val1)) { |
2474 | 0 | return njs_symbol_eq(val1, val2); |
2475 | 0 | } |
2476 | | |
2477 | 0 | return (njs_object(val1) == njs_object(val2)); |
2478 | 0 | } |
2479 | | |
2480 | | /* Sort values as: numeric < symbol < string < objects. */ |
2481 | | |
2482 | 0 | if (val1->type > val2->type) { |
2483 | 0 | hv = val1; |
2484 | 0 | lv = val2; |
2485 | |
|
2486 | 0 | } else { |
2487 | 0 | hv = val2; |
2488 | 0 | lv = val1; |
2489 | 0 | } |
2490 | | |
2491 | | /* If "lv" is an object then "hv" can only be another object. */ |
2492 | 0 | if (njs_is_object(lv)) { |
2493 | 0 | return 0; |
2494 | 0 | } |
2495 | | |
2496 | | /* If "hv" is a symbol then "lv" can only be a numeric. */ |
2497 | 0 | if (njs_is_symbol(hv)) { |
2498 | 0 | return 0; |
2499 | 0 | } |
2500 | | |
2501 | | /* If "hv" is a string then "lv" can be a numeric or symbol. */ |
2502 | 0 | if (njs_is_string(hv)) { |
2503 | 0 | return !njs_is_symbol(lv) |
2504 | 0 | && (njs_number(lv) == njs_string_to_number(vm, hv)); |
2505 | 0 | } |
2506 | | |
2507 | | /* "hv" is an object and "lv" is either a string or a symbol or a numeric. */ |
2508 | | |
2509 | 0 | ret = njs_value_to_primitive(vm, &primitive, hv, NJS_HINT_NONE); |
2510 | 0 | if (ret != NJS_OK) { |
2511 | 0 | return ret; |
2512 | 0 | } |
2513 | | |
2514 | 0 | val1 = &primitive; |
2515 | 0 | val2 = lv; |
2516 | |
|
2517 | 0 | goto again; |
2518 | 0 | } |
2519 | | |
2520 | | |
2521 | | /* |
2522 | | * ECMAScript 5.1: 11.8.5 |
2523 | | * njs_primitive_values_compare() returns |
2524 | | * 1 if val1 is less than val2, |
2525 | | * 0 if val1 is greater than or equal to val2, |
2526 | | * -1 if the values are not comparable. |
2527 | | */ |
2528 | | |
2529 | | static njs_jump_off_t |
2530 | | njs_primitive_values_compare(njs_vm_t *vm, njs_value_t *val1, njs_value_t *val2) |
2531 | 88.2k | { |
2532 | 88.2k | double num1, num2; |
2533 | | |
2534 | 88.2k | if (njs_fast_path(njs_is_numeric(val1))) { |
2535 | 27.3k | num1 = njs_number(val1); |
2536 | | |
2537 | 27.3k | if (njs_fast_path(njs_is_numeric(val2))) { |
2538 | 23.5k | num2 = njs_number(val2); |
2539 | | |
2540 | 23.5k | } else { |
2541 | 3.87k | num2 = njs_string_to_number(vm, val2); |
2542 | 3.87k | } |
2543 | | |
2544 | 60.8k | } else if (njs_is_numeric(val2)) { |
2545 | 30.4k | num1 = njs_string_to_number(vm, val1); |
2546 | 30.4k | num2 = njs_number(val2); |
2547 | | |
2548 | 30.4k | } else { |
2549 | 30.3k | return (njs_string_cmp(vm, val1, val2) < 0) ? 1 : 0; |
2550 | 30.3k | } |
2551 | | |
2552 | | /* NaN and void values are not comparable with anything. */ |
2553 | 57.8k | if (isnan(num1) || isnan(num2)) { |
2554 | 57.4k | return -1; |
2555 | 57.4k | } |
2556 | | |
2557 | | /* Infinities are handled correctly by comparision. */ |
2558 | 443 | return (num1 < num2); |
2559 | 57.8k | } |
2560 | | |
2561 | | |
2562 | | static njs_jump_off_t |
2563 | | njs_function_frame_create(njs_vm_t *vm, njs_value_t *value, |
2564 | | const njs_value_t *this, uintptr_t nargs, njs_bool_t ctor) |
2565 | 378k | { |
2566 | 378k | njs_int_t ret; |
2567 | 378k | njs_value_t new_target, *args; |
2568 | 378k | njs_object_t *object; |
2569 | 378k | njs_function_t *function, *target; |
2570 | | |
2571 | 378k | if (njs_fast_path(njs_is_function(value))) { |
2572 | | |
2573 | 378k | function = njs_function(value); |
2574 | 378k | target = function; |
2575 | 378k | args = NULL; |
2576 | | |
2577 | 378k | if (ctor) { |
2578 | 117k | if (function->bound != NULL) { |
2579 | 0 | target = function->context; |
2580 | 0 | nargs += function->bound_args; |
2581 | |
|
2582 | 0 | args = njs_mp_alloc(vm->mem_pool, nargs * sizeof(njs_value_t)); |
2583 | 0 | if (njs_slow_path(args == NULL)) { |
2584 | 0 | njs_memory_error(vm); |
2585 | 0 | return NJS_ERROR; |
2586 | 0 | } |
2587 | | |
2588 | 0 | memcpy(args, &function->bound[1], |
2589 | 0 | function->bound_args * sizeof(njs_value_t)); |
2590 | 0 | } |
2591 | | |
2592 | 117k | if (!target->ctor) { |
2593 | 0 | njs_type_error(vm, "%s is not a constructor", |
2594 | 0 | njs_type_string(value->type)); |
2595 | 0 | return NJS_ERROR; |
2596 | 0 | } |
2597 | | |
2598 | 117k | if (!target->native) { |
2599 | 0 | object = njs_function_new_object(vm, value); |
2600 | 0 | if (njs_slow_path(object == NULL)) { |
2601 | 0 | return NJS_ERROR; |
2602 | 0 | } |
2603 | | |
2604 | 0 | njs_set_object(&new_target, object); |
2605 | 0 | this = &new_target; |
2606 | 0 | } |
2607 | 117k | } |
2608 | | |
2609 | 378k | ret = njs_function_frame(vm, target, this, args, nargs, ctor); |
2610 | | |
2611 | 378k | if (args != NULL) { |
2612 | 0 | vm->top_frame->put_args = function->bound_args; |
2613 | 0 | njs_mp_free(vm->mem_pool, args); |
2614 | 0 | } |
2615 | | |
2616 | 378k | return ret; |
2617 | 378k | } |
2618 | | |
2619 | 55 | njs_type_error(vm, "%s is not a function", njs_type_string(value->type)); |
2620 | | |
2621 | 55 | return NJS_ERROR; |
2622 | 378k | } |
2623 | | |
2624 | | |
2625 | | njs_object_t * |
2626 | | njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor) |
2627 | 52.5k | { |
2628 | 52.5k | njs_value_t proto, bound; |
2629 | 52.5k | njs_object_t *object; |
2630 | 52.5k | njs_function_t *function; |
2631 | 52.5k | njs_jump_off_t ret; |
2632 | | |
2633 | 52.5k | object = njs_object_alloc(vm); |
2634 | 52.5k | if (njs_slow_path(object == NULL)) { |
2635 | 0 | return NULL; |
2636 | 0 | } |
2637 | | |
2638 | 52.5k | njs_assert(njs_is_function(constructor)); |
2639 | | |
2640 | 52.5k | function = njs_function(constructor); |
2641 | | |
2642 | 52.5k | if (function->bound != NULL) { |
2643 | 0 | function = function->context; |
2644 | 0 | njs_set_function(&bound, function); |
2645 | 0 | constructor = &bound; |
2646 | 0 | } |
2647 | | |
2648 | 52.5k | ret = njs_value_property(vm, constructor, NJS_ATOM_STRING_prototype, &proto); |
2649 | | |
2650 | 52.5k | if (njs_slow_path(ret == NJS_ERROR)) { |
2651 | 0 | return NULL; |
2652 | 0 | } |
2653 | | |
2654 | 52.5k | if (njs_fast_path(njs_is_object(&proto))) { |
2655 | 52.5k | object->__proto__ = njs_object(&proto); |
2656 | 52.5k | } |
2657 | | |
2658 | 52.5k | return object; |
2659 | 52.5k | } |
2660 | | |
2661 | | |
2662 | | static void |
2663 | | njs_vmcode_return(njs_vm_t *vm, njs_value_t *dst, njs_value_t *retval) |
2664 | 43.7k | { |
2665 | 43.7k | njs_frame_t *frame; |
2666 | | |
2667 | 43.7k | frame = (njs_frame_t *) vm->top_frame; |
2668 | | |
2669 | 43.7k | if (frame->native.ctor) { |
2670 | 0 | if (!njs_is_object(retval)) { |
2671 | 0 | retval = frame->native.local[0]; |
2672 | 0 | } |
2673 | 0 | } |
2674 | | |
2675 | 43.7k | njs_vm_scopes_restore(vm, &frame->native); |
2676 | | |
2677 | 43.7k | *dst = *retval; |
2678 | | |
2679 | 43.7k | njs_function_frame_free(vm, &frame->native); |
2680 | 43.7k | } |
2681 | | |
2682 | | |
2683 | | static njs_jump_off_t |
2684 | | njs_vmcode_import(njs_vm_t *vm, njs_mod_t *module, njs_value_t *retval) |
2685 | 0 | { |
2686 | 0 | njs_int_t ret; |
2687 | 0 | njs_mod_t *m; |
2688 | |
|
2689 | 0 | m = njs_module_find(vm, &module->name, 0); |
2690 | 0 | if (njs_slow_path(m == NULL)) { |
2691 | 0 | if (!njs_is_valid(&vm->exception)) { |
2692 | 0 | njs_error(vm, "Cannot load module \"%V\"", &module->name); |
2693 | 0 | } |
2694 | |
|
2695 | 0 | return NJS_ERROR; |
2696 | 0 | } |
2697 | | |
2698 | 0 | if (!njs_is_null(&m->value)) { |
2699 | 0 | njs_value_assign(retval, &m->value); |
2700 | 0 | return sizeof(njs_vmcode_import_t); |
2701 | 0 | } |
2702 | | |
2703 | 0 | njs_set_invalid(&m->value); |
2704 | |
|
2705 | 0 | ret = njs_vm_invoke(vm, &m->function, NULL, 0, &m->value); |
2706 | 0 | if (ret == NJS_ERROR) { |
2707 | 0 | return ret; |
2708 | 0 | } |
2709 | | |
2710 | 0 | njs_value_assign(retval, &m->value); |
2711 | |
|
2712 | 0 | return sizeof(njs_vmcode_import_t); |
2713 | 0 | } |
2714 | | |
2715 | | |
2716 | | static njs_int_t |
2717 | | njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await, |
2718 | | njs_value_t *dst, njs_promise_capability_t *pcap, njs_async_ctx_t *ctx) |
2719 | 5.71k | { |
2720 | 5.71k | size_t size; |
2721 | 5.71k | njs_int_t ret; |
2722 | 5.71k | njs_value_t ctor, val, on_fulfilled, on_rejected, *value, retval; |
2723 | 5.71k | njs_function_t *fulfilled, *rejected; |
2724 | 5.71k | njs_native_frame_t *active; |
2725 | | |
2726 | 5.71k | active = &vm->active_frame->native; |
2727 | | |
2728 | 5.71k | value = njs_scope_valid_value(vm, await->retval); |
2729 | 5.71k | if (njs_slow_path(value == NULL)) { |
2730 | 0 | njs_internal_error(vm, "await->retval is invalid"); |
2731 | 0 | return NJS_ERROR; |
2732 | 0 | } |
2733 | | |
2734 | 5.71k | njs_set_function(&ctor, &njs_vm_ctor(vm, NJS_OBJ_TYPE_PROMISE)); |
2735 | | |
2736 | 5.71k | ret = njs_promise_resolve(vm, &ctor, value, &val); |
2737 | 5.71k | if (njs_slow_path(ret != NJS_OK)) { |
2738 | 0 | return NJS_ERROR; |
2739 | 0 | } |
2740 | | |
2741 | 5.71k | if (ctx == NULL) { |
2742 | 253 | ctx = njs_mp_alloc(vm->mem_pool, sizeof(njs_async_ctx_t)); |
2743 | 253 | if (njs_slow_path(ctx == NULL)) { |
2744 | 0 | njs_memory_error(vm); |
2745 | 0 | return NJS_ERROR; |
2746 | 0 | } |
2747 | | |
2748 | 253 | size = njs_function_frame_size(active); |
2749 | | |
2750 | 253 | fulfilled = njs_promise_create_function(vm, size); |
2751 | 253 | if (njs_slow_path(fulfilled == NULL)) { |
2752 | 0 | return NJS_ERROR; |
2753 | 0 | } |
2754 | | |
2755 | 253 | ctx->await = fulfilled->context; |
2756 | 253 | ctx->capability = pcap; |
2757 | | |
2758 | 253 | ret = njs_function_frame_save(vm, ctx->await, NULL); |
2759 | 253 | if (njs_slow_path(ret != NJS_OK)) { |
2760 | 0 | return NJS_ERROR; |
2761 | 0 | } |
2762 | | |
2763 | 5.46k | } else { |
2764 | 5.46k | fulfilled = njs_promise_create_function(vm, 0); |
2765 | 5.46k | if (njs_slow_path(fulfilled == NULL)) { |
2766 | 0 | return NJS_ERROR; |
2767 | 0 | } |
2768 | 5.46k | } |
2769 | | |
2770 | 5.71k | ctx->pc = (u_char *) await + sizeof(njs_vmcode_await_t); |
2771 | 5.71k | ctx->index = await->retval; |
2772 | 5.71k | ctx->throw_flag = 0; |
2773 | | |
2774 | 5.71k | fulfilled->context = ctx; |
2775 | 5.71k | fulfilled->args_count = 1; |
2776 | 5.71k | fulfilled->u.native = njs_await_fulfilled; |
2777 | | |
2778 | 5.71k | rejected = njs_promise_create_function(vm, 0); |
2779 | 5.71k | if (njs_slow_path(rejected == NULL)) { |
2780 | 0 | return NJS_ERROR; |
2781 | 0 | } |
2782 | | |
2783 | 5.71k | rejected->context = ctx; |
2784 | 5.71k | rejected->args_count = 1; |
2785 | 5.71k | rejected->u.native = njs_await_rejected; |
2786 | | |
2787 | 5.71k | njs_set_function(&on_fulfilled, fulfilled); |
2788 | 5.71k | njs_set_function(&on_rejected, rejected); |
2789 | | |
2790 | 5.71k | ret = njs_promise_perform_then(vm, &val, &on_fulfilled, &on_rejected, NULL, |
2791 | 5.71k | &retval); |
2792 | 5.71k | if (njs_slow_path(ret != NJS_OK)) { |
2793 | 0 | return NJS_ERROR; |
2794 | 0 | } |
2795 | | |
2796 | 5.71k | njs_vmcode_return(vm, dst, &retval); |
2797 | | |
2798 | 5.71k | return NJS_AGAIN; |
2799 | 5.71k | } |
2800 | | |
2801 | | |
2802 | | /* |
2803 | | * njs_vmcode_try_start() is set on the start of a "try" block to create |
2804 | | * a "try" block, to set a catch address to the start of a "catch" or |
2805 | | * "finally" blocks and to initialize a value to track uncaught exception. |
2806 | | */ |
2807 | | |
2808 | | static njs_jump_off_t |
2809 | | njs_vmcode_try_start(njs_vm_t *vm, njs_value_t *exception_value, |
2810 | | njs_value_t *offset, u_char *pc) |
2811 | 76.1k | { |
2812 | 76.1k | njs_value_t *exit_value; |
2813 | 76.1k | njs_frame_t *frame; |
2814 | 76.1k | njs_exception_t *e; |
2815 | 76.1k | njs_vmcode_try_start_t *try_start; |
2816 | | |
2817 | 76.1k | frame = (njs_frame_t *) vm->top_frame; |
2818 | | |
2819 | 76.1k | if (frame->exception.catch != NULL) { |
2820 | 2.05k | e = njs_mp_alloc(vm->mem_pool, sizeof(njs_exception_t)); |
2821 | 2.05k | if (njs_slow_path(e == NULL)) { |
2822 | 0 | njs_memory_error(vm); |
2823 | 0 | return NJS_ERROR; |
2824 | 0 | } |
2825 | | |
2826 | 2.05k | *e = frame->exception; |
2827 | 2.05k | frame->exception.next = e; |
2828 | 2.05k | } |
2829 | | |
2830 | 76.1k | frame->exception.catch = pc + (njs_jump_off_t) offset; |
2831 | | |
2832 | 76.1k | njs_set_invalid(exception_value); |
2833 | | |
2834 | 76.1k | try_start = (njs_vmcode_try_start_t *) pc; |
2835 | 76.1k | exit_value = njs_scope_value(vm, try_start->exit_value); |
2836 | | |
2837 | 76.1k | njs_set_invalid(exit_value); |
2838 | 76.1k | njs_number(exit_value) = 0; |
2839 | | |
2840 | 76.1k | return sizeof(njs_vmcode_try_start_t); |
2841 | 76.1k | } |
2842 | | |
2843 | | |
2844 | | /* |
2845 | | * njs_vmcode_try_break() sets exit_value to INVALID 1, and jumps to |
2846 | | * the nearest try_end block. The exit_value is checked by njs_vmcode_finally(). |
2847 | | */ |
2848 | | |
2849 | | static njs_jump_off_t |
2850 | | njs_vmcode_try_break(njs_vm_t *vm, njs_value_t *exit_value, |
2851 | | njs_value_t *offset) |
2852 | 0 | { |
2853 | | /* exit_value can contain valid value set by vmcode_try_return. */ |
2854 | 0 | if (!njs_is_valid(exit_value)) { |
2855 | 0 | njs_number(exit_value) = 1; |
2856 | 0 | } |
2857 | |
|
2858 | 0 | return (njs_jump_off_t) offset; |
2859 | 0 | } |
2860 | | |
2861 | | |
2862 | | /* |
2863 | | * njs_vmcode_try_continue() sets exit_value to INVALID -1, and jumps to |
2864 | | * the nearest try_end block. The exit_value is checked by njs_vmcode_finally(). |
2865 | | */ |
2866 | | |
2867 | | static njs_jump_off_t |
2868 | | njs_vmcode_try_continue(njs_vm_t *vm, njs_value_t *exit_value, |
2869 | | njs_value_t *offset) |
2870 | 6 | { |
2871 | 6 | njs_number(exit_value) = -1; |
2872 | | |
2873 | 6 | return (njs_jump_off_t) offset; |
2874 | 6 | } |
2875 | | |
2876 | | |
2877 | | /* |
2878 | | * njs_vmcode_try_end() is set on the end of a "try" block to remove the block. |
2879 | | * It is also set on the end of a "catch" block followed by a "finally" block. |
2880 | | */ |
2881 | | |
2882 | | static njs_jump_off_t |
2883 | | njs_vmcode_try_end(njs_vm_t *vm, njs_value_t *invld, njs_value_t *offset) |
2884 | 76.1k | { |
2885 | 76.1k | njs_frame_t *frame; |
2886 | 76.1k | njs_exception_t *e; |
2887 | | |
2888 | 76.1k | frame = (njs_frame_t *) vm->top_frame; |
2889 | 76.1k | e = frame->exception.next; |
2890 | | |
2891 | 76.1k | if (e == NULL) { |
2892 | 74.1k | frame->exception.catch = NULL; |
2893 | | |
2894 | 74.1k | } else { |
2895 | 2.05k | frame->exception = *e; |
2896 | 2.05k | njs_mp_free(vm->mem_pool, e); |
2897 | 2.05k | } |
2898 | | |
2899 | 76.1k | return (njs_jump_off_t) offset; |
2900 | 76.1k | } |
2901 | | |
2902 | | |
2903 | | /* |
2904 | | * njs_vmcode_finally() is set on the end of a "finally" or a "catch" block. |
2905 | | * 1) to throw uncaught exception. |
2906 | | * 2) to make a jump to an enslosing loop exit if "continue" or "break" |
2907 | | * statement was used inside try block. |
2908 | | * 3) to finalize "return" instruction from "try" block. |
2909 | | */ |
2910 | | |
2911 | | static njs_jump_off_t |
2912 | | njs_vmcode_finally(njs_vm_t *vm, njs_value_t *dst, njs_value_t *retval, |
2913 | | u_char *pc) |
2914 | 1.09k | { |
2915 | 1.09k | njs_value_t *exception_value, *exit_value; |
2916 | 1.09k | njs_jump_off_t offset; |
2917 | 1.09k | njs_vmcode_finally_t *finally; |
2918 | | |
2919 | 1.09k | exception_value = njs_scope_value(vm, (njs_index_t) retval); |
2920 | | |
2921 | 1.09k | if (njs_is_valid(exception_value)) { |
2922 | 516 | njs_vm_throw(vm, exception_value); |
2923 | | |
2924 | 516 | return NJS_ERROR; |
2925 | 516 | } |
2926 | | |
2927 | 578 | finally = (njs_vmcode_finally_t *) pc; |
2928 | | |
2929 | 578 | exit_value = njs_scope_value(vm, finally->exit_value); |
2930 | | |
2931 | | /* |
2932 | | * exit_value is set by: |
2933 | | * vmcode_try_start to INVALID 0 |
2934 | | * vmcode_try_break to INVALID 1 |
2935 | | * vmcode_try_continue to INVALID -1 |
2936 | | * vmcode_try_return to a valid return value |
2937 | | */ |
2938 | | |
2939 | 578 | if (njs_is_valid(exit_value)) { |
2940 | 0 | njs_vmcode_return(vm, dst, exit_value); |
2941 | |
|
2942 | 0 | return NJS_OK; |
2943 | |
|
2944 | 578 | } else if (njs_number(exit_value) != 0) { |
2945 | 6 | offset = (njs_number(exit_value) > 0) ? finally->break_offset |
2946 | 6 | : finally->continue_offset; |
2947 | | |
2948 | 6 | if (njs_slow_path(offset |
2949 | 6 | < (njs_jump_off_t) sizeof(njs_vmcode_finally_t))) |
2950 | 0 | { |
2951 | 0 | njs_internal_error(vm, "unset %s offset for FINALLY block", |
2952 | 0 | (njs_number(exit_value) > 0) ? "exit" |
2953 | 0 | : "continuaion"); |
2954 | 0 | return NJS_ERROR; |
2955 | 0 | } |
2956 | | |
2957 | 6 | return offset; |
2958 | 6 | } |
2959 | | |
2960 | 572 | return sizeof(njs_vmcode_finally_t); |
2961 | 578 | } |
2962 | | |
2963 | | |
2964 | | static void |
2965 | | njs_vmcode_error(njs_vm_t *vm, u_char *pc) |
2966 | 22.0k | { |
2967 | 22.0k | njs_vmcode_error_t *err; |
2968 | | |
2969 | 22.0k | err = (njs_vmcode_error_t *) pc; |
2970 | | |
2971 | 22.0k | if (err->type == NJS_OBJ_TYPE_REF_ERROR) { |
2972 | 22.0k | njs_reference_error(vm, "\"%V\" is not defined", &err->u.name); |
2973 | | |
2974 | 22.0k | } else { |
2975 | 0 | njs_throw_error(vm, err->type, "%V", &err->u.message); |
2976 | 0 | } |
2977 | 22.0k | } |
2978 | | |
2979 | | |
2980 | | static njs_int_t |
2981 | | njs_throw_cannot_property(njs_vm_t *vm, njs_value_t *object, njs_value_t *key, |
2982 | | const char *what) |
2983 | 0 | { |
2984 | 0 | njs_int_t ret; |
2985 | 0 | njs_str_t string; |
2986 | 0 | njs_value_t dst; |
2987 | |
|
2988 | 0 | ret = njs_value_to_key2(vm, &dst, key, 0); |
2989 | 0 | if (njs_slow_path(ret != NJS_OK)) { |
2990 | 0 | return NJS_ERROR; |
2991 | 0 | } |
2992 | | |
2993 | 0 | njs_key_string_get(vm, &dst, &string); |
2994 | |
|
2995 | 0 | njs_type_error(vm, "cannot %s property \"%V\" of %s", what, |
2996 | 0 | &string, njs_is_null(object) ? "null" : "undefined"); |
2997 | |
|
2998 | 0 | return NJS_OK; |
2999 | 0 | } |