1 /*
2  * QuickJS Javascript Engine
3  *
4  * Copyright (c) 2017-2021 Fabrice Bellard
5  * Copyright (c) 2017-2021 Charlie Gordon
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #ifndef QUICKJS_H
26 #define QUICKJS_H
27 
28 #include <stdio.h>
29 #include <stdint.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #if defined(__GNUC__) || defined(__clang__)
36 #define js_likely(x)          __builtin_expect(!!(x), 1)
37 #define js_unlikely(x)        __builtin_expect(!!(x), 0)
38 #define js_force_inline       inline __attribute__((always_inline))
39 #define __js_printf_like(f, a)   __attribute__((format(printf, f, a)))
40 #else
41 #define js_likely(x)     (x)
42 #define js_unlikely(x)   (x)
43 #if defined(_MSC_VER)
44 #define js_force_inline  __forceinline
45 #else
46 #define js_force_inline  inline
47 #endif
48 #define __js_printf_like(a, b)
49 #endif
50 
51 #define JS_BOOL int
52 
53 typedef struct JSRuntime JSRuntime;
54 typedef struct JSContext JSContext;
55 typedef struct JSObject JSObject;
56 typedef struct JSClass JSClass;
57 typedef uint32_t JSClassID;
58 typedef uint32_t JSAtom;
59 
60 #if INTPTR_MAX >= INT64_MAX
61 #define JS_PTR64
62 #define JS_PTR64_DEF(a) a
63 #else
64 #define JS_PTR64_DEF(a)
65 #endif
66 
67 #ifndef JS_PTR64
68 #define JS_NAN_BOXING
69 #endif
70 
71 enum {
72     /* all tags with a reference count are negative */
73     JS_TAG_FIRST       = -11, /* first negative tag */
74     JS_TAG_BIG_DECIMAL = -11,
75     JS_TAG_BIG_INT     = -10,
76     JS_TAG_BIG_FLOAT   = -9,
77     JS_TAG_SYMBOL      = -8,
78     JS_TAG_STRING      = -7,
79     JS_TAG_MODULE      = -3, /* used internally */
80     JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
81     JS_TAG_OBJECT      = -1,
82 
83     JS_TAG_INT         = 0,
84     JS_TAG_BOOL        = 1,
85     JS_TAG_NULL        = 2,
86     JS_TAG_UNDEFINED   = 3,
87     JS_TAG_UNINITIALIZED = 4,
88     JS_TAG_CATCH_OFFSET = 5,
89     JS_TAG_EXCEPTION   = 6,
90     JS_TAG_FLOAT64     = 7,
91     /* any larger tag is FLOAT64 if JS_NAN_BOXING */
92 };
93 
94 typedef struct JSRefCountHeader {
95     int ref_count;
96 } JSRefCountHeader;
97 
98 #define JS_FLOAT64_NAN NAN
99 
100 #ifdef CONFIG_CHECK_JSVALUE
101 /* JSValue consistency : it is not possible to run the code in this
102    mode, but it is useful to detect simple reference counting
103    errors. It would be interesting to modify a static C analyzer to
104    handle specific annotations (clang has such annotations but only
105    for objective C) */
106 typedef struct __JSValue *JSValue;
107 typedef const struct __JSValue *JSValueConst;
108 #define JS_VALUE_CONST_CAST(cVal) (JSValue)cVal
109 #define JS_VALUE_MAKE_CONST(val) (JSValueConst)val
110 
111 #define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf)
112 /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
113 #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
114 #define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4)
115 #define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v)
116 #define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v)
117 #define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf)
118 
119 #define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag))
120 #define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag))
121 
122 #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
123 
124 #define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1)
125 
__JS_NewFloat64(JSContext * ctx,double d)126 static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
127 {
128     return JS_MKVAL(JS_TAG_FLOAT64, (int)d);
129 }
130 
JS_VALUE_IS_NAN(JSValue v)131 static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
132 {
133     return 0;
134 }
135 
136 #elif defined(JS_NAN_BOXING)
137 
138 typedef uint64_t JSValue;
139 
140 #define JSValueConst JSValue
141 #define JS_VALUE_CONST_CAST(cVal) cVal
142 #define JS_VALUE_MAKE_CONST(val) val
143 
144 #define JS_VALUE_GET_TAG(v) (int)((v) >> 32)
145 #define JS_VALUE_GET_INT(v) (int)(v)
146 #define JS_VALUE_GET_BOOL(v) (int)(v)
147 #define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v)
148 
149 #define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val))
150 #define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr))
151 
152 #define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */
153 
JS_VALUE_GET_FLOAT64(JSValue v)154 static inline double JS_VALUE_GET_FLOAT64(JSValue v)
155 {
156     union {
157         JSValue v;
158         double d;
159     } u;
160     u.v = v;
161     u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32;
162     return u.d;
163 }
164 
165 #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
166 
__JS_NewFloat64(JSContext * ctx,double d)167 static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
168 {
169     union {
170         double d;
171         uint64_t u64;
172     } u;
173     JSValue v;
174     u.d = d;
175     /* normalize NaN */
176     if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000))
177         v = JS_NAN;
178     else
179         v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32);
180     return v;
181 }
182 
183 #define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST))
184 
185 /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
JS_VALUE_GET_NORM_TAG(JSValue v)186 static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
187 {
188     uint32_t tag;
189     tag = JS_VALUE_GET_TAG(v);
190     if (JS_TAG_IS_FLOAT64(tag))
191         return JS_TAG_FLOAT64;
192     else
193         return tag;
194 }
195 
JS_VALUE_IS_NAN(JSValue v)196 static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
197 {
198     uint32_t tag;
199     tag = JS_VALUE_GET_TAG(v);
200     return tag == (JS_NAN >> 32);
201 }
202 
203 #else /* !JS_NAN_BOXING */
204 
205 typedef union JSValueUnion {
206     int32_t int32;
207     double float64;
208     uintptr_t ptr;
209 } JSValueUnion;
210 
211 typedef struct JSValue {
212     JSValueUnion u;
213     int64_t tag;
214 } JSValue;
215 
216 #define JSValueConst JSValue
217 #define JS_VALUE_CONST_CAST(cVal) cVal
218 #define JS_VALUE_MAKE_CONST(val) val
219 
220 #define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag)
221 /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
222 #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
223 #define JS_VALUE_GET_INT(v) ((v).u.int32)
224 #define JS_VALUE_GET_BOOL(v) ((v).u.int32)
225 #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
226 #define JS_VALUE_GET_PTR(v) ((void *)((v).u.ptr))
227 
228 #define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
229 #define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = (uintptr_t)(void *)p }, tag }
230 
231 #if defined(__cplusplus)
232 #undef JS_MKVAL
233 #undef JS_MKPTR
234 #define with(T, ...)\
235 	([&]{ T t{}; __VA_ARGS__; return t; }())
236 #define JS_MKVAL(tag, val) JSValue{ with(JSValueUnion, t.int32 = val), tag }
237 #define JS_MKPTR(tag, p) JSValue{ with(JSValueUnion, t.ptr = (uintptr_t)(void *)p), tag }
238 #endif
239 
240 #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
241 
242 #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
243 
__JS_NewFloat64(JSContext * ctx,double d)244 static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
245 {
246     JSValue v;
247     v.tag = JS_TAG_FLOAT64;
248     v.u.float64 = d;
249     return v;
250 }
251 
JS_VALUE_IS_NAN(JSValue v)252 static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
253 {
254     union {
255         double d;
256         uint64_t u64;
257     } u;
258     if (v.tag != JS_TAG_FLOAT64)
259         return 0;
260     u.d = v.u.float64;
261     return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000;
262 }
263 
264 #endif /* !JS_NAN_BOXING */
265 
266 #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
267 #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
268 
269 #define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v))
270 #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
271 #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
272 
273 /* special values */
274 #define JS_NULL      JS_MKVAL(JS_TAG_NULL, 0)
275 #define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0)
276 #define JS_FALSE     JS_MKVAL(JS_TAG_BOOL, 0)
277 #define JS_TRUE      JS_MKVAL(JS_TAG_BOOL, 1)
278 #define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0)
279 #define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0)
280 
281 /* flags for object properties */
282 #define JS_PROP_CONFIGURABLE  (1 << 0)
283 #define JS_PROP_WRITABLE      (1 << 1)
284 #define JS_PROP_ENUMERABLE    (1 << 2)
285 #define JS_PROP_C_W_E         (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)
286 #define JS_PROP_LENGTH        (1 << 3) /* used internally in Arrays */
287 #define JS_PROP_TMASK         (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */
288 #define JS_PROP_NORMAL         (0 << 4)
289 #define JS_PROP_GETSET         (1 << 4)
290 #define JS_PROP_VARREF         (2 << 4) /* used internally */
291 #define JS_PROP_AUTOINIT       (3 << 4) /* used internally */
292 
293 /* flags for JS_DefineProperty */
294 #define JS_PROP_HAS_SHIFT        8
295 #define JS_PROP_HAS_CONFIGURABLE (1 << 8)
296 #define JS_PROP_HAS_WRITABLE     (1 << 9)
297 #define JS_PROP_HAS_ENUMERABLE   (1 << 10)
298 #define JS_PROP_HAS_GET          (1 << 11)
299 #define JS_PROP_HAS_SET          (1 << 12)
300 #define JS_PROP_HAS_VALUE        (1 << 13)
301 
302 /* throw an exception if false would be returned
303    (JS_DefineProperty/JS_SetProperty) */
304 #define JS_PROP_THROW            (1 << 14)
305 /* throw an exception if false would be returned in strict mode
306    (JS_SetProperty) */
307 #define JS_PROP_THROW_STRICT     (1 << 15)
308 
309 #define JS_PROP_NO_ADD           (1 << 16) /* internal use */
310 #define JS_PROP_NO_EXOTIC        (1 << 17) /* internal use */
311 
312 #define JS_DEFAULT_STACK_SIZE (256 * 1024)
313 
314 /* JS_Eval() flags */
315 #define JS_EVAL_TYPE_GLOBAL   (0 << 0) /* global code (default) */
316 #define JS_EVAL_TYPE_MODULE   (1 << 0) /* module code */
317 #define JS_EVAL_TYPE_DIRECT   (2 << 0) /* direct call (internal use) */
318 #define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */
319 #define JS_EVAL_TYPE_MASK     (3 << 0)
320 
321 #define JS_EVAL_FLAG_STRICT   (1 << 3) /* force 'strict' mode */
322 #define JS_EVAL_FLAG_STRIP    (1 << 4) /* force 'strip' mode */
323 /* compile but do not run. The result is an object with a
324    JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
325    with JS_EvalFunction(). */
326 #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
327 /* don't include the stack frames before this eval in the Error() backtraces */
328 #define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
329 
330 typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
331 typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
332 typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data);
333 
334 typedef struct JSMallocState {
335     size_t malloc_count;
336     size_t malloc_size;
337     size_t malloc_limit;
338     void *opaque; /* user opaque */
339 } JSMallocState;
340 
341 typedef struct JSMallocFunctions {
342     void *(*js_malloc)(JSMallocState *s, size_t size);
343     void (*js_free)(JSMallocState *s, void *ptr);
344     void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
345     size_t (*js_malloc_usable_size)(const void *ptr);
346 } JSMallocFunctions;
347 
348 typedef struct JSGCObjectHeader JSGCObjectHeader;
349 
350 JSRuntime *JS_NewRuntime(void);
351 /* info lifetime must exceed that of rt */
352 void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
353 void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
354 void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
355 /* use 0 to disable maximum stack size check */
356 void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
357 /* should be called when changing thread to update the stack top value
358    used to check stack overflow. */
359 void JS_UpdateStackTop(JSRuntime *rt);
360 JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
361 void JS_FreeRuntime(JSRuntime *rt);
362 void JS_FreeRuntime2(JSRuntime *rt, void (*gc_leak_handler)(const char* msg));
363 void *JS_GetRuntimeOpaque(JSRuntime *rt);
364 void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque);
365 typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp);
366 void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
367 void JS_RunGC(JSRuntime *rt);
368 JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
369 
370 JSContext *JS_NewContext(JSRuntime *rt);
371 void JS_FreeContext(JSContext *s);
372 JSContext *JS_DupContext(JSContext *ctx);
373 void *JS_GetContextOpaque(JSContext *ctx);
374 void JS_SetContextOpaque(JSContext *ctx, void *opaque);
375 JSRuntime *JS_GetRuntime(JSContext *ctx);
376 void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
377 JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
378 
379 /* the following functions are used to select the intrinsic object to
380    save memory */
381 JSContext *JS_NewContextRaw(JSRuntime *rt);
382 void JS_AddIntrinsicBaseObjects(JSContext *ctx);
383 void JS_AddIntrinsicDate(JSContext *ctx);
384 void JS_AddIntrinsicEval(JSContext *ctx);
385 void JS_AddIntrinsicStringNormalize(JSContext *ctx);
386 void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
387 void JS_AddIntrinsicRegExp(JSContext *ctx);
388 void JS_AddIntrinsicJSON(JSContext *ctx);
389 void JS_AddIntrinsicProxy(JSContext *ctx);
390 void JS_AddIntrinsicMapSet(JSContext *ctx);
391 void JS_AddIntrinsicTypedArrays(JSContext *ctx);
392 void JS_AddIntrinsicPromise(JSContext *ctx);
393 void JS_AddIntrinsicBigInt(JSContext *ctx);
394 void JS_AddIntrinsicBigFloat(JSContext *ctx);
395 void JS_AddIntrinsicBigDecimal(JSContext *ctx);
396 /* enable operator overloading */
397 void JS_AddIntrinsicOperators(JSContext *ctx);
398 /* enable "use math" */
399 void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable);
400 
401 JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
402                                  int argc, JSValueConst *argv);
403 
404 void *js_malloc_rt(JSRuntime *rt, size_t size);
405 void js_free_rt(JSRuntime *rt, void *ptr);
406 void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
407 size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
408 void *js_mallocz_rt(JSRuntime *rt, size_t size);
409 
410 void *js_malloc(JSContext *ctx, size_t size);
411 void js_free(JSContext *ctx, void *ptr);
412 void *js_realloc(JSContext *ctx, void *ptr, size_t size);
413 size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
414 void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
415 void *js_mallocz(JSContext *ctx, size_t size);
416 char *js_strdup(JSContext *ctx, const char *str);
417 char *js_strndup(JSContext *ctx, const char *s, size_t n);
418 
419 typedef struct JSMemoryUsage {
420     int64_t malloc_size, malloc_limit, memory_used_size;
421     int64_t malloc_count;
422     int64_t memory_used_count;
423     int64_t atom_count, atom_size;
424     int64_t str_count, str_size;
425     int64_t obj_count, obj_size;
426     int64_t prop_count, prop_size;
427     int64_t shape_count, shape_size;
428     int64_t js_func_count, js_func_size, js_func_code_size;
429     int64_t js_func_pc2line_count, js_func_pc2line_size;
430     int64_t c_func_count, array_count;
431     int64_t fast_array_count, fast_array_elements;
432     int64_t binary_object_count, binary_object_size;
433 } JSMemoryUsage;
434 
435 void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
436 void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
437 
438 /* atom support */
439 #define JS_ATOM_NULL 0
440 
441 JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
442 JSAtom JS_NewAtom(JSContext *ctx, const char *str);
443 JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
444 JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
445 void JS_FreeAtom(JSContext *ctx, JSAtom v);
446 void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
447 JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
448 JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
449 const char *JS_AtomToCString(JSContext *ctx, JSAtom atom);
450 JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val);
451 
452 /* object class support */
453 
454 typedef struct JSPropertyEnum {
455     JS_BOOL is_enumerable;
456     JSAtom atom;
457 } JSPropertyEnum;
458 
459 typedef struct JSPropertyDescriptor {
460     int flags;
461     JSValue value;
462     JSValue getter;
463     JSValue setter;
464 } JSPropertyDescriptor;
465 
466 typedef struct JSClassExoticMethods {
467     /* Return -1 if exception (can only happen in case of Proxy object),
468        FALSE if the property does not exists, TRUE if it exists. If 1 is
469        returned, the property descriptor 'desc' is filled if != NULL. */
470     int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
471                              JSValueConst obj, JSAtom prop);
472     /* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
473        -1 if exception. The 'is_enumerable' field is ignored.
474     */
475     int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
476                                   uint32_t *plen,
477                                   JSValueConst obj);
478     /* return < 0 if exception, or TRUE/FALSE */
479     int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
480     /* return < 0 if exception or TRUE/FALSE */
481     int (*define_own_property)(JSContext *ctx, JSValueConst this_obj,
482                                JSAtom prop, JSValueConst val,
483                                JSValueConst getter, JSValueConst setter,
484                                int flags);
485     /* The following methods can be emulated with the previous ones,
486        so they are usually not needed */
487     /* return < 0 if exception or TRUE/FALSE */
488     int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
489     JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
490                             JSValueConst receiver);
491     /* return < 0 if exception or TRUE/FALSE */
492     int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
493                         JSValueConst value, JSValueConst receiver, int flags);
494 } JSClassExoticMethods;
495 
496 typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
497 typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val,
498                            JS_MarkFunc *mark_func);
499 #define JS_CALL_FLAG_CONSTRUCTOR (1 << 0)
500 typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj,
501                             JSValueConst this_val, int argc, JSValueConst *argv,
502                             int flags);
503 
504 typedef struct JSClassDef {
505     const char *class_name;
506     JSClassFinalizer *finalizer;
507     JSClassGCMark *gc_mark;
508     /* if call != NULL, the object is a function. If (flags &
509        JS_CALL_FLAG_CONSTRUCTOR) != 0, the function is called as a
510        constructor. In this case, 'this_val' is new.target. A
511        constructor call only happens if the object constructor bit is
512        set (see JS_SetConstructorBit()). */
513     JSClassCall *call;
514     /* XXX: suppress this indirection ? It is here only to save memory
515        because only a few classes need these methods */
516     JSClassExoticMethods *exotic;
517 } JSClassDef;
518 
519 JSClassID JS_NewClassID(JSClassID *pclass_id);
520 int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
521 int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
522 
523 /* value handling */
524 
JS_NewBool(JSContext * ctx,JS_BOOL val)525 static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
526 {
527     return JS_MKVAL(JS_TAG_BOOL, (val != 0));
528 }
529 
JS_NewInt32(JSContext * ctx,int32_t val)530 static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
531 {
532     return JS_MKVAL(JS_TAG_INT, val);
533 }
534 
JS_NewCatchOffset(JSContext * ctx,int32_t val)535 static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
536 {
537     return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
538 }
539 
JS_NewInt64(JSContext * ctx,int64_t val)540 static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
541 {
542     JSValue v;
543     if (val == (int32_t)val) {
544         v = JS_NewInt32(ctx, (int32_t)val);
545     } else {
546         v = __JS_NewFloat64(ctx, (double)val);
547     }
548     return v;
549 }
550 
JS_NewUint32(JSContext * ctx,uint32_t val)551 static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
552 {
553     JSValue v;
554     if (val <= 0x7fffffff) {
555         v = JS_NewInt32(ctx, val);
556     } else {
557         v = __JS_NewFloat64(ctx, val);
558     }
559     return v;
560 }
561 
562 JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
563 JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
564 
JS_NewFloat64(JSContext * ctx,double d)565 static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d)
566 {
567     JSValue v;
568     int32_t val;
569     union {
570         double d;
571         uint64_t u;
572     } u, t;
573     u.d = d;
574     val = (int32_t)d;
575     t.d = val;
576     /* -0 cannot be represented as integer, so we compare the bit
577         representation */
578     if (u.u == t.u) {
579         v = JS_MKVAL(JS_TAG_INT, val);
580     } else {
581         v = __JS_NewFloat64(ctx, d);
582     }
583     return v;
584 }
585 
JS_IsNumber(JSValueConst v)586 static inline JS_BOOL JS_IsNumber(JSValueConst v)
587 {
588     int tag = JS_VALUE_GET_TAG(v);
589     return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag);
590 }
591 
JS_IsBigInt(JSContext * ctx,JSValueConst v)592 static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v)
593 {
594     int tag = JS_VALUE_GET_TAG(v);
595     return tag == JS_TAG_BIG_INT;
596 }
597 
JS_IsBigFloat(JSValueConst v)598 static inline JS_BOOL JS_IsBigFloat(JSValueConst v)
599 {
600     int tag = JS_VALUE_GET_TAG(v);
601     return tag == JS_TAG_BIG_FLOAT;
602 }
603 
JS_IsBigDecimal(JSValueConst v)604 static inline JS_BOOL JS_IsBigDecimal(JSValueConst v)
605 {
606     int tag = JS_VALUE_GET_TAG(v);
607     return tag == JS_TAG_BIG_DECIMAL;
608 }
609 
JS_IsBool(JSValueConst v)610 static inline JS_BOOL JS_IsBool(JSValueConst v)
611 {
612     return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
613 }
614 
JS_IsNull(JSValueConst v)615 static inline JS_BOOL JS_IsNull(JSValueConst v)
616 {
617     return JS_VALUE_GET_TAG(v) == JS_TAG_NULL;
618 }
619 
JS_IsUndefined(JSValueConst v)620 static inline JS_BOOL JS_IsUndefined(JSValueConst v)
621 {
622     return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED;
623 }
624 
JS_IsException(JSValueConst v)625 static inline JS_BOOL JS_IsException(JSValueConst v)
626 {
627     return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION);
628 }
629 
JS_IsUninitialized(JSValueConst v)630 static inline JS_BOOL JS_IsUninitialized(JSValueConst v)
631 {
632     return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED);
633 }
634 
JS_IsString(JSValueConst v)635 static inline JS_BOOL JS_IsString(JSValueConst v)
636 {
637     return JS_VALUE_GET_TAG(v) == JS_TAG_STRING;
638 }
639 
JS_IsSymbol(JSValueConst v)640 static inline JS_BOOL JS_IsSymbol(JSValueConst v)
641 {
642     return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
643 }
644 
JS_IsObject(JSValueConst v)645 static inline JS_BOOL JS_IsObject(JSValueConst v)
646 {
647     return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
648 }
649 
650 JSValue JS_Throw(JSContext *ctx, JSValue obj);
651 JSValue JS_GetException(JSContext *ctx);
652 JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
653 void JS_ResetUncatchableError(JSContext *ctx);
654 JSValue JS_NewError(JSContext *ctx);
655 JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
656 JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
657 JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
658 JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
659 JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
660 JSValue JS_ThrowOutOfMemory(JSContext *ctx);
661 
662 void __JS_FreeValue(JSContext *ctx, JSValue v);
JS_FreeValue(JSContext * ctx,JSValue v)663 static inline void JS_FreeValue(JSContext *ctx, JSValue v)
664 {
665     if (JS_VALUE_HAS_REF_COUNT(v)) {
666         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
667         if (--p->ref_count <= 0) {
668             __JS_FreeValue(ctx, v);
669         }
670     }
671 }
672 void __JS_FreeValueRT(JSRuntime *rt, JSValue v);
JS_FreeValueRT(JSRuntime * rt,JSValue v)673 static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v)
674 {
675     if (JS_VALUE_HAS_REF_COUNT(v)) {
676         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
677         if (--p->ref_count <= 0) {
678             __JS_FreeValueRT(rt, v);
679         }
680     }
681 }
682 
JS_DupValue(JSContext * ctx,JSValueConst v)683 static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
684 {
685     if (JS_VALUE_HAS_REF_COUNT(v)) {
686         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
687         p->ref_count++;
688     }
689     return JS_VALUE_CONST_CAST(v);
690 }
691 
JS_DupValueRT(JSRuntime * rt,JSValueConst v)692 static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
693 {
694     if (JS_VALUE_HAS_REF_COUNT(v)) {
695         JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
696         p->ref_count++;
697     }
698     return JS_VALUE_CONST_CAST(v);
699 }
700 
701 int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
702 int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
JS_ToUint32(JSContext * ctx,uint32_t * pres,JSValueConst val)703 static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
704 {
705     return JS_ToInt32(ctx, (int32_t*)pres, val);
706 }
707 int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
708 int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
709 int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
710 /* return an exception if 'val' is a Number */
711 int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
712 /* same as JS_ToInt64() but allow BigInt */
713 int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val);
714 
715 JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
716 JSValue JS_NewString(JSContext *ctx, const char *str);
717 JSValue JS_NewAtomString(JSContext *ctx, const char *str);
718 JSValue JS_ToString(JSContext *ctx, JSValueConst val);
719 JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
720 const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8);
JS_ToCStringLen(JSContext * ctx,size_t * plen,JSValueConst val1)721 static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1)
722 {
723     return JS_ToCStringLen2(ctx, plen, val1, 0);
724 }
JS_ToCString(JSContext * ctx,JSValueConst val1)725 static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1)
726 {
727     return JS_ToCStringLen2(ctx, NULL, val1, 0);
728 }
729 void JS_FreeCString(JSContext *ctx, const char *ptr);
730 
731 JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id);
732 JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
733 JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
734 JSValue JS_NewObject(JSContext *ctx);
735 
736 JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
737 JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
738 JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val);
739 
740 JSValue JS_NewArray(JSContext *ctx);
741 int JS_IsArray(JSContext *ctx, JSValueConst val);
742 
743 JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
744                                JSAtom prop, JSValueConst receiver,
745                                JS_BOOL throw_ref_error);
JS_GetProperty(JSContext * ctx,JSValueConst this_obj,JSAtom prop)746 static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj,
747                                               JSAtom prop)
748 {
749     return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0);
750 }
751 JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
752                           const char *prop);
753 JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
754                              uint32_t idx);
755 
756 int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
757                            JSAtom prop, JSValue val,
758                            int flags);
JS_SetProperty(JSContext * ctx,JSValueConst this_obj,JSAtom prop,JSValue val)759 static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
760                                  JSAtom prop, JSValue val)
761 {
762     return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
763 }
764 int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
765                          uint32_t idx, JSValue val);
766 int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
767                         int64_t idx, JSValue val);
768 int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
769                       const char *prop, JSValue val);
770 int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop);
771 int JS_IsExtensible(JSContext *ctx, JSValueConst obj);
772 int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
773 int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
774 int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
775 JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val);
776 
777 #define JS_GPN_STRING_MASK  (1 << 0)
778 #define JS_GPN_SYMBOL_MASK  (1 << 1)
779 #define JS_GPN_PRIVATE_MASK (1 << 2)
780 /* only include the enumerable properties */
781 #define JS_GPN_ENUM_ONLY    (1 << 4)
782 /* set theJSPropertyEnum.is_enumerable field */
783 #define JS_GPN_SET_ENUM     (1 << 5)
784 
785 int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
786                            uint32_t *plen, JSValueConst obj, int flags);
787 int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
788                       JSValueConst obj, JSAtom prop);
789 
790 JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
791                 int argc, JSValueConst *argv);
792 JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
793                   int argc, JSValueConst *argv);
794 JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
795                            int argc, JSValueConst *argv);
796 JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
797                             JSValueConst new_target,
798                             int argc, JSValueConst *argv);
799 JS_BOOL JS_DetectModule(const char *input, size_t input_len);
800 /* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
801 JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
802                 const char *filename, int eval_flags);
803 /* same as JS_Eval() but with an explicit 'this_obj' parameter */
804 JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
805                     const char *input, size_t input_len,
806                     const char *filename, int eval_flags);
807 JSValue JS_GetGlobalObject(JSContext *ctx);
808 int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
809 int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
810                       JSAtom prop, JSValueConst val,
811                       JSValueConst getter, JSValueConst setter, int flags);
812 int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
813                            JSAtom prop, JSValue val, int flags);
814 int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,
815                                  uint32_t idx, JSValue val, int flags);
816 int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
817                               const char *prop, JSValue val, int flags);
818 int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
819                             JSAtom prop, JSValue getter, JSValue setter,
820                             int flags);
821 void JS_SetOpaque(JSValue obj, void *opaque);
822 void *JS_GetOpaque(JSValueConst obj, JSClassID class_id);
823 void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id);
824 
825 /* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */
826 JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
827                      const char *filename);
828 #define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */
829 JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
830                       const char *filename, int flags);
831 JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
832                          JSValueConst replacer, JSValueConst space0);
833 
834 typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr);
835 JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
836                           JSFreeArrayBufferDataFunc *free_func, void *opaque,
837                           JS_BOOL is_shared);
838 JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
839 void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
840 uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
841 JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj,
842                                size_t *pbyte_offset,
843                                size_t *pbyte_length,
844                                size_t *pbytes_per_element);
845 typedef struct {
846     void *(*sab_alloc)(void *opaque, size_t size);
847     void (*sab_free)(void *opaque, void *ptr);
848     void (*sab_dup)(void *opaque, void *ptr);
849     void *sab_opaque;
850 } JSSharedArrayBufferFunctions;
851 void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,
852                                       const JSSharedArrayBufferFunctions *sf);
853 
854 JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
855 
856 /* is_handled = TRUE means that the rejection is handled */
857 typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise,
858                                            JSValueConst reason,
859                                            JS_BOOL is_handled, void *opaque);
860 void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque);
861 
862 /* return != 0 if the JS code needs to be interrupted */
863 typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
864 void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
865 /* if can_block is TRUE, Atomics.wait() can be used */
866 void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
867 /* set the [IsHTMLDDA] internal slot */
868 void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj);
869 
870 typedef struct JSModuleDef JSModuleDef;
871 
872 /* return the module specifier (allocated with js_malloc()) or NULL if
873    exception */
874 typedef char *JSModuleNormalizeFunc(JSContext *ctx,
875                                     const char *module_base_name,
876                                     const char *module_name, void *opaque);
877 typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
878                                         const char *module_name, void *opaque);
879 
880 /* module_normalize = NULL is allowed and invokes the default module
881    filename normalizer */
882 void JS_SetModuleLoaderFunc(JSRuntime *rt,
883                             JSModuleNormalizeFunc *module_normalize,
884                             JSModuleLoaderFunc *module_loader, void *opaque);
885 /* return the import.meta object of a module */
886 JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
887 JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
888 
889 /* JS Job support */
890 
891 typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv);
892 int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv);
893 
894 JS_BOOL JS_IsJobPending(JSRuntime *rt);
895 int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
896 
897 /* Object Writer/Reader (currently only used to handle precompiled code) */
898 #define JS_WRITE_OBJ_BYTECODE  (1 << 0) /* allow function/module */
899 #define JS_WRITE_OBJ_BSWAP     (1 << 1) /* byte swapped output */
900 #define JS_WRITE_OBJ_SAB       (1 << 2) /* allow SharedArrayBuffer */
901 #define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
902                                            encode arbitrary object
903                                            graph */
904 uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
905                         int flags);
906 uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
907                          int flags, uint8_t ***psab_tab, size_t *psab_tab_len);
908 
909 #define JS_READ_OBJ_BYTECODE  (1 << 0) /* allow function/module */
910 #define JS_READ_OBJ_ROM_DATA  (1 << 1) /* avoid duplicating 'buf' data */
911 #define JS_READ_OBJ_SAB       (1 << 2) /* allow SharedArrayBuffer */
912 #define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
913 JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
914                       int flags);
915 /* instantiate and evaluate a bytecode function. Only used when
916    reading a script or module with JS_ReadObject() */
917 JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
918 /* load the dependencies of the module 'obj'. Useful when JS_ReadObject()
919    returns a module. */
920 int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
921 
922 /* only exported for os.Worker() */
923 JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels);
924 /* only exported for os.Worker() */
925 JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,
926                           const char *filename);
927 
928 /* C function definition */
929 typedef enum JSCFunctionEnum {  /* XXX: should rename for namespace isolation */
930     JS_CFUNC_generic,
931     JS_CFUNC_generic_magic,
932     JS_CFUNC_constructor,
933     JS_CFUNC_constructor_magic,
934     JS_CFUNC_constructor_or_func,
935     JS_CFUNC_constructor_or_func_magic,
936     JS_CFUNC_f_f,
937     JS_CFUNC_f_f_f,
938     JS_CFUNC_getter,
939     JS_CFUNC_setter,
940     JS_CFUNC_getter_magic,
941     JS_CFUNC_setter_magic,
942     JS_CFUNC_iterator_next,
943 } JSCFunctionEnum;
944 
945 typedef union JSCFunctionType {
946     JSCFunction *generic;
947     JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
948     JSCFunction *constructor;
949     JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic);
950     JSCFunction *constructor_or_func;
951     double (*f_f)(double);
952     double (*f_f_f)(double, double);
953     JSValue (*getter)(JSContext *ctx, JSValueConst this_val);
954     JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val);
955     JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic);
956     JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic);
957     JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val,
958                              int argc, JSValueConst *argv, int *pdone, int magic);
959 } JSCFunctionType;
960 
961 JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
962                          const char *name,
963                          int length, JSCFunctionEnum cproto, int magic);
964 JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
965                             int length, int magic, int data_len,
966                             JSValueConst *data);
967 
JS_NewCFunction(JSContext * ctx,JSCFunction * func,const char * name,int length)968 static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
969                                       int length)
970 {
971     return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
972 }
973 
JS_NewCFunctionMagic(JSContext * ctx,JSCFunctionMagic * func,const char * name,int length,JSCFunctionEnum cproto,int magic)974 static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
975                                            const char *name,
976                                            int length, JSCFunctionEnum cproto, int magic)
977 {
978     return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
979 }
980 void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj,
981                        JSValueConst proto);
982 
983 /* C property definition */
984 
985 typedef struct JSCFunctionListEntry {
986     const char *name;
987     uint8_t prop_flags;
988     uint8_t def_type;
989     int16_t magic;
990     union {
991         struct {
992             uint8_t length; /* XXX: should move outside union */
993             uint8_t cproto; /* XXX: should move outside union */
994             JSCFunctionType cfunc;
995         } func;
996         struct {
997             JSCFunctionType get;
998             JSCFunctionType set;
999         } getset;
1000         struct {
1001             const char *name;
1002             int base;
1003         } alias;
1004         struct {
1005             const struct JSCFunctionListEntry *tab;
1006             int len;
1007         } prop_list;
1008         const char *str;
1009         int32_t i32;
1010         int64_t i64;
1011         double f64;
1012     } u;
1013 } JSCFunctionListEntry;
1014 
1015 #define JS_DEF_CFUNC          0
1016 #define JS_DEF_CGETSET        1
1017 #define JS_DEF_CGETSET_MAGIC  2
1018 #define JS_DEF_PROP_STRING    3
1019 #define JS_DEF_PROP_INT32     4
1020 #define JS_DEF_PROP_INT64     5
1021 #define JS_DEF_PROP_DOUBLE    6
1022 #define JS_DEF_PROP_UNDEFINED 7
1023 #define JS_DEF_OBJECT         8
1024 #define JS_DEF_ALIAS          9
1025 
1026 /* Note: c++ does not like nested designators */
1027 #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
1028 #define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } }
1029 #define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } }
1030 #define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } }
1031 #define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } }
1032 #define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u = { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } }
1033 #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } }
1034 #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } }
1035 #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } }
1036 #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } }
1037 #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } }
1038 #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } }
1039 #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } }
1040 #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } }
1041 
1042 void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
1043                                 const JSCFunctionListEntry *tab,
1044                                 int len);
1045 
1046 /* C module definition */
1047 
1048 typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m);
1049 
1050 JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
1051                            JSModuleInitFunc *func);
1052 /* can only be called before the module is instantiated */
1053 int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
1054 int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
1055                            const JSCFunctionListEntry *tab, int len);
1056 /* can only be called after the module is instantiated */
1057 int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
1058                        JSValue val);
1059 int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
1060                            const JSCFunctionListEntry *tab, int len);
1061 
1062 #undef js_unlikely
1063 #undef js_force_inline
1064 
1065 #ifdef __cplusplus
1066 } /* extern "C" { */
1067 #endif
1068 
1069 #endif /* QUICKJS_H */
1070