Xteink-X4-crosspoint-reader/lib/mquickjs/mquickjs.h
Xuan Son Nguyen 49d2c5eba8 init version
2026-01-31 22:01:10 +01:00

383 lines
14 KiB
C

/*
* Micro QuickJS Javascript Engine
*
* Copyright (c) 2017-2025 Fabrice Bellard
* Copyright (c) 2017-2025 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 MQUICKJS_H
#define MQUICKJS_H
#include <inttypes.h>
#if defined(__GNUC__) || defined(__clang__)
#define __js_printf_like(f, a) __attribute__((format(printf, f, a)))
#else
#define __js_printf_like(a, b)
#endif
#if INTPTR_MAX >= INT64_MAX
#define JS_PTR64 /* pointers are 64 bit wide instead of 32 bit wide */
#endif
typedef struct JSContext JSContext;
#ifdef JS_PTR64
typedef uint64_t JSWord;
typedef uint64_t JSValue;
#define JSW 8
#define JSValue_PRI PRIo64
#define JS_USE_SHORT_FLOAT
#else
typedef uint32_t JSWord;
typedef uint32_t JSValue;
#define JSW 4
#define JSValue_PRI PRIo32
#endif
#define JS_BOOL int
enum {
JS_TAG_INT = 0, /* 31 bit integer (1 bit) */
JS_TAG_PTR = 1, /* pointer (2 bits) */
JS_TAG_SPECIAL = 3, /* other special values (2 bits) */
JS_TAG_BOOL = JS_TAG_SPECIAL | (0 << 2), /* (5 bits) */
JS_TAG_NULL = JS_TAG_SPECIAL | (1 << 2), /* (5 bits) */
JS_TAG_UNDEFINED = JS_TAG_SPECIAL | (2 << 2), /* (5 bits) */
JS_TAG_EXCEPTION = JS_TAG_SPECIAL | (3 << 2), /* (5 bits) */
JS_TAG_SHORT_FUNC = JS_TAG_SPECIAL | (4 << 2), /* (5 bits) */
JS_TAG_UNINITIALIZED = JS_TAG_SPECIAL | (5 << 2), /* (5 bits) */
JS_TAG_STRING_CHAR = JS_TAG_SPECIAL | (6 << 2), /* (5 bits) */
JS_TAG_CATCH_OFFSET = JS_TAG_SPECIAL | (7 << 2), /* (5 bits) */
#ifdef JS_USE_SHORT_FLOAT
JS_TAG_SHORT_FLOAT = 5, /* 3 bits */
#endif
};
#define JS_TAG_SPECIAL_BITS 5
#define JS_VALUE_GET_INT(v) ((int)(v) >> 1)
#define JS_VALUE_GET_SPECIAL_VALUE(v) ((int)(v) >> JS_TAG_SPECIAL_BITS)
#define JS_VALUE_GET_SPECIAL_TAG(v) ((v) & ((1 << JS_TAG_SPECIAL_BITS) - 1))
#define JS_VALUE_MAKE_SPECIAL(tag, v) ((tag) | ((v) << JS_TAG_SPECIAL_BITS))
#define JS_NULL JS_VALUE_MAKE_SPECIAL(JS_TAG_NULL, 0)
#define JS_UNDEFINED JS_VALUE_MAKE_SPECIAL(JS_TAG_UNDEFINED, 0)
#define JS_UNINITIALIZED JS_VALUE_MAKE_SPECIAL(JS_TAG_UNINITIALIZED, 0)
#define JS_FALSE JS_VALUE_MAKE_SPECIAL(JS_TAG_BOOL, 0)
#define JS_TRUE JS_VALUE_MAKE_SPECIAL(JS_TAG_BOOL, 1)
#define JS_EX_NORMAL 0 /* all exceptions except not enough memory */
#define JS_EX_CALL 1 /* specific exception to generate a tail call. The call flags are added */
#define JS_EXCEPTION JS_VALUE_MAKE_SPECIAL(JS_TAG_EXCEPTION, JS_EX_NORMAL)
typedef enum {
JS_CLASS_OBJECT,
JS_CLASS_ARRAY,
JS_CLASS_C_FUNCTION,
JS_CLASS_CLOSURE,
JS_CLASS_NUMBER,
JS_CLASS_BOOLEAN,
JS_CLASS_STRING,
JS_CLASS_DATE,
JS_CLASS_REGEXP,
JS_CLASS_ERROR,
JS_CLASS_EVAL_ERROR,
JS_CLASS_RANGE_ERROR,
JS_CLASS_REFERENCE_ERROR,
JS_CLASS_SYNTAX_ERROR,
JS_CLASS_TYPE_ERROR,
JS_CLASS_URI_ERROR,
JS_CLASS_INTERNAL_ERROR,
JS_CLASS_ARRAY_BUFFER,
JS_CLASS_TYPED_ARRAY,
JS_CLASS_UINT8C_ARRAY,
JS_CLASS_INT8_ARRAY,
JS_CLASS_UINT8_ARRAY,
JS_CLASS_INT16_ARRAY,
JS_CLASS_UINT16_ARRAY,
JS_CLASS_INT32_ARRAY,
JS_CLASS_UINT32_ARRAY,
JS_CLASS_FLOAT32_ARRAY,
JS_CLASS_FLOAT64_ARRAY,
JS_CLASS_USER, /* user classes start from this value */
} JSObjectClassEnum;
/* predefined functions */
typedef enum {
JS_CFUNCTION_bound,
JS_CFUNCTION_USER, /* user functions start from this value */
} JSCFunctionEnum;
/* temporary buffer to hold C strings */
typedef struct {
uint8_t buf[5];
} JSCStringBuf;
typedef struct JSGCRef {
JSValue val;
struct JSGCRef *prev;
} JSGCRef;
/* stack of JSGCRef */
JSValue *JS_PushGCRef(JSContext *ctx, JSGCRef *ref);
JSValue JS_PopGCRef(JSContext *ctx, JSGCRef *ref);
#define JS_PUSH_VALUE(ctx, v) do { JS_PushGCRef(ctx, &v ## _ref); v ## _ref.val = v; } while (0)
#define JS_POP_VALUE(ctx, v) v = JS_PopGCRef(ctx, &v ## _ref)
/* list of JSGCRef (they can be removed in any order, slower) */
JSValue *JS_AddGCRef(JSContext *ctx, JSGCRef *ref);
void JS_DeleteGCRef(JSContext *ctx, JSGCRef *ref);
JSValue JS_NewFloat64(JSContext *ctx, double d);
JSValue JS_NewInt32(JSContext *ctx, int32_t val);
JSValue JS_NewUint32(JSContext *ctx, uint32_t val);
JSValue JS_NewInt64(JSContext *ctx, int64_t val);
static inline JS_BOOL JS_IsInt(JSValue v)
{
return (v & 1) == JS_TAG_INT;
}
static inline JS_BOOL JS_IsPtr(JSValue v)
{
return (v & (JSW - 1)) == JS_TAG_PTR;
}
#ifdef JS_USE_SHORT_FLOAT
static inline JS_BOOL JS_IsShortFloat(JSValue v)
{
return (v & (JSW - 1)) == JS_TAG_SHORT_FLOAT;
}
#endif
static inline JS_BOOL JS_IsBool(JSValue v)
{
return JS_VALUE_GET_SPECIAL_TAG(v) == JS_TAG_BOOL;
}
static inline JS_BOOL JS_IsNull(JSValue v)
{
return v == JS_NULL;
}
static inline JS_BOOL JS_IsUndefined(JSValue v)
{
return v == JS_UNDEFINED;
}
static inline JS_BOOL JS_IsUninitialized(JSValue v)
{
return v == JS_UNINITIALIZED;
}
static inline JS_BOOL JS_IsException(JSValue v)
{
return v == JS_EXCEPTION;
}
static inline JSValue JS_NewBool(int val)
{
return JS_VALUE_MAKE_SPECIAL(JS_TAG_BOOL, (val != 0));
}
JS_BOOL JS_IsNumber(JSContext *ctx, JSValue val);
JS_BOOL JS_IsString(JSContext *ctx, JSValue val);
JS_BOOL JS_IsError(JSContext *ctx, JSValue val);
JS_BOOL JS_IsFunction(JSContext *ctx, JSValue val);
int JS_GetClassID(JSContext *ctx, JSValue val);
void JS_SetOpaque(JSContext *ctx, JSValue val, void *opaque);
void *JS_GetOpaque(JSContext *ctx, JSValue val);
typedef JSValue JSCFunction(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv);
/* no JS function call be called from a C finalizer */
typedef void (*JSCFinalizer)(JSContext *ctx, void *opaque);
typedef enum JSCFunctionDefEnum { /* XXX: should rename for namespace isolation */
JS_CFUNC_generic,
JS_CFUNC_generic_magic,
JS_CFUNC_constructor,
JS_CFUNC_constructor_magic,
JS_CFUNC_generic_params,
JS_CFUNC_f_f,
} JSCFunctionDefEnum;
typedef union JSCFunctionType {
JSCFunction *generic;
JSValue (*generic_magic)(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv, int magic);
JSCFunction *constructor;
JSValue (*constructor_magic)(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv, int magic);
JSValue (*generic_params)(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv, JSValue params);
double (*f_f)(double f);
} JSCFunctionType;
typedef struct JSCFunctionDef {
JSCFunctionType func;
JSValue name;
uint8_t def_type;
uint8_t arg_count;
int16_t magic;
} JSCFunctionDef;
typedef struct {
const JSWord *stdlib_table;
const JSCFunctionDef *c_function_table;
const JSCFinalizer *c_finalizer_table;
uint32_t stdlib_table_len;
uint32_t stdlib_table_align;
uint32_t sorted_atoms_offset;
uint32_t global_object_offset;
uint32_t class_count;
} JSSTDLibraryDef;
typedef void JSWriteFunc(void *opaque, const void *buf, size_t buf_len);
/* return != 0 if the JS code needs to be interrupted */
typedef int JSInterruptHandler(JSContext *ctx, void *opaque);
JSContext *JS_NewContext(void *mem_start, size_t mem_size, const JSSTDLibraryDef *stdlib_def);
/* if prepare_compilation is true, the context will be used to compile
to a binary file. JS_NewContext2() is not expected to be used in
the embedded version */
JSContext *JS_NewContext2(void *mem_start, size_t mem_size, const JSSTDLibraryDef *stdlib_def, JS_BOOL prepare_compilation);
void JS_FreeContext(JSContext *ctx);
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
void JS_SetInterruptHandler(JSContext *ctx, JSInterruptHandler *interrupt_handler);
void JS_SetRandomSeed(JSContext *ctx, uint64_t seed);
JSValue JS_GetGlobalObject(JSContext *ctx);
JSValue JS_Throw(JSContext *ctx, JSValue obj);
JSValue __js_printf_like(3, 4) JS_ThrowError(JSContext *ctx, JSObjectClassEnum error_num,
const char *fmt, ...);
#define JS_ThrowTypeError(ctx, fmt, ...) JS_ThrowError(ctx, JS_CLASS_TYPE_ERROR, fmt, ##__VA_ARGS__)
#define JS_ThrowReferenceError(ctx, fmt, ...) JS_ThrowError(ctx, JS_CLASS_REFERENCE_ERROR, fmt, ##__VA_ARGS__)
#define JS_ThrowInternalError(ctx, fmt, ...) JS_ThrowError(ctx, JS_CLASS_INTERNAL_ERROR, fmt, ##__VA_ARGS__)
#define JS_ThrowRangeError(ctx, fmt, ...) JS_ThrowError(ctx, JS_CLASS_RANGE_ERROR, fmt, ##__VA_ARGS__)
#define JS_ThrowSyntaxError(ctx, fmt, ...) JS_ThrowError(ctx, JS_CLASS_SYNTAX_ERROR, fmt, ##__VA_ARGS__)
JSValue JS_ThrowOutOfMemory(JSContext *ctx);
JSValue JS_GetPropertyStr(JSContext *ctx, JSValue this_obj, const char *str);
JSValue JS_GetPropertyUint32(JSContext *ctx, JSValue obj, uint32_t idx);
JSValue JS_SetPropertyStr(JSContext *ctx, JSValue this_obj,
const char *str, JSValue val);
JSValue JS_SetPropertyUint32(JSContext *ctx, JSValue this_obj,
uint32_t idx, JSValue val);
JSValue JS_NewObjectClassUser(JSContext *ctx, int class_id);
JSValue JS_NewObject(JSContext *ctx);
JSValue JS_NewArray(JSContext *ctx, int initial_len);
/* create a C function with an object parameter (closure) */
JSValue JS_NewCFunctionParams(JSContext *ctx, int func_idx, JSValue params);
#define JS_EVAL_RETVAL (1 << 0) /* return the last value instead of undefined (slower code) */
#define JS_EVAL_REPL (1 << 1) /* implicitly defined global variables in assignments */
#define JS_EVAL_STRIP_COL (1 << 2) /* strip column number debug information (save memory) */
#define JS_EVAL_JSON (1 << 3) /* parse as JSON and return the object */
#define JS_EVAL_REGEXP (1 << 4) /* internal use */
#define JS_EVAL_REGEXP_FLAGS_SHIFT 8 /* internal use */
JSValue JS_Parse(JSContext *ctx, const char *input, size_t input_len,
const char *filename, int eval_flags);
JSValue JS_Run(JSContext *ctx, JSValue val);
JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
const char *filename, int eval_flags);
void JS_GC(JSContext *ctx);
JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len);
JSValue JS_NewString(JSContext *ctx, const char *buf);
const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValue val, JSCStringBuf *buf);
const char *JS_ToCString(JSContext *ctx, JSValue val, JSCStringBuf *buf);
JSValue JS_ToString(JSContext *ctx, JSValue val);
int JS_ToInt32(JSContext *ctx, int *pres, JSValue val);
int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValue val);
int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValue val);
int JS_ToNumber(JSContext *ctx, double *pres, JSValue val);
JSValue JS_GetException(JSContext *ctx);
int JS_StackCheck(JSContext *ctx, uint32_t len);
void JS_PushArg(JSContext *ctx, JSValue val);
#define FRAME_CF_CTOR (1 << 16) /* also ored with argc in
C constructors */
JSValue JS_Call(JSContext *ctx, int call_flags);
#define JS_BYTECODE_MAGIC 0xacfb
typedef struct {
uint16_t magic; /* JS_BYTECODE_MAGIC */
uint16_t version;
uintptr_t base_addr;
JSValue unique_strings;
JSValue main_func;
} JSBytecodeHeader;
/* only used on the host when compiling to file */
void JS_PrepareBytecode(JSContext *ctx,
JSBytecodeHeader *hdr,
const uint8_t **pdata_buf, uint32_t *pdata_len,
JSValue eval_code);
/* only used on the host when compiling to file */
int JS_RelocateBytecode2(JSContext *ctx, JSBytecodeHeader *hdr,
uint8_t *buf, uint32_t buf_len,
uintptr_t new_base_addr, JS_BOOL update_atoms);
#if JSW == 8
typedef struct {
uint16_t magic; /* JS_BYTECODE_MAGIC */
uint16_t version;
uint32_t base_addr;
uint32_t unique_strings;
uint32_t main_func;
} JSBytecodeHeader32;
/* only used on the host when compiling to file. A 32 bit bytecode is generated on a 64 bit host. */
int JS_PrepareBytecode64to32(JSContext *ctx,
JSBytecodeHeader32 *hdr,
const uint8_t **pdata_buf, uint32_t *pdata_len,
JSValue eval_code);
#endif
JS_BOOL JS_IsBytecode(const uint8_t *buf, size_t buf_len);
/* Relocate the bytecode in 'buf' so that it can be executed
later. Return 0 if OK, != 0 if error */
int JS_RelocateBytecode(JSContext *ctx,
uint8_t *buf, uint32_t buf_len);
/* Load the precompiled bytecode from 'buf'. 'buf' must be allocated
as long as the JSContext exists. Use JS_Run() to execute
it. warning: the bytecode is not checked so it should come from a
trusted source. */
JSValue JS_LoadBytecode(JSContext *ctx, const uint8_t *buf);
/* debug functions */
void JS_SetLogFunc(JSContext *ctx, JSWriteFunc *write_func);
void JS_PrintValue(JSContext *ctx, JSValue val);
#define JS_DUMP_LONG (1 << 0) /* display object/array content */
#define JS_DUMP_NOQUOTE (1 << 1) /* strings: no quote for identifiers */
/* for low level dumps: don't dump special properties and use specific
quotes to distinguish string chars, unique strings and normal
strings */
#define JS_DUMP_RAW (1 << 2)
void JS_PrintValueF(JSContext *ctx, JSValue val, int flags);
void JS_DumpValueF(JSContext *ctx, const char *str,
JSValue val, int flags);
void JS_DumpValue(JSContext *ctx, const char *str,
JSValue val);
void JS_DumpMemory(JSContext *ctx, JS_BOOL is_long);
#endif /* MQUICKJS_H */