/* * QuickJS Javascript Engine * * Copyright (c) 2017-2020 Fabrice Bellard * Copyright (c) 2017-2020 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. */#include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.h>#include <string.h>#include <assert.h>#include <sys/time.h>#include <time.h>#include <fenv.h>#include <math.h>#if defined(__APPLE__)#include <malloc/malloc.h>#elif defined(__linux__)#include <malloc.h>#endif #include "cutils.h"#include "list.h"#include "quickjs.h"#include "libregexp.h"#ifdef CONFIG_BIGNUM#include "libbf.h"#endif #define OPTIMIZE 1#define SHORT_OPCODES 1#if defined(EMSCRIPTEN) || defined(__plan9__)#define DIRECT_DISPATCH 0#else#define DIRECT_DISPATCH 1#endif #if defined(__APPLE__)#define MALLOC_OVERHEAD 0#else#define MALLOC_OVERHEAD 8#endif #if !defined(_WIN32)/* define it if printf uses the RNDN rounding mode instead of RNDNA */#define CONFIG_PRINTF_RNDN#endif /* define to include Atomics.* operations which depend on the OS threads */#if !defined(EMSCRIPTEN) && !defined(__plan9__)#define CONFIG_ATOMICS#endif #if !defined(EMSCRIPTEN) && !defined(__plan9__)/* enable stack limitation */#define CONFIG_STACK_CHECK#endif /* dump object free *///#define DUMP_FREE//#define DUMP_CLOSURE/* dump the bytecode of the compiled functions: combination of bits 1: dump pass 3 final byte code 2: dump pass 2 code 4: dump pass 1 code 8: dump stdlib functions 16: dump bytecode in hex 32: dump line number table *///#define DUMP_BYTECODE (1)/* dump the occurence of the automatic GC *///#define DUMP_GC/* dump objects freed by the garbage collector *///#define DUMP_GC_FREE/* dump objects leaking when freeing the runtime *///#define DUMP_LEAKS 1/* dump memory usage before running the garbage collector *///#define DUMP_MEM//#define DUMP_OBJECTS /* dump objects in JS_FreeContext *///#define DUMP_ATOMS /* dump atoms in JS_FreeContext *///#define DUMP_SHAPES /* dump shapes in JS_FreeContext *///#define DUMP_MODULE_RESOLVE//#define DUMP_PROMISE//#define DUMP_READ_OBJECT /* test the GC by forcing it before each object allocation *///#define FORCE_GC_AT_MALLOC #ifdef CONFIG_ATOMICS#include <pthread.h>#include <stdatomic.h>#include <errno.h>#endif enum { /* classid tag */ /* union usage | properties */ JS_CLASS_OBJECT = 1, /* must be first */ JS_CLASS_ARRAY, /* u.array | length */ JS_CLASS_ERROR, JS_CLASS_NUMBER, /* u.object_data */ JS_CLASS_STRING, /* u.object_data */ JS_CLASS_BOOLEAN, /* u.object_data */ JS_CLASS_SYMBOL, /* u.object_data */ JS_CLASS_ARGUMENTS, /* u.array | length */ JS_CLASS_MAPPED_ARGUMENTS, /* | length */ JS_CLASS_DATE, /* u.object_data */ JS_CLASS_MODULE_NS, JS_CLASS_C_FUNCTION, /* u.cfunc */ JS_CLASS_BYTECODE_FUNCTION, /* u.func */ JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ JS_CLASS_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ JS_CLASS_REGEXP, /* u.regexp */ JS_CLASS_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_SHARED_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_UINT8C_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */#ifdef CONFIG_BIGNUM JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */#endif JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_DATAVIEW, /* u.typed_array */#ifdef CONFIG_BIGNUM JS_CLASS_BIG_INT, /* u.object_data */ JS_CLASS_BIG_FLOAT, /* u.object_data */ JS_CLASS_FLOAT_ENV, /* u.float_env */ JS_CLASS_BIG_DECIMAL, /* u.object_data */ JS_CLASS_OPERATOR_SET, /* u.operator_set */#endif JS_CLASS_MAP, /* u.map_state */ JS_CLASS_SET, /* u.map_state */ JS_CLASS_WEAKMAP, /* u.map_state */ JS_CLASS_WEAKSET, /* u.map_state */ JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ JS_CLASS_GENERATOR, /* u.generator_data */ JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_PROMISE, /* u.promise_data */ JS_CLASS_PROMISE_RESOLVE_FUNCTION, /* u.promise_function_data */ JS_CLASS_PROMISE_REJECT_FUNCTION, /* u.promise_function_data */ JS_CLASS_ASYNC_FUNCTION, /* u.func */ JS_CLASS_ASYNC_FUNCTION_RESOLVE, /* u.async_function_data */ JS_CLASS_ASYNC_FUNCTION_REJECT, /* u.async_function_data */ JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ JS_CLASS_INIT_COUNT, /* last entry for predefined classes */}; /* number of typed array types */#define JS_TYPED_ARRAY_COUNT (JS_CLASS_FLOAT64_ARRAY - JS_CLASS_UINT8C_ARRAY + 1)static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT];#define typed_array_size_log2(classid) (typed_array_size_log2[(classid)- JS_CLASS_UINT8C_ARRAY]) typedef enum JSErrorEnum { JS_EVAL_ERROR, JS_RANGE_ERROR, JS_REFERENCE_ERROR, JS_SYNTAX_ERROR, JS_TYPE_ERROR, JS_URI_ERROR, JS_INTERNAL_ERROR, JS_AGGREGATE_ERROR, JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */} JSErrorEnum; #define JS_MAX_LOCAL_VARS 65536#define JS_STACK_SIZE_MAX 65534#define JS_STRING_LEN_MAX ((1 << 30) - 1) #define __exception __attribute__((warn_unused_result)) typedef struct JSShape JSShape;typedef struct JSString JSString;typedef struct JSString JSAtomStruct; typedef enum { JS_GC_PHASE_NONE, JS_GC_PHASE_DECREF, JS_GC_PHASE_REMOVE_CYCLES,} JSGCPhaseEnum; typedef enum OPCodeEnum {#define FMT(f)#define DEF(id, size, n_pop, n_push, f) OP_ ## id,#define def(id, size, n_pop, n_push, f)#include "quickjs-opcode.h"#undef def#undef DEF#undef FMT OP_COUNT, /* excluding temporary opcodes */ /* temporary opcodes : overlap with the short opcodes */ OP_TEMP_START = OP_nop + 1, OP___dummy = OP_TEMP_START - 1,#define FMT(f)#define DEF(id, size, n_pop, n_push, f)#define def(id, size, n_pop, n_push, f) OP_ ## id,#include "quickjs-opcode.h"#undef def#undef DEF#undef FMT OP_TEMP_END,} OPCodeEnum; #ifdef CONFIG_BIGNUM/* function pointers are used for numeric operations so that it is possible to remove some numeric types */typedef struct { JSValue (*to_string)(JSContext *ctx, JSValueConst val); JSValue (*from_string)(JSContext *ctx, const char *buf, int radix, int flags, slimb_t *pexponent); int (*unary_arith)(JSContext *ctx, JSValue *pres, OPCodeEnum op, JSValue op1); int (*binary_arith)(JSContext *ctx, OPCodeEnum op, JSValue *pres, JSValue op1, JSValue op2); int (*compare)(JSContext *ctx, OPCodeEnum op, JSValue op1, JSValue op2); /* only for bigfloat: */ JSValue (*mul_pow10_to_float64)(JSContext *ctx, const bf_t *a, int64_t exponent); int (*mul_pow10)(JSContext *ctx, JSValue *sp);} JSNumericOperations;#endif struct JSRuntime { JSMallocFunctions mf; JSMallocState malloc_state; const char *rt_info; int atom_hash_size; /* power of two */ int atom_count; int atom_size; int atom_count_resize; /* resize hash table at this count */ uint32_t *atom_hash; JSAtomStruct **atom_array; int atom_free_index; /* 0 = none */ int class_count; /* size of class_array */ JSClass *class_array; struct list_head context_list; /* list of JSContext.link */ /* list of JSGCObjectHeader.link. List of allocated GC objects (used by the garbage collector) */ struct list_head gc_obj_list; /* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */ struct list_head gc_zero_ref_count_list; struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold;#ifdef DUMP_LEAKS struct list_head string_list; /* list of JSString.link */#endif /* stack limitation */ const uint8_t *stack_top; size_t stack_size; /* in bytes */ JSValue current_exception; /* true if inside an out of memory error, to avoid recursing */ BOOL in_out_of_memory : 8; struct JSStackFrame *current_stack_frame; JSInterruptHandler *interrupt_handler; void *interrupt_opaque; JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; JSModuleLoaderFunc *module_loader_func; void *module_loader_opaque; BOOL can_block : 8; /* TRUE if Atomics.wait can block */ /* used to allocate, free and clone SharedArrayBuffers */ JSSharedArrayBufferFunctions sab_funcs; /* Shape hash table */ int shape_hash_bits; int shape_hash_size; int shape_hash_count; /* number of hashed shapes */ JSShape **shape_hash;#ifdef CONFIG_BIGNUM bf_context_t bf_ctx; JSNumericOperations bigint_ops; JSNumericOperations bigfloat_ops; JSNumericOperations bigdecimal_ops; uint32_t operator_count;#endif void *user_opaque;}; struct JSClass { uint32_t class_id; /* 0 means free entry */ JSAtom class_name; JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; JSClassCall *call; /* pointers for exotic behavior, can be NULL if none are present */ const JSClassExoticMethods *exotic;}; #define JS_MODE_STRICT (1 << 0)#define JS_MODE_STRIP (1 << 1)#define JS_MODE_MATH (1 << 2) typedef struct JSStackFrame { struct JSStackFrame *prev_frame; /* NULL if first stack frame */ JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue *arg_buf; /* arguments */ JSValue *var_buf; /* variables */ struct list_head var_ref_list; /* list of JSVarRef.link */ const uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ int arg_count; int js_mode; /* 0 or JS_MODE_MATH for C functions */ /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp;} JSStackFrame; typedef enum { JS_GC_OBJ_TYPE_JS_OBJECT, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE, JS_GC_OBJ_TYPE_SHAPE, JS_GC_OBJ_TYPE_VAR_REF, JS_GC_OBJ_TYPE_ASYNC_FUNCTION, JS_GC_OBJ_TYPE_JS_CONTEXT,} JSGCObjectTypeEnum; /* header for GC objects. GC objects are C data structures with a reference count that can reference other GC objects. JS Objects are a particular type of GC object. */struct JSGCObjectHeader { int ref_count; /* must come first, 32-bit */ JSGCObjectTypeEnum gc_obj_type : 4; uint8_t mark : 4; /* used by the GC */ uint8_t dummy1; /* not used by the GC */ uint16_t dummy2; /* not used by the GC */ struct list_head link;}; typedef struct JSVarRef { union { JSGCObjectHeader header; /* must come first */ struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ /* 0 : the JSVarRef is on the stack. header.link is an element of JSStackFrame.var_ref_list. 1 : the JSVarRef is detached. header.link has the normal meanning */ uint8_t is_detached : 1; uint8_t is_arg : 1; uint16_t var_idx; /* index of the corresponding function variable on the stack */ }; }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ JSValue value; /* used when the variable is no longer on the stack */} JSVarRef; #ifdef CONFIG_BIGNUMtypedef struct JSFloatEnv { limb_t prec; bf_flags_t flags; unsigned int status;} JSFloatEnv; /* the same structure is used for big integers and big floats. Big integers are never infinite or NaNs */typedef struct JSBigFloat { JSRefCountHeader header; /* must come first, 32-bit */ bf_t num;} JSBigFloat; typedef struct JSBigDecimal { JSRefCountHeader header; /* must come first, 32-bit */ bfdec_t num;} JSBigDecimal;#endif typedef enum { JS_AUTOINIT_ID_PROTOTYPE, JS_AUTOINIT_ID_MODULE_NS, JS_AUTOINIT_ID_PROP,} JSAutoInitIDEnum; /* must be large enough to have a negligible runtime cost and small enough to call the interrupt callback often. */#define JS_INTERRUPT_COUNTER_INIT 10000 struct JSContext { JSGCObjectHeader header; /* must come first */ JSRuntime *rt; struct list_head link; uint16_t binary_object_count; int binary_object_size; JSShape *array_shape; /* initial shape for Array objects */ JSValue *class_proto; JSValue function_proto; JSValue function_ctor; JSValue array_ctor; JSValue regexp_ctor; JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; JSValue throw_type_error; JSValue eval_obj; JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ uint64_t random_state;#ifdef CONFIG_BIGNUM bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */ JSFloatEnv fp_env; /* global FP environment */ BOOL bignum_ext : 8; /* enable math mode */ BOOL allow_operator_overloading : 8;#endif /* when the counter reaches zero, JSRutime.interrupt_handler is called */ int interrupt_counter; BOOL is_error_property_enabled; struct list_head loaded_modules; /* list of JSModuleDef.link */ /* if NULL, RegExp compilation is not supported */ JSValue (*compile_regexp)(JSContext *ctx, JSValueConst pattern, JSValueConst flags); /* if NULL, eval is not supported */ JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); void *user_opaque;}; typedef union JSFloat64Union { double d; uint64_t u64; uint32_t u32[2];} JSFloat64Union; enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, JS_ATOM_TYPE_SYMBOL, JS_ATOM_TYPE_PRIVATE,}; enum { JS_ATOM_HASH_SYMBOL, JS_ATOM_HASH_PRIVATE,}; typedef enum { JS_ATOM_KIND_STRING, JS_ATOM_KIND_SYMBOL, JS_ATOM_KIND_PRIVATE,Lines 1–500 of 53859. Load more
/* * QuickJS Javascript Engine * * Copyright (c) 2017-2020 Fabrice Bellard * Copyright (c) 2017-2020 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. */ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> #include <inttypes.h> #include <string.h> #include <assert.h> #include <sys/time.h> #include <time.h> #include <fenv.h> #include <math.h> #if defined(__APPLE__) #include <malloc/malloc.h> #elif defined(__linux__) #include <malloc.h> #endif #include "cutils.h" #include "list.h" #include "quickjs.h" #include "libregexp.h" #ifdef CONFIG_BIGNUM #include "libbf.h" #endif #define OPTIMIZE 1 #define SHORT_OPCODES 1 #if defined(EMSCRIPTEN) || defined(__plan9__) #define DIRECT_DISPATCH 0 #else #define DIRECT_DISPATCH 1 #endif #if defined(__APPLE__) #define MALLOC_OVERHEAD 0 #else #define MALLOC_OVERHEAD 8 #endif #if !defined(_WIN32) /* define it if printf uses the RNDN rounding mode instead of RNDNA */ #define CONFIG_PRINTF_RNDN #endif /* define to include Atomics.* operations which depend on the OS threads */ #if !defined(EMSCRIPTEN) && !defined(__plan9__) #define CONFIG_ATOMICS #endif #if !defined(EMSCRIPTEN) && !defined(__plan9__) /* enable stack limitation */ #define CONFIG_STACK_CHECK #endif /* dump object free */ //#define DUMP_FREE //#define DUMP_CLOSURE /* dump the bytecode of the compiled functions: combination of bits 1: dump pass 3 final byte code 2: dump pass 2 code 4: dump pass 1 code 8: dump stdlib functions 16: dump bytecode in hex 32: dump line number table */ //#define DUMP_BYTECODE (1) /* dump the occurence of the automatic GC */ //#define DUMP_GC /* dump objects freed by the garbage collector */ //#define DUMP_GC_FREE /* dump objects leaking when freeing the runtime */ //#define DUMP_LEAKS 1 /* dump memory usage before running the garbage collector */ //#define DUMP_MEM //#define DUMP_OBJECTS /* dump objects in JS_FreeContext */ //#define DUMP_ATOMS /* dump atoms in JS_FreeContext */ //#define DUMP_SHAPES /* dump shapes in JS_FreeContext */ //#define DUMP_MODULE_RESOLVE //#define DUMP_PROMISE //#define DUMP_READ_OBJECT /* test the GC by forcing it before each object allocation */ //#define FORCE_GC_AT_MALLOC #ifdef CONFIG_ATOMICS #include <pthread.h> #include <stdatomic.h> #include <errno.h> #endif enum { /* classid tag */ /* union usage | properties */ JS_CLASS_OBJECT = 1, /* must be first */ JS_CLASS_ARRAY, /* u.array | length */ JS_CLASS_ERROR, JS_CLASS_NUMBER, /* u.object_data */ JS_CLASS_STRING, /* u.object_data */ JS_CLASS_BOOLEAN, /* u.object_data */ JS_CLASS_SYMBOL, /* u.object_data */ JS_CLASS_ARGUMENTS, /* u.array | length */ JS_CLASS_MAPPED_ARGUMENTS, /* | length */ JS_CLASS_DATE, /* u.object_data */ JS_CLASS_MODULE_NS, JS_CLASS_C_FUNCTION, /* u.cfunc */ JS_CLASS_BYTECODE_FUNCTION, /* u.func */ JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ JS_CLASS_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_FOR_IN_ITERATOR, /* u.for_in_iterator */ JS_CLASS_REGEXP, /* u.regexp */ JS_CLASS_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_SHARED_ARRAY_BUFFER, /* u.array_buffer */ JS_CLASS_UINT8C_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT8_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT16_ARRAY, /* u.array (typed_array) */ JS_CLASS_INT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */ #ifdef CONFIG_BIGNUM JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */ #endif JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */ JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */ JS_CLASS_DATAVIEW, /* u.typed_array */ #ifdef CONFIG_BIGNUM JS_CLASS_BIG_INT, /* u.object_data */ JS_CLASS_BIG_FLOAT, /* u.object_data */ JS_CLASS_FLOAT_ENV, /* u.float_env */ JS_CLASS_BIG_DECIMAL, /* u.object_data */ JS_CLASS_OPERATOR_SET, /* u.operator_set */ #endif JS_CLASS_MAP, /* u.map_state */ JS_CLASS_SET, /* u.map_state */ JS_CLASS_WEAKMAP, /* u.map_state */ JS_CLASS_WEAKSET, /* u.map_state */ JS_CLASS_MAP_ITERATOR, /* u.map_iterator_data */ JS_CLASS_SET_ITERATOR, /* u.map_iterator_data */ JS_CLASS_ARRAY_ITERATOR, /* u.array_iterator_data */ JS_CLASS_STRING_ITERATOR, /* u.array_iterator_data */ JS_CLASS_REGEXP_STRING_ITERATOR, /* u.regexp_string_iterator_data */ JS_CLASS_GENERATOR, /* u.generator_data */ JS_CLASS_PROXY, /* u.proxy_data */ JS_CLASS_PROMISE, /* u.promise_data */ JS_CLASS_PROMISE_RESOLVE_FUNCTION, /* u.promise_function_data */ JS_CLASS_PROMISE_REJECT_FUNCTION, /* u.promise_function_data */ JS_CLASS_ASYNC_FUNCTION, /* u.func */ JS_CLASS_ASYNC_FUNCTION_RESOLVE, /* u.async_function_data */ JS_CLASS_ASYNC_FUNCTION_REJECT, /* u.async_function_data */ JS_CLASS_ASYNC_FROM_SYNC_ITERATOR, /* u.async_from_sync_iterator_data */ JS_CLASS_ASYNC_GENERATOR_FUNCTION, /* u.func */ JS_CLASS_ASYNC_GENERATOR, /* u.async_generator_data */ JS_CLASS_INIT_COUNT, /* last entry for predefined classes */ }; /* number of typed array types */ #define JS_TYPED_ARRAY_COUNT (JS_CLASS_FLOAT64_ARRAY - JS_CLASS_UINT8C_ARRAY + 1) static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT]; #define typed_array_size_log2(classid) (typed_array_size_log2[(classid)- JS_CLASS_UINT8C_ARRAY]) typedef enum JSErrorEnum { JS_EVAL_ERROR, JS_RANGE_ERROR, JS_REFERENCE_ERROR, JS_SYNTAX_ERROR, JS_TYPE_ERROR, JS_URI_ERROR, JS_INTERNAL_ERROR, JS_AGGREGATE_ERROR, JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */ } JSErrorEnum; #define JS_MAX_LOCAL_VARS 65536 #define JS_STACK_SIZE_MAX 65534 #define JS_STRING_LEN_MAX ((1 << 30) - 1) #define __exception __attribute__((warn_unused_result)) typedef struct JSShape JSShape; typedef struct JSString JSString; typedef struct JSString JSAtomStruct; typedef enum { JS_GC_PHASE_NONE, JS_GC_PHASE_DECREF, JS_GC_PHASE_REMOVE_CYCLES, } JSGCPhaseEnum; typedef enum OPCodeEnum { #define FMT(f) #define DEF(id, size, n_pop, n_push, f) OP_ ## id, #define def(id, size, n_pop, n_push, f) #include "quickjs-opcode.h" #undef def #undef DEF #undef FMT OP_COUNT, /* excluding temporary opcodes */ /* temporary opcodes : overlap with the short opcodes */ OP_TEMP_START = OP_nop + 1, OP___dummy = OP_TEMP_START - 1, #define FMT(f) #define DEF(id, size, n_pop, n_push, f) #define def(id, size, n_pop, n_push, f) OP_ ## id, #include "quickjs-opcode.h" #undef def #undef DEF #undef FMT OP_TEMP_END, } OPCodeEnum; #ifdef CONFIG_BIGNUM /* function pointers are used for numeric operations so that it is possible to remove some numeric types */ typedef struct { JSValue (*to_string)(JSContext *ctx, JSValueConst val); JSValue (*from_string)(JSContext *ctx, const char *buf, int radix, int flags, slimb_t *pexponent); int (*unary_arith)(JSContext *ctx, JSValue *pres, OPCodeEnum op, JSValue op1); int (*binary_arith)(JSContext *ctx, OPCodeEnum op, JSValue *pres, JSValue op1, JSValue op2); int (*compare)(JSContext *ctx, OPCodeEnum op, JSValue op1, JSValue op2); /* only for bigfloat: */ JSValue (*mul_pow10_to_float64)(JSContext *ctx, const bf_t *a, int64_t exponent); int (*mul_pow10)(JSContext *ctx, JSValue *sp); } JSNumericOperations; #endif struct JSRuntime { JSMallocFunctions mf; JSMallocState malloc_state; const char *rt_info; int atom_hash_size; /* power of two */ int atom_count; int atom_size; int atom_count_resize; /* resize hash table at this count */ uint32_t *atom_hash; JSAtomStruct **atom_array; int atom_free_index; /* 0 = none */ int class_count; /* size of class_array */ JSClass *class_array; struct list_head context_list; /* list of JSContext.link */ /* list of JSGCObjectHeader.link. List of allocated GC objects (used by the garbage collector) */ struct list_head gc_obj_list; /* list of JSGCObjectHeader.link. Used during JS_FreeValueRT() */ struct list_head gc_zero_ref_count_list; struct list_head tmp_obj_list; /* used during GC */ JSGCPhaseEnum gc_phase : 8; size_t malloc_gc_threshold; #ifdef DUMP_LEAKS struct list_head string_list; /* list of JSString.link */ #endif /* stack limitation */ const uint8_t *stack_top; size_t stack_size; /* in bytes */ JSValue current_exception; /* true if inside an out of memory error, to avoid recursing */ BOOL in_out_of_memory : 8; struct JSStackFrame *current_stack_frame; JSInterruptHandler *interrupt_handler; void *interrupt_opaque; JSHostPromiseRejectionTracker *host_promise_rejection_tracker; void *host_promise_rejection_tracker_opaque; struct list_head job_list; /* list of JSJobEntry.link */ JSModuleNormalizeFunc *module_normalize_func; JSModuleLoaderFunc *module_loader_func; void *module_loader_opaque; BOOL can_block : 8; /* TRUE if Atomics.wait can block */ /* used to allocate, free and clone SharedArrayBuffers */ JSSharedArrayBufferFunctions sab_funcs; /* Shape hash table */ int shape_hash_bits; int shape_hash_size; int shape_hash_count; /* number of hashed shapes */ JSShape **shape_hash; #ifdef CONFIG_BIGNUM bf_context_t bf_ctx; JSNumericOperations bigint_ops; JSNumericOperations bigfloat_ops; JSNumericOperations bigdecimal_ops; uint32_t operator_count; #endif void *user_opaque; }; struct JSClass { uint32_t class_id; /* 0 means free entry */ JSAtom class_name; JSClassFinalizer *finalizer; JSClassGCMark *gc_mark; JSClassCall *call; /* pointers for exotic behavior, can be NULL if none are present */ const JSClassExoticMethods *exotic; }; #define JS_MODE_STRICT (1 << 0) #define JS_MODE_STRIP (1 << 1) #define JS_MODE_MATH (1 << 2) typedef struct JSStackFrame { struct JSStackFrame *prev_frame; /* NULL if first stack frame */ JSValue cur_func; /* current function, JS_UNDEFINED if the frame is detached */ JSValue *arg_buf; /* arguments */ JSValue *var_buf; /* variables */ struct list_head var_ref_list; /* list of JSVarRef.link */ const uint8_t *cur_pc; /* only used in bytecode functions : PC of the instruction after the call */ int arg_count; int js_mode; /* 0 or JS_MODE_MATH for C functions */ /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; } JSStackFrame; typedef enum { JS_GC_OBJ_TYPE_JS_OBJECT, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE, JS_GC_OBJ_TYPE_SHAPE, JS_GC_OBJ_TYPE_VAR_REF, JS_GC_OBJ_TYPE_ASYNC_FUNCTION, JS_GC_OBJ_TYPE_JS_CONTEXT, } JSGCObjectTypeEnum; /* header for GC objects. GC objects are C data structures with a reference count that can reference other GC objects. JS Objects are a particular type of GC object. */ struct JSGCObjectHeader { int ref_count; /* must come first, 32-bit */ JSGCObjectTypeEnum gc_obj_type : 4; uint8_t mark : 4; /* used by the GC */ uint8_t dummy1; /* not used by the GC */ uint16_t dummy2; /* not used by the GC */ struct list_head link; }; typedef struct JSVarRef { union { JSGCObjectHeader header; /* must come first */ struct { int __gc_ref_count; /* corresponds to header.ref_count */ uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ /* 0 : the JSVarRef is on the stack. header.link is an element of JSStackFrame.var_ref_list. 1 : the JSVarRef is detached. header.link has the normal meanning */ uint8_t is_detached : 1; uint8_t is_arg : 1; uint16_t var_idx; /* index of the corresponding function variable on the stack */ }; }; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ JSValue value; /* used when the variable is no longer on the stack */ } JSVarRef; #ifdef CONFIG_BIGNUM typedef struct JSFloatEnv { limb_t prec; bf_flags_t flags; unsigned int status; } JSFloatEnv; /* the same structure is used for big integers and big floats. Big integers are never infinite or NaNs */ typedef struct JSBigFloat { JSRefCountHeader header; /* must come first, 32-bit */ bf_t num; } JSBigFloat; typedef struct JSBigDecimal { JSRefCountHeader header; /* must come first, 32-bit */ bfdec_t num; } JSBigDecimal; #endif typedef enum { JS_AUTOINIT_ID_PROTOTYPE, JS_AUTOINIT_ID_MODULE_NS, JS_AUTOINIT_ID_PROP, } JSAutoInitIDEnum; /* must be large enough to have a negligible runtime cost and small enough to call the interrupt callback often. */ #define JS_INTERRUPT_COUNTER_INIT 10000 struct JSContext { JSGCObjectHeader header; /* must come first */ JSRuntime *rt; struct list_head link; uint16_t binary_object_count; int binary_object_size; JSShape *array_shape; /* initial shape for Array objects */ JSValue *class_proto; JSValue function_proto; JSValue function_ctor; JSValue array_ctor; JSValue regexp_ctor; JSValue promise_ctor; JSValue native_error_proto[JS_NATIVE_ERROR_COUNT]; JSValue iterator_proto; JSValue async_iterator_proto; JSValue array_proto_values; JSValue throw_type_error; JSValue eval_obj; JSValue global_obj; /* global object */ JSValue global_var_obj; /* contains the global let/const definitions */ uint64_t random_state; #ifdef CONFIG_BIGNUM bf_context_t *bf_ctx; /* points to rt->bf_ctx, shared by all contexts */ JSFloatEnv fp_env; /* global FP environment */ BOOL bignum_ext : 8; /* enable math mode */ BOOL allow_operator_overloading : 8; #endif /* when the counter reaches zero, JSRutime.interrupt_handler is called */ int interrupt_counter; BOOL is_error_property_enabled; struct list_head loaded_modules; /* list of JSModuleDef.link */ /* if NULL, RegExp compilation is not supported */ JSValue (*compile_regexp)(JSContext *ctx, JSValueConst pattern, JSValueConst flags); /* if NULL, eval is not supported */ JSValue (*eval_internal)(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int flags, int scope_idx); void *user_opaque; }; typedef union JSFloat64Union { double d; uint64_t u64; uint32_t u32[2]; } JSFloat64Union; enum { JS_ATOM_TYPE_STRING = 1, JS_ATOM_TYPE_GLOBAL_SYMBOL, JS_ATOM_TYPE_SYMBOL, JS_ATOM_TYPE_PRIVATE, }; enum { JS_ATOM_HASH_SYMBOL, JS_ATOM_HASH_PRIVATE, }; typedef enum { JS_ATOM_KIND_STRING, JS_ATOM_KIND_SYMBOL, JS_ATOM_KIND_PRIVATE,