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