894 lines
32 KiB
C
894 lines
32 KiB
C
/*
|
|
* QuickJS Javascript Engine
|
|
*
|
|
* Copyright (c) 2017-2021 Fabrice Bellard
|
|
* Copyright (c) 2017-2021 Charlie Gordon
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
#ifndef QUICKJS_H
|
|
#define QUICKJS_H
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#if defined(__GNUC__) || defined(__clang__)
|
|
#define js_likely(x) __builtin_expect(!!(x), 1)
|
|
#define js_unlikely(x) __builtin_expect(!!(x), 0)
|
|
#define js_force_inline inline __attribute__((always_inline))
|
|
#define __js_printf_like(f, a) __attribute__((format(printf, f, a)))
|
|
#else
|
|
#define js_likely(x) (x)
|
|
#define js_unlikely(x) (x)
|
|
#define js_force_inline inline
|
|
#define __js_printf_like(a, b)
|
|
#endif
|
|
|
|
#define JS_BOOL int
|
|
|
|
typedef struct JSRuntime JSRuntime;
|
|
typedef struct JSContext JSContext;
|
|
typedef struct JSClass JSClass;
|
|
typedef uint32_t JSClassID;
|
|
typedef uint32_t JSAtom;
|
|
|
|
#if INTPTR_MAX >= INT64_MAX
|
|
#define JS_PTR64
|
|
#define JS_PTR64_DEF(a) a
|
|
#else
|
|
#define JS_PTR64_DEF(a)
|
|
#endif
|
|
|
|
#ifndef JS_PTR64
|
|
#define JS_NAN_BOXING
|
|
#endif
|
|
|
|
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
|
|
#define JS_LIMB_BITS 64
|
|
#else
|
|
#define JS_LIMB_BITS 32
|
|
#endif
|
|
|
|
#define JS_SHORT_BIG_INT_BITS JS_LIMB_BITS
|
|
|
|
enum {
|
|
/* all tags with a reference count are negative */
|
|
JS_TAG_FIRST = -10, /* first negative tag */
|
|
JS_TAG_SYMBOL = -9,
|
|
JS_TAG_STRING = -8,
|
|
JS_TAG_STRING_ROPE = -7,
|
|
JS_TAG_ARRAY = -6, /* intrinsic array type */
|
|
JS_TAG_MODULE = -3, /* used internally */
|
|
JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
|
|
JS_TAG_OBJECT = -1,
|
|
|
|
JS_TAG_INT = 0,
|
|
JS_TAG_BOOL = 1,
|
|
JS_TAG_NULL = 2,
|
|
JS_TAG_UNINITIALIZED = 4,
|
|
JS_TAG_CATCH_OFFSET = 5,
|
|
JS_TAG_EXCEPTION = 6,
|
|
JS_TAG_SHORT_BIG_INT = 7,
|
|
JS_TAG_FLOAT64 = 8,
|
|
/* any larger tag is FLOAT64 if JS_NAN_BOXING */
|
|
};
|
|
|
|
typedef struct JSRefCountHeader {
|
|
int ref_count;
|
|
} JSRefCountHeader;
|
|
|
|
#define JS_FLOAT64_NAN NAN
|
|
|
|
#ifdef CONFIG_CHECK_JSVALUE
|
|
/* JSValue consistency : it is not possible to run the code in this
|
|
mode, but it is useful to detect simple reference counting
|
|
errors. It would be interesting to modify a static C analyzer to
|
|
handle specific annotations (clang has such annotations but only
|
|
for objective C) */
|
|
typedef struct __JSValue *JSValue;
|
|
typedef const struct __JSValue *JSValueConst;
|
|
|
|
#define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf)
|
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
|
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
|
|
#define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4)
|
|
#define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v)
|
|
#define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v)
|
|
#define JS_VALUE_GET_SHORT_BIG_INT(v) JS_VALUE_GET_INT(v)
|
|
#define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf)
|
|
|
|
#define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag))
|
|
#define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag))
|
|
|
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
|
|
|
|
#define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1)
|
|
|
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
|
{
|
|
return JS_MKVAL(JS_TAG_FLOAT64, (int)d);
|
|
}
|
|
|
|
static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(JS_NAN_BOXING)
|
|
|
|
typedef uint64_t JSValue;
|
|
|
|
#define JSValueConst JSValue
|
|
|
|
#define JS_VALUE_GET_TAG(v) (int)((v) >> 32)
|
|
#define JS_VALUE_GET_INT(v) (int)(v)
|
|
#define JS_VALUE_GET_BOOL(v) (int)(v)
|
|
#define JS_VALUE_GET_SHORT_BIG_INT(v) (int)(v)
|
|
#define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v)
|
|
|
|
#define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val))
|
|
#define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr))
|
|
|
|
#define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */
|
|
|
|
static inline double JS_VALUE_GET_FLOAT64(JSValue v)
|
|
{
|
|
union {
|
|
JSValue v;
|
|
double d;
|
|
} u;
|
|
u.v = v;
|
|
u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32;
|
|
return u.d;
|
|
}
|
|
|
|
#define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
|
|
|
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
|
{
|
|
union {
|
|
double d;
|
|
uint64_t u64;
|
|
} u;
|
|
JSValue v;
|
|
u.d = d;
|
|
/* normalize NaN */
|
|
if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000))
|
|
v = JS_NAN;
|
|
else
|
|
v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32);
|
|
return v;
|
|
}
|
|
|
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST))
|
|
|
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
|
static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
|
|
{
|
|
uint32_t tag;
|
|
tag = JS_VALUE_GET_TAG(v);
|
|
if (JS_TAG_IS_FLOAT64(tag))
|
|
return JS_TAG_FLOAT64;
|
|
else
|
|
return tag;
|
|
}
|
|
|
|
static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
|
|
{
|
|
uint32_t tag;
|
|
tag = JS_VALUE_GET_TAG(v);
|
|
return tag == (JS_NAN >> 32);
|
|
}
|
|
|
|
#else /* !JS_NAN_BOXING */
|
|
|
|
typedef union JSValueUnion {
|
|
int32_t int32;
|
|
double float64;
|
|
void *ptr;
|
|
#if JS_SHORT_BIG_INT_BITS == 32
|
|
int32_t short_big_int;
|
|
#else
|
|
int64_t short_big_int;
|
|
#endif
|
|
} JSValueUnion;
|
|
|
|
typedef struct JSValue {
|
|
JSValueUnion u;
|
|
int64_t tag;
|
|
} JSValue;
|
|
|
|
#define JSValueConst JSValue
|
|
|
|
#define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag)
|
|
/* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
|
|
#define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
|
|
#define JS_VALUE_GET_INT(v) ((v).u.int32)
|
|
#define JS_VALUE_GET_BOOL(v) ((v).u.int32)
|
|
#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
|
|
#define JS_VALUE_GET_SHORT_BIG_INT(v) ((v).u.short_big_int)
|
|
#define JS_VALUE_GET_PTR(v) ((v).u.ptr)
|
|
|
|
#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
|
|
#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
|
|
|
|
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
|
|
|
|
#define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
|
|
|
|
static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
|
|
{
|
|
JSValue v;
|
|
v.tag = JS_TAG_FLOAT64;
|
|
v.u.float64 = d;
|
|
return v;
|
|
}
|
|
|
|
static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v)
|
|
{
|
|
union {
|
|
double d;
|
|
uint64_t u64;
|
|
} u;
|
|
if (v.tag != JS_TAG_FLOAT64)
|
|
return 0;
|
|
u.d = v.u.float64;
|
|
return (u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000;
|
|
}
|
|
|
|
#endif /* !JS_NAN_BOXING */
|
|
|
|
#define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
|
|
#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)))
|
|
|
|
#define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
|
|
|
|
/* special values */
|
|
#define JS_NULL JS_MKVAL(JS_TAG_NULL, 0)
|
|
#define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0)
|
|
#define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1)
|
|
#define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0)
|
|
#define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0)
|
|
|
|
/* flags for object properties - simplified model:
|
|
- No per-property writable/configurable (use stone() for immutability)
|
|
- Text keys are enumerable, object keys are not */
|
|
#define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, VARREF */
|
|
#define JS_PROP_NORMAL (0 << 4)
|
|
#define JS_PROP_VARREF (2 << 4) /* used internally for closures */
|
|
|
|
#ifndef JS_DEFAULT_STACK_SIZE
|
|
#define JS_DEFAULT_STACK_SIZE (1024 * 1024)
|
|
#endif
|
|
|
|
/* JS_Eval() flags */
|
|
#define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */
|
|
#define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */
|
|
#define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */
|
|
#define JS_EVAL_TYPE_MASK (3 << 0)
|
|
|
|
/* compile but do not run. The result is an object with a
|
|
JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
|
|
with JS_EvalFunction(). */
|
|
#define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
|
|
/* don't include the stack frames before this eval in the Error() backtraces */
|
|
#define JS_EVAL_FLAG_BACKTRACE_BARRIER (1 << 6)
|
|
|
|
typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
|
|
typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
|
typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data);
|
|
|
|
typedef struct JSMallocState {
|
|
size_t malloc_count;
|
|
size_t malloc_size;
|
|
size_t malloc_limit;
|
|
void *opaque; /* user opaque */
|
|
} JSMallocState;
|
|
|
|
typedef struct JSMallocFunctions {
|
|
void *(*js_malloc)(JSMallocState *s, size_t size);
|
|
void (*js_free)(JSMallocState *s, void *ptr);
|
|
void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
|
|
size_t (*js_malloc_usable_size)(const void *ptr);
|
|
} JSMallocFunctions;
|
|
|
|
typedef struct JSGCObjectHeader JSGCObjectHeader;
|
|
|
|
JSValue JS_Stone(JSContext *ctx, JSValueConst this_val);
|
|
int JS_IsStone(JSContext *ctx, JSValueConst val);
|
|
|
|
JSRuntime *JS_NewRuntime(void);
|
|
/* info lifetime must exceed that of rt */
|
|
void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
|
|
void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
|
|
void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
|
|
/* use 0 to disable maximum stack size check */
|
|
void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
|
|
/* should be called when changing thread to update the stack top value
|
|
used to check stack overflow. */
|
|
void JS_UpdateStackTop(JSRuntime *rt);
|
|
JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
|
|
void JS_FreeRuntime(JSRuntime *rt);
|
|
void *JS_GetRuntimeOpaque(JSRuntime *rt);
|
|
void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque);
|
|
typedef void JS_MarkFunc(JSRuntime *rt, JSGCObjectHeader *gp);
|
|
void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
|
|
void JS_RunGC(JSRuntime *rt);
|
|
JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
|
|
|
|
JSContext *JS_NewContext(JSRuntime *rt);
|
|
void JS_FreeContext(JSContext *s);
|
|
JSContext *JS_DupContext(JSContext *ctx);
|
|
JSContext *JS_GetContext(JSRuntime *rt);
|
|
void *JS_GetContextOpaque(JSContext *ctx);
|
|
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
|
|
JSRuntime *JS_GetRuntime(JSContext *ctx);
|
|
void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
|
|
JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
|
|
|
|
/* the following functions are used to select the intrinsic object to
|
|
save memory */
|
|
JSContext *JS_NewContextRaw(JSRuntime *rt);
|
|
void JS_AddIntrinsicBaseObjects(JSContext *ctx);
|
|
void JS_AddIntrinsicEval(JSContext *ctx);
|
|
void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
|
|
void JS_AddIntrinsicRegExp(JSContext *ctx);
|
|
void JS_AddIntrinsicJSON(JSContext *ctx);
|
|
|
|
JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
|
|
int argc, JSValueConst *argv);
|
|
|
|
void *js_malloc_rt(JSRuntime *rt, size_t size);
|
|
void js_free_rt(JSRuntime *rt, void *ptr);
|
|
void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
|
|
size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
|
|
void *js_mallocz_rt(JSRuntime *rt, size_t size);
|
|
|
|
void *js_malloc(JSContext *ctx, size_t size);
|
|
void js_free(JSContext *ctx, void *ptr);
|
|
void *js_realloc(JSContext *ctx, void *ptr, size_t size);
|
|
size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
|
|
void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
|
|
void *js_mallocz(JSContext *ctx, size_t size);
|
|
char *js_strdup(JSContext *ctx, const char *str);
|
|
char *js_strndup(JSContext *ctx, const char *s, size_t n);
|
|
|
|
typedef struct JSMemoryUsage {
|
|
int64_t malloc_size, malloc_limit, memory_used_size;
|
|
int64_t malloc_count;
|
|
int64_t memory_used_count;
|
|
int64_t atom_count, atom_size;
|
|
int64_t str_count, str_size;
|
|
int64_t obj_count, obj_size;
|
|
int64_t prop_count, prop_size;
|
|
int64_t shape_count, shape_size;
|
|
int64_t js_func_count, js_func_size, js_func_code_size;
|
|
int64_t js_func_pc2line_count, js_func_pc2line_size;
|
|
int64_t c_func_count, array_count;
|
|
int64_t fast_array_count, fast_array_elements;
|
|
int64_t binary_object_count, binary_object_size;
|
|
} JSMemoryUsage;
|
|
|
|
void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
|
|
void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
|
|
|
|
/* atom support */
|
|
#define JS_ATOM_NULL 0
|
|
|
|
JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
|
|
JSAtom JS_NewAtom(JSContext *ctx, const char *str);
|
|
JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
|
|
JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
|
|
void JS_FreeAtom(JSContext *ctx, JSAtom v);
|
|
void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
|
|
JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
|
|
JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
|
|
const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom);
|
|
static inline const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)
|
|
{
|
|
return JS_AtomToCStringLen(ctx, NULL, atom);
|
|
}
|
|
JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val);
|
|
|
|
/* object class support */
|
|
|
|
typedef struct JSPropertyEnum {
|
|
JS_BOOL is_enumerable;
|
|
JSAtom atom;
|
|
} JSPropertyEnum;
|
|
|
|
typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
|
|
typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val,
|
|
JS_MarkFunc *mark_func);
|
|
typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj,
|
|
JSValueConst this_val, int argc, JSValueConst *argv,
|
|
int flags);
|
|
|
|
typedef struct JSClassDef {
|
|
const char *class_name;
|
|
JSClassFinalizer *finalizer;
|
|
JSClassGCMark *gc_mark;
|
|
/* if call != NULL, the object is a function */
|
|
JSClassCall *call;
|
|
} JSClassDef;
|
|
|
|
#define JS_INVALID_CLASS_ID 0
|
|
JSClassID JS_NewClassID(JSClassID *pclass_id);
|
|
/* Returns the class ID if `v` is an object, otherwise returns JS_INVALID_CLASS_ID. */
|
|
JSClassID JS_GetClassID(JSValue v);
|
|
int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
|
|
int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
|
|
|
|
extern JSClassID js_class_id_alloc;
|
|
|
|
/* value handling */
|
|
|
|
static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
|
|
{
|
|
return JS_MKVAL(JS_TAG_BOOL, (val != 0));
|
|
}
|
|
|
|
static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
|
|
{
|
|
return JS_MKVAL(JS_TAG_INT, val);
|
|
}
|
|
|
|
static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
|
|
{
|
|
return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
|
|
}
|
|
|
|
static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val)
|
|
{
|
|
JSValue v;
|
|
if (val == (int32_t)val) {
|
|
v = JS_NewInt32(ctx, val);
|
|
} else {
|
|
v = __JS_NewFloat64(ctx, val);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val)
|
|
{
|
|
JSValue v;
|
|
if (val <= 0x7fffffff) {
|
|
v = JS_NewInt32(ctx, val);
|
|
} else {
|
|
v = __JS_NewFloat64(ctx, val);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d)
|
|
{
|
|
int32_t val;
|
|
union {
|
|
double d;
|
|
uint64_t u;
|
|
} u, t;
|
|
if (d >= INT32_MIN && d <= INT32_MAX) {
|
|
u.d = d;
|
|
val = (int32_t)d;
|
|
t.d = val;
|
|
/* -0 cannot be represented as integer, so we compare the bit
|
|
representation */
|
|
if (u.u == t.u)
|
|
return JS_MKVAL(JS_TAG_INT, val);
|
|
}
|
|
return __JS_NewFloat64(ctx, d);
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsNumber(JSValueConst v)
|
|
{
|
|
int tag = JS_VALUE_GET_TAG(v);
|
|
return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag);
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsBool(JSValueConst v)
|
|
{
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsNull(JSValueConst v)
|
|
{
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG_NULL;
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsException(JSValueConst v)
|
|
{
|
|
return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION);
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsUninitialized(JSValueConst v)
|
|
{
|
|
return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED);
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsString(JSValueConst v)
|
|
{
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG_STRING ||
|
|
JS_VALUE_GET_TAG(v) == JS_TAG_STRING_ROPE;
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsSymbol(JSValueConst v)
|
|
{
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
|
|
}
|
|
|
|
static inline JS_BOOL JS_IsObject(JSValueConst v)
|
|
{
|
|
return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
|
|
}
|
|
int JS_IsArray(JSContext *ctx, JSValueConst val);
|
|
JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
|
|
|
|
// Fundamental
|
|
int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres);
|
|
|
|
JSValue JS_Throw(JSContext *ctx, JSValue obj);
|
|
void JS_SetUncatchableException(JSContext *ctx, JS_BOOL flag);
|
|
JSValue JS_GetException(JSContext *ctx);
|
|
JS_BOOL JS_HasException(JSContext *ctx);
|
|
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
|
|
JSValue JS_NewError(JSContext *ctx);
|
|
JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
|
|
JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
|
|
JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
|
|
JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
|
|
JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
|
|
JSValue JS_ThrowOutOfMemory(JSContext *ctx);
|
|
|
|
void __JS_FreeValue(JSContext *ctx, JSValue v);
|
|
static inline void JS_FreeValue(JSContext *ctx, JSValue v)
|
|
{
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
|
if (--p->ref_count <= 0) {
|
|
__JS_FreeValue(ctx, v);
|
|
}
|
|
}
|
|
}
|
|
void __JS_FreeValueRT(JSRuntime *rt, JSValue v);
|
|
static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v)
|
|
{
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
|
if (--p->ref_count <= 0) {
|
|
__JS_FreeValueRT(rt, v);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
|
|
{
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
|
p->ref_count++;
|
|
}
|
|
return (JSValue)v;
|
|
}
|
|
|
|
static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
|
|
{
|
|
if (JS_VALUE_HAS_REF_COUNT(v)) {
|
|
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
|
|
p->ref_count++;
|
|
}
|
|
return (JSValue)v;
|
|
}
|
|
|
|
JS_BOOL JS_StrictEq(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
|
JS_BOOL JS_SameValue(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
|
JS_BOOL JS_SameValueZero(JSContext *ctx, JSValueConst op1, JSValueConst op2);
|
|
|
|
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
|
|
int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
|
|
static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
|
|
{
|
|
return JS_ToInt32(ctx, (int32_t*)pres, val);
|
|
}
|
|
int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom);
|
|
int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
|
|
int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
|
|
int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
|
|
/* return an exception if 'val' is a Number */
|
|
|
|
JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
|
|
static inline JSValue JS_NewString(JSContext *ctx, const char *str)
|
|
{
|
|
return JS_NewStringLen(ctx, str, strlen(str));
|
|
}
|
|
JSValue JS_NewAtomString(JSContext *ctx, const char *str);
|
|
JSValue JS_ToString(JSContext *ctx, JSValueConst val);
|
|
JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
|
|
const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8);
|
|
static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1)
|
|
{
|
|
return JS_ToCStringLen2(ctx, plen, val1, 0);
|
|
}
|
|
static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1)
|
|
{
|
|
return JS_ToCStringLen2(ctx, NULL, val1, 0);
|
|
}
|
|
void JS_FreeCString(JSContext *ctx, const char *ptr);
|
|
|
|
JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id);
|
|
JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
|
|
JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
|
|
JSValue JS_NewObject(JSContext *ctx);
|
|
|
|
JSValue JS_NewArray(JSContext *ctx);
|
|
JSValue JS_NewArrayLen(JSContext *ctx, uint32_t len);
|
|
int JS_ArrayPush(JSContext *ctx, JSValueConst obj, JSValueConst val);
|
|
JSValue JS_ArrayPop(JSContext *ctx, JSValueConst obj);
|
|
|
|
JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
|
|
JSAtom prop, JSValueConst receiver,
|
|
JS_BOOL throw_ref_error);
|
|
static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj,
|
|
JSAtom prop)
|
|
{
|
|
return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0);
|
|
}
|
|
|
|
// For records
|
|
JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop);
|
|
int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, const char *prop, JSValue val);
|
|
int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop, JSValue val);
|
|
JSValue JS_GetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key);
|
|
int JS_SetPropertyKey(JSContext *ctx, JSValueConst this_obj, JSValueConst key, JSValue val);
|
|
|
|
// Must be an array
|
|
JSValue JS_GetPropertyNumber(JSContext *ctx, JSValueConst this_obj, int idx);
|
|
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx);
|
|
int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj, uint32_t idx, JSValue val);
|
|
int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj, int64_t idx, JSValue val);
|
|
|
|
int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop);
|
|
int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop);
|
|
JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val);
|
|
|
|
/* Get Own Property Names flags */
|
|
#define JS_GPN_STRING_MASK (1 << 0)
|
|
#define JS_GPN_SYMBOL_MASK (1 << 1)
|
|
#define JS_GPN_PRIVATE_MASK (1 << 2)
|
|
#define JS_GPN_ENUM_ONLY (1 << 4)
|
|
#define JS_GPN_SET_ENUM (1 << 5)
|
|
|
|
int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
|
|
uint32_t *plen, JSValueConst obj, int flags);
|
|
void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab,
|
|
uint32_t len);
|
|
|
|
JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
|
|
int argc, JSValueConst *argv);
|
|
JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
|
|
int argc, JSValueConst *argv);
|
|
/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */
|
|
JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
|
|
const char *filename, int eval_flags);
|
|
/* same as JS_Eval() but with an explicit 'this_obj' parameter */
|
|
JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
|
|
const char *input, size_t input_len,
|
|
const char *filename, int eval_flags);
|
|
JSValue JS_GetGlobalObject(JSContext *ctx);
|
|
void JS_SetOpaque(JSValue obj, void *opaque);
|
|
void *JS_GetOpaque(JSValueConst obj, JSClassID class_id);
|
|
void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id);
|
|
void *JS_GetAnyOpaque(JSValueConst obj, JSClassID *class_id);
|
|
|
|
/* 'buf' must be zero terminated i.e. buf[buf_len] = '\0'. */
|
|
JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
|
|
const char *filename);
|
|
#define JS_PARSE_JSON_EXT (1 << 0) /* allow extended JSON */
|
|
JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,
|
|
const char *filename, int flags);
|
|
JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,
|
|
JSValueConst replacer, JSValueConst space0);
|
|
|
|
/* return != 0 if the JS code needs to be interrupted */
|
|
typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
|
|
void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
|
|
/* select which debug info is stripped from the compiled code */
|
|
#define JS_STRIP_SOURCE (1 << 0) /* strip source code */
|
|
#define JS_STRIP_DEBUG (1 << 1) /* strip all debug info including source code */
|
|
void JS_SetStripInfo(JSRuntime *rt, int flags);
|
|
int JS_GetStripInfo(JSRuntime *rt);
|
|
|
|
/* Object Writer/Reader (currently only used to handle precompiled code) */
|
|
#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
|
#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
|
|
#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
|
|
#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
|
|
encode arbitrary object
|
|
graph */
|
|
uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
|
|
int flags);
|
|
uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
|
|
int flags, uint8_t ***psab_tab, size_t *psab_tab_len);
|
|
|
|
#define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
|
#define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */
|
|
#define JS_READ_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
|
|
#define JS_READ_OBJ_REFERENCE (1 << 3) /* allow object references */
|
|
JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
|
|
int flags);
|
|
/* instantiate and evaluate a bytecode function. Only used when
|
|
reading a script or module with JS_ReadObject() */
|
|
JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
|
|
|
|
/* C function definition */
|
|
typedef enum JSCFunctionEnum {
|
|
JS_CFUNC_generic,
|
|
JS_CFUNC_generic_magic,
|
|
JS_CFUNC_f_f,
|
|
JS_CFUNC_f_f_f,
|
|
} JSCFunctionEnum;
|
|
|
|
typedef union JSCFunctionType {
|
|
JSCFunction *generic;
|
|
JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
|
|
double (*f_f)(double);
|
|
double (*f_f_f)(double, double);
|
|
} JSCFunctionType;
|
|
|
|
JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
|
|
const char *name,
|
|
int length, JSCFunctionEnum cproto, int magic);
|
|
JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
|
|
int length, int magic, int data_len,
|
|
JSValueConst *data);
|
|
|
|
static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
|
|
int length)
|
|
{
|
|
return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
|
|
}
|
|
|
|
static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
|
|
const char *name,
|
|
int length, JSCFunctionEnum cproto, int magic)
|
|
{
|
|
return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
|
|
}
|
|
|
|
/* C property definition */
|
|
|
|
typedef struct JSCFunctionListEntry {
|
|
const char *name;
|
|
uint8_t prop_flags;
|
|
uint8_t def_type;
|
|
int16_t magic;
|
|
union {
|
|
struct {
|
|
uint8_t length; /* XXX: should move outside union */
|
|
uint8_t cproto; /* XXX: should move outside union */
|
|
JSCFunctionType cfunc;
|
|
} func;
|
|
struct {
|
|
const char *name;
|
|
int base;
|
|
} alias;
|
|
struct {
|
|
const struct JSCFunctionListEntry *tab;
|
|
int len;
|
|
} prop_list;
|
|
const char *str;
|
|
int32_t i32;
|
|
int64_t i64;
|
|
double f64;
|
|
} u;
|
|
} JSCFunctionListEntry;
|
|
|
|
#define JS_DEF_CFUNC 0
|
|
#define JS_DEF_PROP_STRING 3
|
|
#define JS_DEF_PROP_INT32 4
|
|
#define JS_DEF_PROP_INT64 5
|
|
#define JS_DEF_PROP_DOUBLE 6
|
|
#define JS_DEF_PROP_UNDEFINED 7
|
|
#define JS_DEF_OBJECT 8
|
|
#define JS_DEF_ALIAS 9
|
|
|
|
/* Note: c++ does not like nested designators */
|
|
#define JS_CFUNC_DEF(name, length, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } }
|
|
#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } }
|
|
#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, 0, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } }
|
|
#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, 0, JS_DEF_CFUNC, magic, .u = { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } }
|
|
#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u = { .str = cstr } }
|
|
#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u = { .i32 = val } }
|
|
#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u = { .i64 = val } }
|
|
#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u = { .f64 = val } }
|
|
#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u = { .i32 = 0 } }
|
|
#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u = { .prop_list = { tab, len } } }
|
|
#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } }
|
|
#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } }
|
|
|
|
int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
|
|
const JSCFunctionListEntry *tab,
|
|
int len);
|
|
|
|
/* debug value output */
|
|
|
|
typedef struct {
|
|
JS_BOOL show_hidden : 8; /* only show enumerable properties */
|
|
JS_BOOL raw_dump : 8; /* avoid doing autoinit and avoid any malloc() call (for internal use) */
|
|
uint32_t max_depth; /* recurse up to this depth, 0 = no limit */
|
|
uint32_t max_string_length; /* print no more than this length for
|
|
strings, 0 = no limit */
|
|
uint32_t max_item_count; /* print no more than this count for
|
|
arrays or objects, 0 = no limit */
|
|
} JSPrintValueOptions;
|
|
|
|
typedef void JSPrintValueWrite(void *opaque, const char *buf, size_t len);
|
|
|
|
void JS_PrintValueSetDefaultOptions(JSPrintValueOptions *options);
|
|
void JS_PrintValueRT(JSRuntime *rt, JSPrintValueWrite *write_func, void *write_opaque,
|
|
JSValueConst val, const JSPrintValueOptions *options);
|
|
void JS_PrintValue(JSContext *ctx, JSPrintValueWrite *write_func, void *write_opaque,
|
|
JSValueConst val, const JSPrintValueOptions *options);
|
|
|
|
typedef struct js_debug {
|
|
const char *name; // nameof function
|
|
const char *what;
|
|
const char *source; // source code of function
|
|
size_t srclen;
|
|
const char *filename; // name of file function is in
|
|
int nparams;
|
|
int vararg;
|
|
int line; // line the function is on
|
|
int param_n;
|
|
int closure_n;
|
|
uint32_t unique; // a unique identifier for this function
|
|
} js_debug;
|
|
|
|
void js_debug_info(JSContext *js, JSValue fn, js_debug *dbg);
|
|
void free_js_debug_info(JSContext *js, js_debug *dbg);
|
|
|
|
typedef void (*js_hook)(JSContext*, int type, js_debug *dbg, void *user);
|
|
#define JS_HOOK_CALL 1
|
|
#define JS_HOOK_RET 2
|
|
#define JS_HOOK_CYCLE 4
|
|
#define JS_HOOK_GC 8
|
|
void js_debug_sethook(JSContext *ctx, js_hook, int type, void *user);
|
|
|
|
uint32_t js_debugger_stack_depth(JSContext *ctx);
|
|
JSValue js_debugger_backtrace_fns(JSContext *ctx, const uint8_t *cur_pc);
|
|
JSValue js_debugger_closure_variables(JSContext *ctx, JSValue fn);
|
|
JSValue js_debugger_local_variables(JSContext *ctx, int stack_index);
|
|
void js_debugger_set_closure_variable(JSContext *js, JSValue fn, JSValue var_name, JSValue val);
|
|
JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc);
|
|
JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn);
|
|
JSValue js_debugger_fn_bytecode(JSContext *js, JSValue fn);
|
|
void *js_debugger_val_address(JSContext *js, JSValue val);
|
|
|
|
#undef js_unlikely
|
|
#undef js_force_inline
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" { */
|
|
#endif
|
|
|
|
#endif /* QUICKJS_H */
|