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