53859 lines · 1.7 MB · C
RawDownload
/* * 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t