1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #ifndef _NJS_VM_H_INCLUDED_
8 #define _NJS_VM_H_INCLUDED_
9 
10 
11 #define NJS_MAX_STACK_SIZE       (256 * 1024)
12 
13 
14 /*
15  * NJS_PROPERTY_QUERY_GET must be less to NJS_PROPERTY_QUERY_SET
16  * and NJS_PROPERTY_QUERY_DELETE.
17  */
18 #define NJS_PROPERTY_QUERY_GET     0
19 #define NJS_PROPERTY_QUERY_SET     1
20 #define NJS_PROPERTY_QUERY_DELETE  2
21 
22 
23 typedef struct njs_frame_s            njs_frame_t;
24 typedef struct njs_native_frame_s     njs_native_frame_t;
25 typedef struct njs_parser_s           njs_parser_t;
26 typedef struct njs_parser_scope_s     njs_parser_scope_t;
27 typedef struct njs_parser_node_s      njs_parser_node_t;
28 typedef struct njs_generator_s        njs_generator_t;
29 
30 
31 typedef enum {
32     NJS_SCOPE_GLOBAL = 0,
33     NJS_SCOPE_FUNCTION,
34     NJS_SCOPE_BLOCK
35 } njs_scope_t;
36 
37 
38 typedef enum {
39     NJS_OBJ_TYPE_OBJECT = 0,
40     NJS_OBJ_TYPE_ARRAY,
41     NJS_OBJ_TYPE_BOOLEAN,
42     NJS_OBJ_TYPE_NUMBER,
43     NJS_OBJ_TYPE_SYMBOL,
44     NJS_OBJ_TYPE_STRING,
45     NJS_OBJ_TYPE_FUNCTION,
46     NJS_OBJ_TYPE_ASYNC_FUNCTION,
47     NJS_OBJ_TYPE_REGEXP,
48     NJS_OBJ_TYPE_DATE,
49     NJS_OBJ_TYPE_PROMISE,
50     NJS_OBJ_TYPE_ARRAY_BUFFER,
51     NJS_OBJ_TYPE_DATA_VIEW,
52     NJS_OBJ_TYPE_TEXT_DECODER,
53     NJS_OBJ_TYPE_TEXT_ENCODER,
54     NJS_OBJ_TYPE_BUFFER,
55 
56 #define NJS_OBJ_TYPE_HIDDEN_MIN    (NJS_OBJ_TYPE_ITERATOR)
57     NJS_OBJ_TYPE_ITERATOR,
58     NJS_OBJ_TYPE_ARRAY_ITERATOR,
59     NJS_OBJ_TYPE_TYPED_ARRAY,
60 #define NJS_OBJ_TYPE_HIDDEN_MAX    (NJS_OBJ_TYPE_TYPED_ARRAY + 1)
61 #define NJS_OBJ_TYPE_NORMAL_MAX    (NJS_OBJ_TYPE_HIDDEN_MAX)
62 
63 #define NJS_OBJ_TYPE_TYPED_ARRAY_MIN    (NJS_OBJ_TYPE_UINT8_ARRAY)
64 #define njs_typed_array_index(type)     (type - NJS_OBJ_TYPE_TYPED_ARRAY_MIN)
65     NJS_OBJ_TYPE_UINT8_ARRAY,
66     NJS_OBJ_TYPE_UINT8_CLAMPED_ARRAY,
67     NJS_OBJ_TYPE_INT8_ARRAY,
68     NJS_OBJ_TYPE_UINT16_ARRAY,
69     NJS_OBJ_TYPE_INT16_ARRAY,
70     NJS_OBJ_TYPE_UINT32_ARRAY,
71     NJS_OBJ_TYPE_INT32_ARRAY,
72     NJS_OBJ_TYPE_FLOAT32_ARRAY,
73     NJS_OBJ_TYPE_FLOAT64_ARRAY,
74 #define NJS_OBJ_TYPE_TYPED_ARRAY_MAX    (NJS_OBJ_TYPE_FLOAT64_ARRAY + 1)
75 #define NJS_OBJ_TYPE_TYPED_ARRAY_SIZE   (NJS_OBJ_TYPE_TYPED_ARRAY_MAX         \
76                                          - NJS_OBJ_TYPE_TYPED_ARRAY_MIN)
77 
78     NJS_OBJ_TYPE_ERROR,
79     NJS_OBJ_TYPE_EVAL_ERROR,
80     NJS_OBJ_TYPE_INTERNAL_ERROR,
81     NJS_OBJ_TYPE_RANGE_ERROR,
82     NJS_OBJ_TYPE_REF_ERROR,
83     NJS_OBJ_TYPE_SYNTAX_ERROR,
84     NJS_OBJ_TYPE_TYPE_ERROR,
85     NJS_OBJ_TYPE_URI_ERROR,
86     NJS_OBJ_TYPE_MEMORY_ERROR,
87     NJS_OBJ_TYPE_AGGREGATE_ERROR,
88 
89     NJS_OBJ_TYPE_MAX,
90 } njs_object_type_t;
91 
92 
93 #define njs_primitive_prototype_index(type)                                   \
94     (NJS_OBJ_TYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
95 
96 
97 #define njs_prototype_type(index)                                             \
98     (index + NJS_OBJECT)
99 
100 
101 enum njs_object_e {
102     NJS_OBJECT_THIS = 0,
103     NJS_OBJECT_NJS,
104     NJS_OBJECT_PROCESS,
105     NJS_OBJECT_MATH,
106     NJS_OBJECT_JSON,
107 #ifdef NJS_TEST262
108     NJS_OBJECT_262,
109 #endif
110     NJS_OBJECT_MAX
111 };
112 
113 
114 enum njs_hook_e {
115     NJS_HOOK_EXIT = 0,
116     NJS_HOOK_MAX
117 };
118 
119 
120 typedef enum {
121     NJS_LEVEL_LOCAL = 0,
122     NJS_LEVEL_CLOSURE,
123     NJS_LEVEL_GLOBAL,
124     NJS_LEVEL_STATIC,
125     NJS_LEVEL_TEMP,
126     NJS_LEVEL_MAX
127 } njs_level_type_t;
128 
129 
130 struct njs_vm_s {
131     /* njs_vm_t must be aligned to njs_value_t due to scratch value. */
132     njs_value_t              retval;
133 
134     njs_arr_t                *paths;
135     njs_arr_t                *protos;
136 
137     njs_arr_t                *scope_absolute;
138     njs_value_t              **levels[NJS_LEVEL_MAX];
139     size_t                   global_items;
140 
141     njs_external_ptr_t       external;
142 
143     njs_native_frame_t       *top_frame;
144     njs_frame_t              *active_frame;
145 
146     njs_rbtree_t             *variables_hash;
147     njs_lvlhsh_t             keywords_hash;
148     njs_lvlhsh_t             values_hash;
149 
150     njs_arr_t                *modules;
151     njs_lvlhsh_t             modules_hash;
152 
153     uint32_t                 event_id;
154     njs_lvlhsh_t             events_hash;
155     njs_queue_t              posted_events;
156     njs_queue_t              promise_events;
157 
158     njs_vm_opt_t             options;
159 
160     /*
161      * The prototypes and constructors arrays must be together because
162      * they are copied from njs_vm_shared_t by single memcpy()
163      * in njs_builtin_objects_clone().
164      */
165     njs_object_prototype_t   prototypes[NJS_OBJ_TYPE_MAX];
166     njs_function_t           constructors[NJS_OBJ_TYPE_MAX];
167 
168     njs_function_t           *hooks[NJS_HOOK_MAX];
169 
170     njs_mp_t                 *mem_pool;
171 
172     u_char                   *start;
173     size_t                   stack_size;
174 
175     njs_vm_shared_t          *shared;
176 
177     njs_regex_generic_ctx_t  *regex_generic_ctx;
178     njs_regex_compile_ctx_t  *regex_compile_ctx;
179     njs_regex_match_data_t   *single_match_data;
180 
181     njs_array_t              *promise_reason;
182 
183     njs_parser_scope_t       *global_scope;
184 
185     /*
186      * MemoryError is statically allocated immutable Error object
187      * with the InternalError prototype.
188      */
189     njs_object_t             memory_error_object;
190 
191     njs_object_t             string_object;
192     njs_object_t             global_object;
193     njs_value_t              global_value;
194 
195     njs_arr_t                *codes;  /* of njs_vm_code_t */
196     njs_arr_t                *functions_name_cache;
197 
198     njs_trace_t              trace;
199     njs_random_t             random;
200 
201     uint64_t                 symbol_generator;
202 };
203 
204 
205 typedef struct {
206     uint32_t                 offset;
207     uint32_t                 line;
208 } njs_vm_line_num_t;
209 
210 
211 typedef struct {
212     u_char                   *start;
213     u_char                   *end;
214     njs_str_t                file;
215     njs_str_t                name;
216     njs_arr_t                *lines;  /* of njs_vm_line_num_t */
217 } njs_vm_code_t;
218 
219 
220 struct njs_vm_shared_s {
221     njs_lvlhsh_t             keywords_hash;
222     njs_lvlhsh_t             values_hash;
223 
224     njs_lvlhsh_t             array_instance_hash;
225     njs_lvlhsh_t             string_instance_hash;
226     njs_lvlhsh_t             function_instance_hash;
227     njs_lvlhsh_t             async_function_instance_hash;
228     njs_lvlhsh_t             arrow_instance_hash;
229     njs_lvlhsh_t             arguments_object_instance_hash;
230     njs_lvlhsh_t             regexp_instance_hash;
231 
232     njs_lvlhsh_t             modules_hash;
233 
234     njs_lvlhsh_t             env_hash;
235 
236     njs_object_t             string_object;
237     njs_object_t             objects[NJS_OBJECT_MAX];
238 
239     njs_exotic_slots_t       global_slots;
240 
241     /*
242      * The prototypes and constructors arrays must be togther because they are
243      * copied to njs_vm_t by single memcpy() in njs_builtin_objects_clone().
244      */
245     njs_object_prototype_t   prototypes[NJS_OBJ_TYPE_MAX];
246     njs_function_t           constructors[NJS_OBJ_TYPE_MAX];
247 
248     njs_regexp_pattern_t     *empty_regexp_pattern;
249 };
250 
251 
252 void njs_vm_scopes_restore(njs_vm_t *vm, njs_native_frame_t *frame,
253     njs_native_frame_t *previous);
254 
255 njs_int_t njs_builtin_objects_create(njs_vm_t *vm);
256 njs_int_t njs_builtin_objects_clone(njs_vm_t *vm, njs_value_t *global);
257 njs_int_t njs_builtin_match_native_function(njs_vm_t *vm,
258     njs_function_t *function, njs_str_t *name);
259 
260 njs_arr_t *njs_vm_completions(njs_vm_t *vm, njs_str_t *expression);
261 
262 void *njs_lvlhsh_alloc(void *data, size_t size);
263 void njs_lvlhsh_free(void *data, void *p, size_t size);
264 
265 
266 extern const njs_str_t    njs_entry_main;
267 extern const njs_str_t    njs_entry_module;
268 extern const njs_str_t    njs_entry_native;
269 extern const njs_str_t    njs_entry_unknown;
270 extern const njs_str_t    njs_entry_anonymous;
271 
272 extern const njs_lvlhsh_proto_t  njs_object_hash_proto;
273 
274 
275 #endif /* _NJS_VM_H_INCLUDED_ */
276