forked from bellard/mquickjs
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmquickjs.h
More file actions
388 lines (338 loc) · 14.5 KB
/
mquickjs.h
File metadata and controls
388 lines (338 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/*
* 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);
JS_BOOL JS_IsObject(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);
const char *JS_GetOwnPropertyByIndex(JSContext *ctx, uint32_t property_index, uint32_t *pcount, JSValue val);
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);
JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len);
const char *JS_GetTypedArrayBuffer(JSContext *ctx, size_t *plen, JSValue val);
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);
int JS_ToBool(JSContext *ctx, 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 */