diff options
Diffstat (limited to 'src/shared/quickjs/quickjs.h')
-rw-r--r-- | src/shared/quickjs/quickjs.h | 1100 |
1 files changed, 603 insertions, 497 deletions
diff --git a/src/shared/quickjs/quickjs.h b/src/shared/quickjs/quickjs.h index 3a22f5b7b..55215ee4f 100644 --- a/src/shared/quickjs/quickjs.h +++ b/src/shared/quickjs/quickjs.h @@ -1,8 +1,10 @@ /* * QuickJS Javascript Engine * - * Copyright (c) 2017-2021 Fabrice Bellard - * Copyright (c) 2017-2021 Charlie Gordon + * Copyright (c) 2017-2024 Fabrice Bellard + * Copyright (c) 2017-2024 Charlie Gordon + * Copyright (c) 2023-2025 Ben Noordhuis + * Copyright (c) 2023-2025 Saúl Ibarra Corretgé * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,26 +27,43 @@ #ifndef QUICKJS_H #define QUICKJS_H +#include <stdbool.h> #include <stdio.h> #include <stdint.h> +#include <string.h> +#include <math.h> #ifdef __cplusplus extern "C" { #endif +#define QUICKJS_NG 1 + #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))) +#define JS_EXTERN __attribute__((visibility("default"))) #else -#define js_likely(x) (x) -#define js_unlikely(x) (x) #define js_force_inline inline -#define __js_printf_like(a, b) +#define JS_EXTERN /* nothing */ #endif -#define JS_BOOL int +/* Borrowed from Folly */ +#ifndef JS_PRINTF_FORMAT +#ifdef _MSC_VER +#include <sal.h> +#define JS_PRINTF_FORMAT _Printf_format_string_ +#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) +#else +#define JS_PRINTF_FORMAT +#if !defined(__clang__) && defined(__GNUC__) +#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ + __attribute__((format(gnu_printf, format_param, dots_param))) +#else +#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \ + __attribute__((format(printf, format_param, dots_param))) +#endif +#endif +#endif typedef struct JSRuntime JSRuntime; typedef struct JSContext JSContext; @@ -53,23 +72,23 @@ 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 +/* Unless documented otherwise, C string pointers (`char *` or `const char *`) + are assumed to verify these constraints: + - unless a length is passed separately, the string has a null terminator + - string contents is either pure ASCII or is UTF-8 encoded. + */ -#ifndef JS_PTR64 -#define JS_NAN_BOXING +/* Overridable purely for testing purposes; don't touch. */ +#ifndef JS_NAN_BOXING +#if INTPTR_MAX < INT64_MAX +#define JS_NAN_BOXING 1 /* Use NAN boxing for 32bit builds. */ +#endif #endif enum { /* all tags with a reference count are negative */ - JS_TAG_FIRST = -11, /* first negative tag */ - JS_TAG_BIG_DECIMAL = -11, - JS_TAG_BIG_INT = -10, - JS_TAG_BIG_FLOAT = -9, + JS_TAG_FIRST = -9, /* first negative tag */ + JS_TAG_BIG_INT = -9, JS_TAG_SYMBOL = -8, JS_TAG_STRING = -7, JS_TAG_MODULE = -3, /* used internally */ @@ -87,52 +106,12 @@ enum { /* any larger tag is FLOAT64 if JS_NAN_BOXING */ }; -typedef struct JSRefCountHeader { - int ref_count; -} JSRefCountHeader; - -#define JS_FLOAT64_NAN NAN +#define JSValueConst JSValue /* For backwards compatibility. */ -#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_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) +#if defined(JS_NAN_BOXING) && 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) @@ -156,9 +135,8 @@ static inline double JS_VALUE_GET_FLOAT64(JSValue v) #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32)) -static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) +static inline JSValue __JS_NewFloat64(double d) { - (void) ctx; union { double d; uint64_t u64; @@ -166,7 +144,7 @@ static inline JSValue __JS_NewFloat64(JSContext *ctx, double d) JSValue v; u.d = d; /* normalize NaN */ - if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000)) + if ((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000) v = JS_NAN; else v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32); @@ -186,7 +164,7 @@ static inline int JS_VALUE_GET_NORM_TAG(JSValue v) return tag; } -static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +static inline bool JS_VALUE_IS_NAN(JSValue v) { uint32_t tag; tag = JS_VALUE_GET_TAG(v); @@ -206,8 +184,6 @@ typedef struct JSValue { 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) @@ -216,26 +192,50 @@ typedef struct JSValue { #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64) #define JS_VALUE_GET_PTR(v) ((v).u.ptr) -JSValue mkVal(int32_t tag, int32_t val); -JSValue mkPtr(int32_t tag, void *p); - -#define JS_MKVAL(tag, val) mkVal(tag, val) -#define JS_MKPTR(tag, p) mkPtr(tag, p) +/* msvc doesn't understand designated initializers without /std:c++20 */ +#ifdef __cplusplus +static inline JSValue JS_MKPTR(int64_t tag, void *ptr) +{ + JSValue v; + v.u.ptr = ptr; + v.tag = tag; + return v; +} +static inline JSValue JS_MKVAL(int64_t tag, int32_t int32) +{ + JSValue v; + v.u.int32 = int32; + v.tag = tag; + return v; +} +static inline JSValue JS_MKNAN(void) +{ + JSValue v; + v.u.float64 = NAN; + v.tag = JS_TAG_FLOAT64; + return v; +} +/* provide as macros for consistency and backward compat reasons */ +#define JS_MKPTR(tag, ptr) JS_MKPTR(tag, ptr) +#define JS_MKVAL(tag, val) JS_MKVAL(tag, val) +#define JS_NAN JS_MKNAN() /* alas, not a constant expression */ +#else +#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag } +#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag } +#define JS_NAN (JSValue){ (JSValueUnion){ .float64 = NAN }, JS_TAG_FLOAT64 } +#endif #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) +static inline JSValue __JS_NewFloat64(double d) { - (void) ctx; JSValue v; v.tag = JS_TAG_FLOAT64; v.u.float64 = d; return v; } -static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) +static inline bool JS_VALUE_IS_NAN(JSValue v) { union { double d; @@ -253,7 +253,6 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #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_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v)) -#define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v)) #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST) /* special values */ @@ -294,8 +293,12 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #define JS_PROP_NO_ADD (1 << 16) /* internal use */ #define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */ +#define JS_PROP_DEFINE_PROPERTY (1 << 18) /* internal use */ +#define JS_PROP_REFLECT_DEFINE_PROPERTY (1 << 19) /* internal use */ -#define JS_DEFAULT_STACK_SIZE (256 * 1024) +#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) */ @@ -305,7 +308,7 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) #define JS_EVAL_TYPE_MASK (3 << 0) #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */ -#define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */ +#define JS_EVAL_FLAG_UNUSED (1 << 4) /* unused */ /* 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(). */ @@ -316,93 +319,127 @@ static inline JS_BOOL JS_VALUE_IS_NAN(JSValue v) promise. Only allowed with JS_EVAL_TYPE_GLOBAL */ #define JS_EVAL_FLAG_ASYNC (1 << 7) -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 JSValue JSCFunction(JSContext *ctx, JSValue this_val, int argc, JSValue *argv); +typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic); +typedef JSValue JSCFunctionData(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic, JSValue *func_data); 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); + void *(*js_calloc)(void *opaque, size_t count, size_t size); + void *(*js_malloc)(void *opaque, size_t size); + void (*js_free)(void *opaque, void *ptr); + void *(*js_realloc)(void *opaque, void *ptr, size_t size); size_t (*js_malloc_usable_size)(const void *ptr); } JSMallocFunctions; +// Debug trace system: the debug output will be produced to the dump stream (currently +// stdout) if dumps are enabled and JS_SetDumpFlags is invoked with the corresponding +// bit set. +#define JS_DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */ +#define JS_DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */ +#define JS_DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */ +#define JS_DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */ +#define JS_DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */ +#define JS_DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */ +#define JS_DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */ +#define JS_DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */ +#define JS_DUMP_FREE 0x200 /* dump every object free */ +#define JS_DUMP_GC 0x400 /* dump the occurrence of the automatic GC */ +#define JS_DUMP_GC_FREE 0x800 /* dump objects freed by the GC */ +#define JS_DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */ +#define JS_DUMP_PROMISE 0x2000 /* dump promise steps */ +#define JS_DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */ +#define JS_DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */ +#define JS_DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */ +#define JS_DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */ +#define JS_DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */ +#define JS_DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */ + +// Finalizers run in LIFO order at the very end of JS_FreeRuntime. +// Intended for cleanup of associated resources; the runtime itself +// is no longer usable. +typedef void JSRuntimeFinalizer(JSRuntime *rt, void *arg); + typedef struct JSGCObjectHeader JSGCObjectHeader; -JSRuntime *JS_NewRuntime(void); +JS_EXTERN 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); +JS_EXTERN void JS_SetRuntimeInfo(JSRuntime *rt, const char *info); +/* use 0 to disable memory limit */ +JS_EXTERN void JS_SetMemoryLimit(JSRuntime *rt, size_t limit); +JS_EXTERN void JS_SetDumpFlags(JSRuntime *rt, uint64_t flags); +JS_EXTERN uint64_t JS_GetDumpFlags(JSRuntime *rt); +JS_EXTERN size_t JS_GetGCThreshold(JSRuntime *rt); +JS_EXTERN 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); +JS_EXTERN 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); +JS_EXTERN void JS_UpdateStackTop(JSRuntime *rt); +JS_EXTERN JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque); +JS_EXTERN void JS_FreeRuntime(JSRuntime *rt); +JS_EXTERN void *JS_GetRuntimeOpaque(JSRuntime *rt); +JS_EXTERN void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque); +JS_EXTERN int JS_AddRuntimeFinalizer(JSRuntime *rt, + JSRuntimeFinalizer *finalizer, void *arg); 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); -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); +JS_EXTERN void JS_MarkValue(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); +JS_EXTERN void JS_RunGC(JSRuntime *rt); +JS_EXTERN bool JS_IsLiveObject(JSRuntime *rt, JSValue obj); + +JS_EXTERN JSContext *JS_NewContext(JSRuntime *rt); +JS_EXTERN void JS_FreeContext(JSContext *s); +JS_EXTERN JSContext *JS_DupContext(JSContext *ctx); +JS_EXTERN void *JS_GetContextOpaque(JSContext *ctx); +JS_EXTERN void JS_SetContextOpaque(JSContext *ctx, void *opaque); +JS_EXTERN JSRuntime *JS_GetRuntime(JSContext *ctx); +JS_EXTERN void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj); +JS_EXTERN JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id); +JS_EXTERN JSValue JS_GetFunctionProto(JSContext *ctx); /* 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_AddIntrinsicDate(JSContext *ctx); -void JS_AddIntrinsicEval(JSContext *ctx); -void JS_AddIntrinsicStringNormalize(JSContext *ctx); -void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); -void JS_AddIntrinsicRegExp(JSContext *ctx); -void JS_AddIntrinsicJSON(JSContext *ctx); -void JS_AddIntrinsicProxy(JSContext *ctx); -void JS_AddIntrinsicMapSet(JSContext *ctx); -void JS_AddIntrinsicTypedArrays(JSContext *ctx); -void JS_AddIntrinsicPromise(JSContext *ctx); -void JS_AddIntrinsicBigInt(JSContext *ctx); -void JS_AddIntrinsicBigFloat(JSContext *ctx); -void JS_AddIntrinsicBigDecimal(JSContext *ctx); -/* enable operator overloading */ -void JS_AddIntrinsicOperators(JSContext *ctx); -/* enable "use math" */ -void JS_EnableBignumExt(JSContext *ctx, JS_BOOL enable); - -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); +JS_EXTERN JSContext *JS_NewContextRaw(JSRuntime *rt); +JS_EXTERN void JS_AddIntrinsicBaseObjects(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicDate(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicEval(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicRegExp(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicJSON(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicProxy(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicMapSet(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicTypedArrays(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicPromise(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicBigInt(JSContext *ctx); +JS_EXTERN void JS_AddIntrinsicWeakRef(JSContext *ctx); +JS_EXTERN void JS_AddPerformance(JSContext *ctx); + +/* for equality comparisons and sameness */ +JS_EXTERN int JS_IsEqual(JSContext *ctx, JSValue op1, JSValue op2); +JS_EXTERN bool JS_IsStrictEqual(JSContext *ctx, JSValue op1, JSValue op2); +JS_EXTERN bool JS_IsSameValue(JSContext *ctx, JSValue op1, JSValue op2); +/* Similar to same-value equality, but +0 and -0 are considered equal. */ +JS_EXTERN bool JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2); + +/* Only used for running 262 tests. TODO(saghul) add build time flag. */ +JS_EXTERN JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv); + +JS_EXTERN void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size); +JS_EXTERN void *js_malloc_rt(JSRuntime *rt, size_t size); +JS_EXTERN void js_free_rt(JSRuntime *rt, void *ptr); +JS_EXTERN void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size); +JS_EXTERN size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr); +JS_EXTERN void *js_mallocz_rt(JSRuntime *rt, size_t size); + +JS_EXTERN void *js_calloc(JSContext *ctx, size_t count, size_t size); +JS_EXTERN void *js_malloc(JSContext *ctx, size_t size); +JS_EXTERN void js_free(JSContext *ctx, void *ptr); +JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size); +JS_EXTERN size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); +JS_EXTERN void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); +JS_EXTERN void *js_mallocz(JSContext *ctx, size_t size); +JS_EXTERN char *js_strdup(JSContext *ctx, const char *str); +JS_EXTERN char *js_strndup(JSContext *ctx, const char *s, size_t n); typedef struct JSMemoryUsage { int64_t malloc_size, malloc_limit, memory_used_size; @@ -420,27 +457,27 @@ typedef struct JSMemoryUsage { 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); +JS_EXTERN void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s); +JS_EXTERN 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_AtomToCString(JSContext *ctx, JSAtom atom); -JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val); +JS_EXTERN JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len); +JS_EXTERN JSAtom JS_NewAtom(JSContext *ctx, const char *str); +JS_EXTERN JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n); +JS_EXTERN JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); +JS_EXTERN void JS_FreeAtom(JSContext *ctx, JSAtom v); +JS_EXTERN void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); +JS_EXTERN JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); +JS_EXTERN JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); +JS_EXTERN const char *JS_AtomToCString(JSContext *ctx, JSAtom atom); +JS_EXTERN JSAtom JS_ValueToAtom(JSContext *ctx, JSValue val); /* object class support */ typedef struct JSPropertyEnum { - JS_BOOL is_enumerable; + bool is_enumerable; JSAtom atom; } JSPropertyEnum; @@ -453,44 +490,44 @@ typedef struct JSPropertyDescriptor { typedef struct JSClassExoticMethods { /* Return -1 if exception (can only happen in case of Proxy object), - FALSE if the property does not exists, TRUE if it exists. If 1 is + false if the property does not exists, true if it exists. If 1 is returned, the property descriptor 'desc' is filled if != NULL. */ int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); + JSValue obj, JSAtom prop); /* '*ptab' should hold the '*plen' property keys. Return 0 if OK, -1 if exception. The 'is_enumerable' field is ignored. */ int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab, uint32_t *plen, - JSValueConst obj); - /* return < 0 if exception, or TRUE/FALSE */ - int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop); - /* return < 0 if exception or TRUE/FALSE */ - int (*define_own_property)(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, + JSValue obj); + /* return < 0 if exception, or true/false */ + int (*delete_property)(JSContext *ctx, JSValue obj, JSAtom prop); + /* return < 0 if exception or true/false */ + int (*define_own_property)(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags); /* The following methods can be emulated with the previous ones, so they are usually not needed */ - /* return < 0 if exception or TRUE/FALSE */ - int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom); - JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst receiver); - /* return < 0 if exception or TRUE/FALSE */ - int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom, - JSValueConst value, JSValueConst receiver, int flags); + /* return < 0 if exception or true/false */ + int (*has_property)(JSContext *ctx, JSValue obj, JSAtom atom); + JSValue (*get_property)(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue receiver); + /* return < 0 if exception or true/false */ + int (*set_property)(JSContext *ctx, JSValue obj, JSAtom atom, + JSValue value, JSValue receiver, int flags); } JSClassExoticMethods; typedef void JSClassFinalizer(JSRuntime *rt, JSValue val); -typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val, +typedef void JSClassGCMark(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func); #define JS_CALL_FLAG_CONSTRUCTOR (1 << 0) -typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj, - JSValueConst this_val, int argc, JSValueConst *argv, +typedef JSValue JSClassCall(JSContext *ctx, JSValue func_obj, + JSValue this_val, int argc, JSValue *argv, int flags); typedef struct JSClassDef { - const char *class_name; + const char *class_name; /* pure ASCII only! */ JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; /* if call != NULL, the object is a function. If (flags & @@ -504,224 +541,246 @@ typedef struct JSClassDef { JSClassExoticMethods *exotic; } JSClassDef; +#define JS_EVAL_OPTIONS_VERSION 1 + +typedef struct JSEvalOptions { + int version; + int eval_flags; + const char *filename; + int line_num; + // can add new fields in ABI-compatible manner by incrementing JS_EVAL_OPTIONS_VERSION +} JSEvalOptions; + #define JS_INVALID_CLASS_ID 0 -JSClassID JS_NewClassID(JSClassID *pclass_id); +JS_EXTERN JSClassID JS_NewClassID(JSRuntime *rt, 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); +JS_EXTERN JSClassID JS_GetClassID(JSValue v); +JS_EXTERN int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def); +JS_EXTERN bool JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id); /* value handling */ -JSValue JS_NewBool(JSContext *ctx, JS_BOOL val); -JSValue JS_NewInt32(JSContext *ctx, int32_t val); -JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val); -JSValue JS_NewInt64(JSContext *ctx, int64_t val); -JSValue JS_NewUint32(JSContext *ctx, uint32_t val); -JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); -JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); +static js_force_inline JSValue JS_NewBool(JSContext *ctx, bool val) +{ + (void)&ctx; + return JS_MKVAL(JS_TAG_BOOL, (val != 0)); +} -JSValue JS_NewFloat64(JSContext *ctx, double d); +static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val) +{ + (void)&ctx; + return JS_MKVAL(JS_TAG_INT, val); +} -static inline JS_BOOL JS_IsNumber(JSValueConst v) +static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double val) { - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); + (void)&ctx; + return __JS_NewFloat64(val); } -static inline JS_BOOL JS_IsBigInt(JSContext *ctx, JSValueConst v) +static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val) { - (void) ctx; - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_INT; + (void)&ctx; + return JS_MKVAL(JS_TAG_CATCH_OFFSET, val); } -static inline JS_BOOL JS_IsBigFloat(JSValueConst v) +static js_force_inline JSValue JS_NewInt64(JSContext *ctx, int64_t val) { - int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_FLOAT; + JSValue v; + if (val >= INT32_MIN && val <= INT32_MAX) { + v = JS_NewInt32(ctx, (int32_t)val); + } else { + v = JS_NewFloat64(ctx, (double)val); + } + return v; } -static inline JS_BOOL JS_IsBigDecimal(JSValueConst v) +static js_force_inline JSValue JS_NewUint32(JSContext *ctx, uint32_t val) +{ + JSValue v; + if (val <= INT32_MAX) { + v = JS_NewInt32(ctx, (int32_t)val); + } else { + v = JS_NewFloat64(ctx, (double)val); + } + return v; +} + +JS_EXTERN JSValue JS_NewNumber(JSContext *ctx, double d); +JS_EXTERN JSValue JS_NewBigInt64(JSContext *ctx, int64_t v); +JS_EXTERN JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v); + +static inline bool JS_IsNumber(JSValue v) { int tag = JS_VALUE_GET_TAG(v); - return tag == JS_TAG_BIG_DECIMAL; + return tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag); +} + +static inline bool JS_IsBigInt(JSContext *ctx, JSValue v) +{ + (void)&ctx; + return JS_VALUE_GET_TAG(v) == JS_TAG_BIG_INT; } -static inline JS_BOOL JS_IsBool(JSValueConst v) +static inline bool JS_IsBool(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL; } -static inline JS_BOOL JS_IsNull(JSValueConst v) +static inline bool JS_IsNull(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_NULL; } -static inline JS_BOOL JS_IsUndefined(JSValueConst v) +static inline bool JS_IsUndefined(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED; } -static inline JS_BOOL JS_IsException(JSValueConst v) +static inline bool JS_IsException(JSValue v) { - return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION); + return JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION; } -static inline JS_BOOL JS_IsUninitialized(JSValueConst v) +static inline bool JS_IsUninitialized(JSValue v) { - return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED); + return JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED; } -static inline JS_BOOL JS_IsString(JSValueConst v) +static inline bool JS_IsString(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_STRING; } -static inline JS_BOOL JS_IsSymbol(JSValueConst v) +static inline bool JS_IsSymbol(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL; } -static inline JS_BOOL JS_IsObject(JSValueConst v) +static inline bool JS_IsObject(JSValue v) { return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT; } -JSValue JS_Throw(JSContext *ctx, JSValue obj); -JSValue JS_GetException(JSContext *ctx); -JS_BOOL JS_HasException(JSContext *ctx); -JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val); -void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, JS_BOOL flag); -void JS_ResetUncatchableError(JSContext *ctx); -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); - -#ifndef NDEBUG -void notifyRefCountIncrease(JSRefCountHeader *p); -void notifyRefCountDecrease(JSRefCountHeader *p); -#endif - -void JS_FreeValue(JSContext *ctx, JSValue v); -void JS_FreeValueRT(JSRuntime *rt, JSValue v); - -static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v) +JS_EXTERN JSValue JS_Throw(JSContext *ctx, JSValue obj); +JS_EXTERN JSValue JS_GetException(JSContext *ctx); +JS_EXTERN bool JS_HasException(JSContext *ctx); +JS_EXTERN JSValue JS_GetBacktrace(JSContext *ctx); +JS_EXTERN bool JS_IsError(JSContext *ctx, JSValue val); +JS_EXTERN bool JS_IsUncatchableError(JSContext* ctx, JSValue val); +JS_EXTERN void JS_SetUncatchableError(JSContext *ctx, JSValue val); +JS_EXTERN void JS_ClearUncatchableError(JSContext *ctx, JSValue val); +// Shorthand for: +// JSValue exc = JS_GetException(ctx); +// JS_ClearUncatchableError(ctx, exc); +// JS_Throw(ctx, exc); +JS_EXTERN void JS_ResetUncatchableError(JSContext *ctx); +JS_EXTERN JSValue JS_NewError(JSContext *ctx); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowPlainError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowSyntaxError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowTypeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowReferenceError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowRangeError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(2, 3) JS_ThrowInternalError(JSContext *ctx, JS_PRINTF_FORMAT const char *fmt, ...); +JS_EXTERN JSValue JS_ThrowOutOfMemory(JSContext *ctx); +JS_EXTERN void JS_FreeValue(JSContext *ctx, JSValue v); +JS_EXTERN void JS_FreeValueRT(JSRuntime *rt, JSValue v); +JS_EXTERN JSValue JS_DupValue(JSContext *ctx, JSValue v); +JS_EXTERN JSValue JS_DupValueRT(JSRuntime *rt, JSValue v); +JS_EXTERN int JS_ToBool(JSContext *ctx, JSValue val); /* return -1 for JS_EXCEPTION */ +static inline JSValue JS_ToBoolean(JSContext *ctx, JSValue val) { - (void) ctx; - if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); -#ifndef NDEBUG - notifyRefCountIncrease(p); -#endif - p->ref_count++; - } - return v; + return JS_NewBool(ctx, JS_ToBool(ctx, val)); } - -static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v) -{ - (void) rt; - if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); -#ifndef NDEBUG - notifyRefCountIncrease(p); -#endif - p->ref_count++; - } - return 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) +JS_EXTERN JSValue JS_ToNumber(JSContext *ctx, JSValue val); +JS_EXTERN int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValue val); +static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValue val) { return JS_ToInt32(ctx, (int32_t*)pres, val); } -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); +JS_EXTERN int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValue val); +JS_EXTERN int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValue val); +JS_EXTERN int JS_ToFloat64(JSContext *ctx, double *pres, JSValue val); /* return an exception if 'val' is a Number */ -int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val); +JS_EXTERN int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValue val); +JS_EXTERN int JS_ToBigUint64(JSContext *ctx, uint64_t *pres, JSValue val); /* same as JS_ToInt64() but allow BigInt */ -int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val); - -JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1); -JSValue JS_NewString(JSContext *ctx, const char *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) +JS_EXTERN int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValue val); + +JS_EXTERN 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)); +} +JS_EXTERN JSValue JS_NewAtomString(JSContext *ctx, const char *str); +JS_EXTERN JSValue JS_ToString(JSContext *ctx, JSValue val); +JS_EXTERN JSValue JS_ToPropertyKey(JSContext *ctx, JSValue val); +JS_EXTERN const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValue val1, bool cesu8); +static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValue val1) { return JS_ToCStringLen2(ctx, plen, val1, 0); } -static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1) +static inline const char *JS_ToCString(JSContext *ctx, JSValue 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); - -JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val); -JS_BOOL JS_IsRegExp(JSContext* ctx, JSValueConst val); -JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val); -JS_BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, JS_BOOL val); -JS_BOOL JS_IsArrayBuffer(JSValueConst v); - -JSValue JS_NewArray(JSContext *ctx); -int JS_IsArray(JSContext *ctx, JSValueConst val); - -JSValue JS_NewDate(JSContext *ctx, double epoch_ms); -JS_BOOL JS_IsDate(JSValueConst v); - -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); -} -JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop); -JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx); - -int JS_SetPropertyInternal(JSContext *ctx, JSValueConst obj, - JSAtom prop, JSValue val, JSValueConst this_obj, - int flags); -static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val) -{ - return JS_SetPropertyInternal(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW); -} -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_SetPropertyStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val); -int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop); -int JS_IsExtensible(JSContext *ctx, JSValueConst obj); -int JS_PreventExtensions(JSContext *ctx, JSValueConst obj); -int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags); -int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val); -JSValue JS_GetPrototype(JSContext *ctx, JSValueConst val); - -JSValue JS_ObjectSeal(JSContext *ctx, JSValueConst obj, int freeze); +JS_EXTERN void JS_FreeCString(JSContext *ctx, const char *ptr); + +JS_EXTERN JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValue proto, JSClassID class_id); +JS_EXTERN JSValue JS_NewObjectClass(JSContext *ctx, int class_id); +JS_EXTERN JSValue JS_NewObjectProto(JSContext *ctx, JSValue proto); +JS_EXTERN JSValue JS_NewObject(JSContext *ctx); +JS_EXTERN JSValue JS_NewObjectFrom(JSContext *ctx, int count, + const JSAtom *props, + const JSValue *values); +JS_EXTERN JSValue JS_NewObjectFromStr(JSContext *ctx, int count, + const char **props, + const JSValue *values); +JS_EXTERN JSValue JS_ToObject(JSContext *ctx, JSValue val); +JS_EXTERN JSValue JS_ToObjectString(JSContext *ctx, JSValue val); + +JS_EXTERN bool JS_IsFunction(JSContext* ctx, JSValue val); +JS_EXTERN bool JS_IsConstructor(JSContext* ctx, JSValue val); +JS_EXTERN bool JS_SetConstructorBit(JSContext *ctx, JSValue func_obj, bool val); + +JS_EXTERN bool JS_IsRegExp(JSValue val); +JS_EXTERN bool JS_IsMap(JSValue val); +JS_EXTERN int JS_IsSimpleValue(JSContext* ctx, JSValue v); + +JS_EXTERN JSValue JS_NewArray(JSContext *ctx); +// takes ownership of the values +JS_EXTERN JSValue JS_NewArrayFrom(JSContext *ctx, int count, + const JSValue *values); +JS_EXTERN int JS_IsArray(JSContext *ctx, JSValue val); + +JS_EXTERN JSValue JS_NewDate(JSContext *ctx, double epoch_ms); +JS_EXTERN bool JS_IsDate(JSValue v); + +JS_EXTERN JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop); +JS_EXTERN JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx); +JS_EXTERN JSValue JS_GetPropertyInt64(JSContext *ctx, JSValue this_obj, + int64_t idx); +JS_EXTERN JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj, + const char *prop); + +JS_EXTERN int JS_SetProperty(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val); +JS_EXTERN int JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx, JSValue val); +JS_EXTERN int JS_SetPropertyInt64(JSContext *ctx, JSValue this_obj, + int64_t idx, JSValue val); +JS_EXTERN int JS_SetPropertyStr(JSContext *ctx, JSValue this_obj, + const char *prop, JSValue val); +JS_EXTERN int JS_HasProperty(JSContext *ctx, JSValue this_obj, JSAtom prop); +JS_EXTERN int JS_IsExtensible(JSContext *ctx, JSValue obj); +JS_EXTERN int JS_PreventExtensions(JSContext *ctx, JSValue obj); +JS_EXTERN int JS_DeleteProperty(JSContext *ctx, JSValue obj, JSAtom prop, int flags); +JS_EXTERN int JS_SetPrototype(JSContext *ctx, JSValue obj, JSValue proto_val); +JS_EXTERN JSValue JS_GetPrototype(JSContext *ctx, JSValue val); +JS_EXTERN int JS_GetLength(JSContext *ctx, JSValue obj, int64_t *pres); +JS_EXTERN int JS_SetLength(JSContext *ctx, JSValue obj, int64_t len); +JS_EXTERN int JS_SealObject(JSContext *ctx, JSValue obj); +JS_EXTERN int JS_FreezeObject(JSContext *ctx, JSValue obj); #define JS_GPN_STRING_MASK (1 << 0) #define JS_GPN_SYMBOL_MASK (1 << 1) @@ -731,62 +790,75 @@ JSValue JS_ObjectSeal(JSContext *ctx, JSValueConst obj, int freeze); /* set theJSPropertyEnum.is_enumerable field */ #define JS_GPN_SET_ENUM (1 << 5) -int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, - uint32_t *plen, JSValueConst obj, int flags); -int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, - JSValueConst obj, JSAtom prop); - -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); -JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj, - int argc, JSValueConst *argv); -JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj, - JSValueConst new_target, - int argc, JSValueConst *argv); -JS_BOOL JS_DetectModule(const char *input, size_t input_len); +JS_EXTERN int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab, + uint32_t *plen, JSValue obj, int flags); +JS_EXTERN int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc, + JSValue obj, JSAtom prop); +JS_EXTERN void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, + uint32_t len); + +JS_EXTERN JSValue JS_Call(JSContext *ctx, JSValue func_obj, JSValue this_obj, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_Invoke(JSContext *ctx, JSValue this_val, JSAtom atom, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_CallConstructor(JSContext *ctx, JSValue func_obj, + int argc, JSValue *argv); +JS_EXTERN JSValue JS_CallConstructor2(JSContext *ctx, JSValue func_obj, + JSValue new_target, + int argc, JSValue *argv); +/* Try to detect if the input is a module. Returns true if parsing the input + * as a module produces no syntax errors. It's a naive approach that is not + * wholly infallible: non-strict classic scripts may _parse_ okay as a module + * but not _execute_ as one (different runtime semantics.) Use with caution. + * |input| can be either ASCII or UTF-8 encoded source code. + */ +JS_EXTERN bool JS_DetectModule(const char *input, size_t input_len); /* '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 line, int eval_flags); -JSValue JS_GetGlobalObject(JSContext *ctx); -int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); -int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValueConst val, - JSValueConst getter, JSValueConst setter, int flags); -int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue val, int flags); -int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj, - uint32_t idx, JSValue val, int flags); -int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj, - const char *prop, JSValue val, int flags); -int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj, - JSAtom prop, JSValue getter, JSValue setter, - int flags); -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); +JS_EXTERN JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len, + const char *filename, int eval_flags); +JS_EXTERN JSValue JS_Eval2(JSContext *ctx, const char *input, size_t input_len, + JSEvalOptions *options); +JS_EXTERN JSValue JS_EvalThis(JSContext *ctx, JSValue this_obj, + const char *input, size_t input_len, + const char *filename, int eval_flags); +JS_EXTERN JSValue JS_EvalThis2(JSContext *ctx, JSValue this_obj, + const char *input, size_t input_len, + JSEvalOptions *options); +JS_EXTERN JSValue JS_GetGlobalObject(JSContext *ctx); +JS_EXTERN int JS_IsInstanceOf(JSContext *ctx, JSValue val, JSValue obj); +JS_EXTERN int JS_DefineProperty(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, + JSValue getter, JSValue setter, int flags); +JS_EXTERN int JS_DefinePropertyValue(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyValueUint32(JSContext *ctx, JSValue this_obj, + uint32_t idx, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyValueStr(JSContext *ctx, JSValue this_obj, + const char *prop, JSValue val, int flags); +JS_EXTERN int JS_DefinePropertyGetSet(JSContext *ctx, JSValue this_obj, + JSAtom prop, JSValue getter, JSValue setter, + int flags); +/* Only supported for custom classes, returns 0 on success < 0 otherwise. */ +JS_EXTERN int JS_SetOpaque(JSValue obj, void *opaque); +JS_EXTERN void *JS_GetOpaque(JSValue obj, JSClassID class_id); +JS_EXTERN void *JS_GetOpaque2(JSContext *ctx, JSValue obj, JSClassID class_id); +JS_EXTERN void *JS_GetAnyOpaque(JSValue 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); +JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, + const char *filename); +JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValue obj, + JSValue replacer, JSValue space0); typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); -JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - JS_BOOL is_shared); -JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); -void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); -uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); +JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, + JSFreeArrayBufferDataFunc *free_func, void *opaque, + bool is_shared); +JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); +JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValue obj); +JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValue obj); +JS_EXTERN bool JS_IsArrayBuffer(JSValue obj); +JS_EXTERN uint8_t *JS_GetUint8Array(JSContext *ctx, size_t *psize, JSValue obj); typedef enum JSTypedArrayEnum { JS_TYPED_ARRAY_UINT8C = 0, @@ -798,24 +870,30 @@ typedef enum JSTypedArrayEnum { JS_TYPED_ARRAY_UINT32, JS_TYPED_ARRAY_BIG_INT64, JS_TYPED_ARRAY_BIG_UINT64, + JS_TYPED_ARRAY_FLOAT16, JS_TYPED_ARRAY_FLOAT32, JS_TYPED_ARRAY_FLOAT64, } JSTypedArrayEnum; -JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValueConst *argv, +JS_EXTERN JSValue JS_NewTypedArray(JSContext *ctx, int argc, JSValue *argv, JSTypedArrayEnum array_type); -JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, - size_t *pbyte_offset, - size_t *pbyte_length, - size_t *pbytes_per_element); +JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValue obj, + size_t *pbyte_offset, + size_t *pbyte_length, + size_t *pbytes_per_element); +JS_EXTERN JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len, + JSFreeArrayBufferDataFunc *free_func, void *opaque, + bool is_shared); +/* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */ +JS_EXTERN int JS_GetTypedArrayType(JSValue obj); +JS_EXTERN JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len); typedef struct { void *(*sab_alloc)(void *opaque, size_t size); void (*sab_free)(void *opaque, void *ptr); void (*sab_dup)(void *opaque, void *ptr); void *sab_opaque; } JSSharedArrayBufferFunctions; -void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, - const JSSharedArrayBufferFunctions *sf); +JS_EXTERN void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, const JSSharedArrayBufferFunctions *sf); typedef enum JSPromiseStateEnum { JS_PROMISE_PENDING, @@ -823,23 +901,26 @@ typedef enum JSPromiseStateEnum { JS_PROMISE_REJECTED, } JSPromiseStateEnum; -JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); -JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise); -JSValue JS_PromiseResult(JSContext *ctx, JSValue promise); +JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); +JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValue promise); +JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValue promise); +JS_EXTERN bool JS_IsPromise(JSValue val); -/* is_handled = TRUE means that the rejection is handled */ -typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValueConst promise, - JSValueConst reason, - JS_BOOL is_handled, void *opaque); -void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); +JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global); + +/* is_handled = true means that the rejection is handled */ +typedef void JSHostPromiseRejectionTracker(JSContext *ctx, JSValue promise, + JSValue reason, + bool is_handled, void *opaque); +JS_EXTERN void JS_SetHostPromiseRejectionTracker(JSRuntime *rt, JSHostPromiseRejectionTracker *cb, void *opaque); /* 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); -/* if can_block is TRUE, Atomics.wait() can be used */ -void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block); +JS_EXTERN void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque); +/* if can_block is true, Atomics.wait() can be used */ +JS_EXTERN void JS_SetCanBlock(JSRuntime *rt, bool can_block); /* set the [IsHTMLDDA] internal slot */ -void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj); +JS_EXTERN void JS_SetIsHTMLDDA(JSContext *ctx, JSValue obj); typedef struct JSModuleDef JSModuleDef; @@ -853,51 +934,57 @@ typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx, /* module_normalize = NULL is allowed and invokes the default module filename normalizer */ -void JS_SetModuleLoaderFunc(JSRuntime *rt, - JSModuleNormalizeFunc *module_normalize, - JSModuleLoaderFunc *module_loader, void *opaque); +JS_EXTERN void JS_SetModuleLoaderFunc(JSRuntime *rt, + JSModuleNormalizeFunc *module_normalize, + JSModuleLoaderFunc *module_loader, void *opaque); /* return the import.meta object of a module */ -JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); -JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); -JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m); +JS_EXTERN JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m); +JS_EXTERN JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m); +JS_EXTERN JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m); /* JS Job support */ -typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv); -int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv); +typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValue *argv); +JS_EXTERN int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValue *argv); + +JS_EXTERN bool JS_IsJobPending(JSRuntime *rt); +JS_EXTERN int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); -JS_BOOL JS_IsJobPending(JSRuntime *rt); -int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx); +/* Structure to retrieve (de)serialized SharedArrayBuffer objects. */ +typedef struct JSSABTab { + uint8_t **tab; + size_t len; +} JSSABTab; /* 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_BSWAP (0) /* byte swapped output (obsolete, handled transparently) */ #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_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to encode arbitrary object graph */ +#define JS_WRITE_OBJ_STRIP_SOURCE (1 << 4) /* do not write source code information */ +#define JS_WRITE_OBJ_STRIP_DEBUG (1 << 5) /* do not write debug information */ +JS_EXTERN uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValue obj, int flags); +JS_EXTERN uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValue obj, + int flags, JSSABTab *psab_tab); #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_ROM_DATA (0) /* avoid duplicating 'buf' data (obsolete, broken by ICs) */ #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); +JS_EXTERN JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, int flags); +JS_EXTERN JSValue JS_ReadObject2(JSContext *ctx, const uint8_t *buf, size_t buf_len, + int flags, JSSABTab *psab_tab); /* 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); +JS_EXTERN JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj); /* load the dependencies of the module 'obj'. Useful when JS_ReadObject() returns a module. */ -int JS_ResolveModule(JSContext *ctx, JSValueConst obj); +JS_EXTERN int JS_ResolveModule(JSContext *ctx, JSValue obj); /* only exported for os.Worker() */ -JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); +JS_EXTERN JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels); /* only exported for os.Worker() */ -JSValue JS_LoadModule(JSContext *ctx, const char *basename, +JS_EXTERN JSValue JS_LoadModule(JSContext *ctx, const char *basename, const char *filename); /* C function definition */ @@ -919,39 +1006,53 @@ typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */ typedef union JSCFunctionType { JSCFunction *generic; - JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); + JSValue (*generic_magic)(JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic); JSCFunction *constructor; - JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); + JSValue (*constructor_magic)(JSContext *ctx, JSValue new_target, int argc, JSValue *argv, int magic); JSCFunction *constructor_or_func; double (*f_f)(double); double (*f_f_f)(double, double); - JSValue (*getter)(JSContext *ctx, JSValueConst this_val); - JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val); - JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic); - JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic); - JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int *pdone, int magic); + JSValue (*getter)(JSContext *ctx, JSValue this_val); + JSValue (*setter)(JSContext *ctx, JSValue this_val, JSValue val); + JSValue (*getter_magic)(JSContext *ctx, JSValue this_val, int magic); + JSValue (*setter_magic)(JSContext *ctx, JSValue this_val, JSValue val, int magic); + JSValue (*iterator_next)(JSContext *ctx, JSValue this_val, + int argc, JSValue *argv, int *pdone, int magic); } 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); - -JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name, - int length); +JS_EXTERN JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic); +JS_EXTERN JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic, + JSValue proto_val); +JS_EXTERN JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, + int length, int magic, int data_len, + JSValue *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); +} -JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, - const char *name, int length, JSCFunctionEnum cproto, int magic); -void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, - JSValueConst proto); +static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func, + const char *name, + int length, JSCFunctionEnum cproto, int magic) +{ + /* Used to squelch a -Wcast-function-type warning. */ + JSCFunctionType ft; + ft.generic_magic = func; + return JS_NewCFunction2(ctx, ft.generic, name, length, cproto, magic); +} +JS_EXTERN void JS_SetConstructor(JSContext *ctx, JSValue func_obj, + JSValue proto); /* C property definition */ typedef struct JSCFunctionListEntry { - const char *name; + const char *name; /* pure ASCII or UTF-8 encoded */ uint8_t prop_flags; uint8_t def_type; int16_t magic; @@ -973,9 +1074,10 @@ typedef struct JSCFunctionListEntry { const struct JSCFunctionListEntry *tab; int len; } prop_list; - const char *str; + const char *str; /* pure ASCII or UTF-8 encoded */ int32_t i32; int64_t i64; + uint64_t u64; double f64; } u; } JSCFunctionListEntry; @@ -992,41 +1094,43 @@ typedef struct JSCFunctionListEntry { #define JS_DEF_ALIAS 9 /* Note: c++ does not like nested designators */ -#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 } } } } -#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 } } } } -#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 } } } } -#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 } } } } -#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } -#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 } } } } -#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 } } } - -void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj, - const JSCFunctionListEntry *tab, - int len); +#define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define JS_CFUNC_DEF2(name, length, func1, prop_flags) { name, prop_flags, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } } } +#define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, { .func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } } } +#define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, { .func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } } } +#define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } +#define JS_CGETSET_DEF2(name, fgetter, fsetter, prop_flags) { name, prop_flags, JS_DEF_CGETSET, 0, { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } +#define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, { .getset = { .get = { .getter_magic = fgetter }, .set = { .setter_magic = fsetter } } } } +#define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, { .str = cstr } } +#define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, { .i32 = val } } +#define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, { .i64 = val } } +#define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .f64 = val } } +#define JS_PROP_U2D_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, { .u64 = val } } +#define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, { .i32 = 0 } } +#define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, { .prop_list = { tab, len } } } +#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, -1 } } } +#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, { .alias = { from, base } } } + +JS_EXTERN void JS_SetPropertyFunctionList(JSContext *ctx, JSValue obj, + const JSCFunctionListEntry *tab, + int len); /* C module definition */ typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m); -JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, - JSModuleInitFunc *func); +JS_EXTERN JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str, + JSModuleInitFunc *func); /* can only be called before the module is instantiated */ -int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); -int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, - const JSCFunctionListEntry *tab, int len); +JS_EXTERN int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str); +JS_EXTERN int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); /* can only be called after the module is instantiated */ -int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, - JSValue val); -int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, - const JSCFunctionListEntry *tab, int len); - +JS_EXTERN int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name, + JSValue val); +JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, + const JSCFunctionListEntry *tab, int len); /* Qbs extensions */ struct LookupResult @@ -1041,22 +1145,24 @@ void setScopeLookup(JSContext *ctx, ScopeLookup *scopeLookup); // Alternative: Request with throw in script engine typedef void FoundUndefinedHandler(JSContext *ctx); void setFoundUndefinedHandler(JSContext *ctx, FoundUndefinedHandler *handler); - typedef void FunctionEnteredHandler(JSContext *ctx, JSValue this_val); typedef void FunctionExitedHandler(JSContext *ctx); void setFunctionEnteredHandler(JSContext *ctx, FunctionEnteredHandler *handler); void setFunctionExitedHandler(JSContext *ctx, FunctionExitedHandler *handler); -int isSimpleValue(JSValue v); -#ifndef NDEBUG -void watchRefCount(void *p); -#endif +/* Version */ + +#define QJS_VERSION_MAJOR 0 +#define QJS_VERSION_MINOR 8 +#define QJS_VERSION_PATCH 0 +#define QJS_VERSION_SUFFIX "" + +JS_EXTERN const char* JS_GetVersion(void); -void build_backtrace(JSContext *ctx, JSValueConst error_obj, - const char *filename, int line_num, - int backtrace_flags); +/* Integration point for quickjs-libc.c, not for public use. */ +JS_EXTERN uintptr_t js_std_cmd(int cmd, ...); -#undef js_unlikely +#undef JS_EXTERN #undef js_force_inline #ifdef __cplusplus |