packages feed

quickjs-hs 0.1.2.3 → 0.1.2.4

raw patch · 9 files changed

+50979/−50645 lines, 9 filesdep ~QuickCheck

Dependency ranges changed: QuickCheck

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for quickjs-hs +### 0.1.2.4++* Bumped the quickjs library to 2020-11-08 release+* Relaxed QuickCheck bounds (PR by poscat0x04)+ ### 0.1.2.3  * Fix for infinite loop caused by incorrect defintion of SomeJSRuntimeException
quickjs-hs.cabal view
@@ -1,6 +1,6 @@ cabal-version:  1.12 name:           quickjs-hs-version:        0.1.2.3+version:        0.1.2.4 homepage:       https://github.com/goodlyrottenapple/quickjs-hs#readme bug-reports:    https://github.com/goodlyrottenapple/quickjs-hs/issues author:         Sam Balco@@ -71,7 +71,7 @@    cc-options:      -static -D_GNU_SOURCE -    -DCONFIG_VERSION="2020-09-06"+    -DCONFIG_VERSION="2020-11-08"     -DCONFIG_BIGNUM  test-suite quickjs-hs-test@@ -87,7 +87,7 @@     , aeson     , exceptions     , HUnit                >=1.6.0.0  && <1.7-    , QuickCheck           >=2.9  && <2.14+    , QuickCheck           >=2.9  && <2.15     , tasty                >=1.0  && <1.3     , tasty-hunit          >=0.10 && <0.11     , tasty-quickcheck     >=0.9  && <0.11
quickjs/libbf.h view
@@ -27,7 +27,7 @@ #include <stddef.h> #include <stdint.h> -#if defined(__x86_64__)+#if INTPTR_MAX >= INT64_MAX #define LIMB_LOG2_BITS 6 #else #define LIMB_LOG2_BITS 5
quickjs/libregexp.c view
@@ -75,7 +75,7 @@     int capture_count;     int total_capture_count; /* -1 = not computed yet */     int has_named_captures; /* -1 = don't know, 0 = no, 1 = yes */-    void *mem_opaque;+    void *opaque;     DynBuf group_names;     union {         char error_msg[TMP_BUF_SIZE];@@ -230,7 +230,7 @@     invert = c & 1;     c_pt = char_range_table[c >> 1];     len = *c_pt++;-    cr_init(cr, s->mem_opaque, lre_realloc);+    cr_init(cr, s->opaque, lre_realloc);     for(i = 0; i < len * 2; i++) {         if (cr_add_point(cr, c_pt[i]))             goto fail;@@ -625,7 +625,7 @@     p++;     q = name;     while (is_unicode_char(*p)) {-        if ((q - name) > sizeof(name) - 1)+        if ((q - name) >= sizeof(name) - 1)             goto unknown_property_name;         *q++ = *p++;     }@@ -634,7 +634,7 @@     if (*p == '=') {         p++;         while (is_unicode_char(*p)) {-            if ((q - value) > sizeof(value) - 1)+            if ((q - value) >= sizeof(value) - 1)                 return re_parse_error(s, "unknown unicode property value");             *q++ = *p++;         }@@ -651,7 +651,7 @@     } else if (!strcmp(name, "Script_Extensions") || !strcmp(name, "scx")) {         script_ext = TRUE;     do_script:-        cr_init(cr, s->mem_opaque, lre_realloc);+        cr_init(cr, s->opaque, lre_realloc);         ret = unicode_script(cr, value, script_ext);         if (ret) {             cr_free(cr);@@ -661,7 +661,7 @@                 goto out_of_memory;         }     } else if (!strcmp(name, "General_Category") || !strcmp(name, "gc")) {-        cr_init(cr, s->mem_opaque, lre_realloc);+        cr_init(cr, s->opaque, lre_realloc);         ret = unicode_general_category(cr, value);         if (ret) {             cr_free(cr);@@ -671,7 +671,7 @@                 goto out_of_memory;         }     } else if (value[0] == '\0') {-        cr_init(cr, s->mem_opaque, lre_realloc);+        cr_init(cr, s->opaque, lre_realloc);         ret = unicode_general_category(cr, name);         if (ret == -1) {             cr_free(cr);@@ -864,7 +864,7 @@     CharRange cr1_s, *cr1 = &cr1_s;     BOOL invert;     -    cr_init(cr, s->mem_opaque, lre_realloc);+    cr_init(cr, s->opaque, lre_realloc);     p = *pp;     p++;    /* skip '[' */     invert = FALSE;@@ -1147,9 +1147,13 @@                         }                     }                     capture_index++;+                    if (capture_index >= CAPTURE_COUNT_MAX)+                        goto done;                 }             } else {                 capture_index++;+                if (capture_index >= CAPTURE_COUNT_MAX)+                    goto done;             }             break;         case '\\':@@ -1163,6 +1167,7 @@             break;         }     }+ done:     if (capture_name)         return -1;     else@@ -1734,6 +1739,9 @@ {     int start, len, pos; +    if (lre_check_stack_overflow(s->opaque, 0))+        return re_parse_error(s, "stack overflow");+         start = s->byte_code.size;     if (re_parse_alternative(s, is_backward_dir))         return -1;@@ -1819,7 +1827,7 @@     BOOL is_sticky;          memset(s, 0, sizeof(*s));-    s->mem_opaque = opaque;+    s->opaque = opaque;     s->buf_ptr = (const uint8_t *)buf;     s->buf_end = s->buf_ptr + buf_len;     s->buf_start = s->buf_ptr;
quickjs/quickjs-atom.h view
@@ -113,6 +113,7 @@ DEF(_eval_, "<eval>") DEF(_ret_, "<ret>") DEF(_var_, "<var>")+DEF(_arg_var_, "<arg_var>") DEF(_with_, "<with>") DEF(lastIndex, "lastIndex") DEF(target, "target")
quickjs/quickjs-libc.c view
@@ -623,6 +623,97 @@         return JS_NewString(ctx, str); } +#if defined(_WIN32)+static void setenv(const char *name, const char *value, int overwrite)+{+    char *str;+    size_t name_len, value_len;+    name_len = strlen(name);+    value_len = strlen(value);+    str = malloc(name_len + 1 + value_len + 1);+    memcpy(str, name, name_len);+    str[name_len] = '=';+    memcpy(str + name_len + 1, value, value_len);+    str[name_len + 1 + value_len] = '\0';+    _putenv(str);+    free(str);+}++static void unsetenv(const char *name)+{+    setenv(name, "", TRUE);+}+#endif /* _WIN32 */++static JSValue js_std_setenv(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv)+{+    const char *name, *value;+    name = JS_ToCString(ctx, argv[0]);+    if (!name)+        return JS_EXCEPTION;+    value = JS_ToCString(ctx, argv[1]);+    if (!value) {+        JS_FreeCString(ctx, name);+        return JS_EXCEPTION;+    }+    setenv(name, value, TRUE);+    JS_FreeCString(ctx, name);+    JS_FreeCString(ctx, value);+    return JS_UNDEFINED;+}++static JSValue js_std_unsetenv(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    const char *name;+    name = JS_ToCString(ctx, argv[0]);+    if (!name)+        return JS_EXCEPTION;+    unsetenv(name);+    JS_FreeCString(ctx, name);+    return JS_UNDEFINED;+}++/* return an object containing the list of the available environment+   variables. */+static JSValue js_std_getenviron(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    char **envp;+    const char *name, *p, *value;+    JSValue obj;+    uint32_t idx;+    size_t name_len;+    JSAtom atom;+    int ret;++    obj = JS_NewObject(ctx);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    envp = environ;+    for(idx = 0; envp[idx] != NULL; idx++) {+        name = envp[idx];+        p = strchr(name, '=');+        name_len = p - name;+        if (!p)+            continue;+        value = p + 1;+        atom = JS_NewAtomLen(ctx, name, name_len);+        if (atom == JS_ATOM_NULL)+            goto fail;+        ret = JS_DefinePropertyValue(ctx, obj, atom, JS_NewString(ctx, value),+                                     JS_PROP_C_W_E);+        JS_FreeAtom(ctx, atom);+        if (ret < 0)+            goto fail;+    }+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}+ static JSValue js_std_gc(JSContext *ctx, JSValueConst this_val,                          int argc, JSValueConst *argv) {@@ -1395,6 +1486,9 @@     JS_CFUNC_DEF("evalScript", 1, js_evalScript ),     JS_CFUNC_DEF("loadScript", 1, js_loadScript ),     JS_CFUNC_DEF("getenv", 1, js_std_getenv ),+    JS_CFUNC_DEF("setenv", 1, js_std_setenv ),+    JS_CFUNC_DEF("unsetenv", 1, js_std_unsetenv ),+    JS_CFUNC_DEF("getenviron", 1, js_std_getenviron ),     JS_CFUNC_DEF("urlGet", 1, js_std_urlGet ),     JS_CFUNC_DEF("loadFile", 1, js_std_loadFile ),     JS_CFUNC_DEF("strerror", 1, js_std_strerror ),@@ -1412,7 +1506,6 @@     JS_PROP_INT32_DEF("SEEK_CUR", SEEK_CUR, JS_PROP_CONFIGURABLE ),     JS_PROP_INT32_DEF("SEEK_END", SEEK_END, JS_PROP_CONFIGURABLE ),     JS_OBJECT_DEF("Error", js_std_error_props, countof(js_std_error_props), JS_PROP_CONFIGURABLE),-    /* setenv, ... */ };      static const JSCFunctionListEntry js_std_file_proto_funcs[] = {
quickjs/quickjs-opcode.h view
@@ -114,7 +114,7 @@ DEF(      add_brand, 1, 2, 0, none) /* this_obj home_obj -> */ DEF(   return_async, 1, 1, 0, none) DEF(          throw, 1, 1, 0, none)-DEF(      throw_var, 6, 0, 0, atom_u8)+DEF(    throw_error, 6, 0, 0, atom_u8) DEF(           eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */ DEF(     apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */ DEF(         regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a@@ -205,16 +205,15 @@ DEF(for_await_of_start, 1, 1, 3, none) DEF(    for_in_next, 1, 1, 3, none) DEF(    for_of_next, 2, 3, 5, u8)-DEF(for_await_of_next, 1, 3, 4, none)+DEF(iterator_check_object, 1, 1, 1, none) DEF(iterator_get_value_done, 1, 1, 2, none) DEF( iterator_close, 1, 3, 0, none) DEF(iterator_close_return, 1, 4, 4, none)-DEF(async_iterator_close, 1, 3, 2, none)-DEF(async_iterator_next, 1, 4, 4, none)-DEF(async_iterator_get, 2, 4, 5, u8)+DEF(  iterator_next, 1, 4, 4, none)+DEF(  iterator_call, 2, 4, 5, u8) DEF(  initial_yield, 1, 0, 0, none) DEF(          yield, 1, 1, 2, none)-DEF(     yield_star, 1, 2, 2, none)+DEF(     yield_star, 1, 1, 2, none) DEF(async_yield_star, 1, 1, 2, none) DEF(          await, 1, 1, 1, none) @@ -265,8 +264,6 @@ DEF(            nop, 1, 0, 0, none)   /* temporary opcodes: never emitted in the final bytecode */--def(set_arg_valid_upto, 3, 0, 0, arg) /* emitted in phase 1, removed in phase 2 */  def(    enter_scope, 3, 0, 0, u16)  /* emitted in phase 1, removed in phase 2 */ def(    leave_scope, 3, 0, 0, u16)  /* emitted in phase 1, removed in phase 2 */
quickjs/quickjs.c view
@@ -199,50627 +199,50852 @@ } JSErrorEnum;  #define JS_MAX_LOCAL_VARS 65536-#define JS_STACK_SIZE_MAX 65536-#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 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,-} JSAtomKindEnum;--#define JS_ATOM_HASH_MASK  ((1 << 30) - 1)--struct JSString {-    JSRefCountHeader header; /* must come first, 32-bit */-    uint32_t len : 31;-    uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */-    /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3,-       for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3-       XXX: could change encoding to have one more bit in hash */-    uint32_t hash : 30;-    uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */-    uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */-#ifdef DUMP_LEAKS-    struct list_head link; /* string list */-#endif-    union {-        uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */-        uint16_t str16[0];-    } u;-};--typedef struct JSClosureVar {-    uint8_t is_local : 1;-    uint8_t is_arg : 1;-    uint8_t is_const : 1;-    uint8_t is_lexical : 1;-    uint8_t var_kind : 3; /* see JSVarKindEnum */-    /* 9 bits available */-    uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the-                    parent function. otherwise: index to a closure-                    variable of the parent function */-    JSAtom var_name;-} JSClosureVar;--typedef struct JSVarScope {-    int parent;  /* index into fd->scopes of the enclosing scope */-    int first;   /* index into fd->vars of the last variable in this scope */-} JSVarScope;--typedef enum {-    /* XXX: add more variable kinds here instead of using bit fields */-    JS_VAR_NORMAL,-    JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */-    JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator-                                 function declaration */-    JS_VAR_CATCH,-    JS_VAR_PRIVATE_FIELD,-    JS_VAR_PRIVATE_METHOD,-    JS_VAR_PRIVATE_GETTER,-    JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */-    JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */-} JSVarKindEnum;--typedef struct JSVarDef {-    JSAtom var_name;-    int scope_level;   /* index into fd->scopes of this variable lexical scope */-    int scope_next;    /* index into fd->vars of the next variable in the-                        * same or enclosing lexical scope */-    uint8_t is_func_var : 1; /* used for the function self reference */-    uint8_t is_const : 1;-    uint8_t is_lexical : 1;-    uint8_t is_captured : 1;-    uint8_t var_kind : 4; /* see JSVarKindEnum */-    /* only used during compilation: function pool index for lexical-       variables with var_kind =-       JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of-       the definition of the 'var' variables (they have scope_level =-       0) */-    int func_pool_or_scope_idx : 24; /* only used during compilation */-} JSVarDef;--/* for the encoding of the pc2line table */-#define PC2LINE_BASE     (-1)-#define PC2LINE_RANGE    5-#define PC2LINE_OP_FIRST 1-#define PC2LINE_DIFF_PC_MAX ((255 - PC2LINE_OP_FIRST) / PC2LINE_RANGE)--typedef enum JSFunctionKindEnum {-    JS_FUNC_NORMAL = 0,-    JS_FUNC_GENERATOR = (1 << 0),-    JS_FUNC_ASYNC = (1 << 1),-    JS_FUNC_ASYNC_GENERATOR = (JS_FUNC_GENERATOR | JS_FUNC_ASYNC),-} JSFunctionKindEnum;--typedef struct JSFunctionBytecode {-    JSGCObjectHeader header; /* must come first */-    uint8_t js_mode;-    uint8_t has_prototype : 1; /* true if a prototype field is necessary */-    uint8_t has_simple_parameter_list : 1;-    uint8_t is_derived_class_constructor : 1;-    /* true if home_object needs to be initialized */-    uint8_t need_home_object : 1;-    uint8_t func_kind : 2;-    uint8_t new_target_allowed : 1;-    uint8_t super_call_allowed : 1;-    uint8_t super_allowed : 1;-    uint8_t arguments_allowed : 1;-    uint8_t has_debug : 1;-    uint8_t backtrace_barrier : 1; /* stop backtrace on this function */-    uint8_t read_only_bytecode : 1;-    /* XXX: 4 bits available */-    uint8_t *byte_code_buf; /* (self pointer) */-    int byte_code_len;-    JSAtom func_name;-    JSVarDef *vardefs; /* arguments + local variables (arg_count + var_count) (self pointer) */-    JSClosureVar *closure_var; /* list of variables in the closure (self pointer) */-    uint16_t arg_count;-    uint16_t var_count;-    uint16_t defined_arg_count; /* for length function property */-    uint16_t stack_size; /* maximum stack size */-    JSContext *realm; /* function realm */-    JSValue *cpool; /* constant pool (self pointer) */-    int cpool_count;-    int closure_var_count;-    struct {-        /* debug info, move to separate structure to save memory? */-        JSAtom filename;-        int line_num;-        int source_len;-        int pc2line_len;-        uint8_t *pc2line_buf;-        char *source;-    } debug;-} JSFunctionBytecode;--typedef struct JSBoundFunction {-    JSValue func_obj;-    JSValue this_val;-    int argc;-    JSValue argv[0];-} JSBoundFunction;--typedef enum JSIteratorKindEnum {-    JS_ITERATOR_KIND_KEY,-    JS_ITERATOR_KIND_VALUE,-    JS_ITERATOR_KIND_KEY_AND_VALUE,-} JSIteratorKindEnum;--typedef struct JSForInIterator {-    JSValue obj;-    BOOL is_array;-    uint32_t array_length;-    uint32_t idx;-} JSForInIterator;--typedef struct JSRegExp {-    JSString *pattern;-    JSString *bytecode; /* also contains the flags */-} JSRegExp;--typedef struct JSProxyData {-    JSValue target;-    JSValue handler;-    uint8_t is_func;-    uint8_t is_revoked;-} JSProxyData;--typedef struct JSArrayBuffer {-    int byte_length; /* 0 if detached */-    uint8_t detached;-    uint8_t shared; /* if shared, the array buffer cannot be detached */-    uint8_t *data; /* NULL if detached */-    struct list_head array_list;-    void *opaque;-    JSFreeArrayBufferDataFunc *free_func;-} JSArrayBuffer;--typedef struct JSTypedArray {-    struct list_head link; /* link to arraybuffer */-    JSObject *obj; /* back pointer to the TypedArray/DataView object */-    JSObject *buffer; /* based array buffer */-    uint32_t offset; /* offset in the array buffer */-    uint32_t length; /* length in the array buffer */-} JSTypedArray;--typedef struct JSAsyncFunctionState {-    JSValue this_val; /* 'this' generator argument */-    int argc; /* number of function arguments */-    BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */-    JSStackFrame frame;-} JSAsyncFunctionState;--/* XXX: could use an object instead to avoid the-   JS_TAG_ASYNC_FUNCTION tag for the GC */-typedef struct JSAsyncFunctionData {-    JSGCObjectHeader header; /* must come first */-    JSValue resolving_funcs[2];-    BOOL is_active; /* true if the async function state is valid */-    JSAsyncFunctionState func_state;-} JSAsyncFunctionData;--typedef enum {-   /* binary operators */-   JS_OVOP_ADD,-   JS_OVOP_SUB,-   JS_OVOP_MUL,-   JS_OVOP_DIV,-   JS_OVOP_MOD,-   JS_OVOP_POW,-   JS_OVOP_OR,-   JS_OVOP_AND,-   JS_OVOP_XOR,-   JS_OVOP_SHL,-   JS_OVOP_SAR,-   JS_OVOP_SHR,-   JS_OVOP_EQ,-   JS_OVOP_LESS,--   JS_OVOP_BINARY_COUNT,-   /* unary operators */-   JS_OVOP_POS = JS_OVOP_BINARY_COUNT,-   JS_OVOP_NEG,-   JS_OVOP_INC,-   JS_OVOP_DEC,-   JS_OVOP_NOT,--   JS_OVOP_COUNT,-} JSOverloadableOperatorEnum;--typedef struct {-    uint32_t operator_index;-    JSObject *ops[JS_OVOP_BINARY_COUNT]; /* self operators */-} JSBinaryOperatorDefEntry;--typedef struct {-    int count;-    JSBinaryOperatorDefEntry *tab;-} JSBinaryOperatorDef;--typedef struct {-    uint32_t operator_counter;-    BOOL is_primitive; /* OperatorSet for a primitive type */-    /* NULL if no operator is defined */-    JSObject *self_ops[JS_OVOP_COUNT]; /* self operators */-    JSBinaryOperatorDef left;-    JSBinaryOperatorDef right;-} JSOperatorSetData;--typedef struct JSReqModuleEntry {-    JSAtom module_name;-    JSModuleDef *module; /* used using resolution */-} JSReqModuleEntry;--typedef enum JSExportTypeEnum {-    JS_EXPORT_TYPE_LOCAL,-    JS_EXPORT_TYPE_INDIRECT,-} JSExportTypeEnum;--typedef struct JSExportEntry {-    union {-        struct {-            int var_idx; /* closure variable index */-            JSVarRef *var_ref; /* if != NULL, reference to the variable */-        } local; /* for local export */-        int req_module_idx; /* module for indirect export */-    } u;-    JSExportTypeEnum export_type;-    JSAtom local_name; /* '*' if export ns from. not used for local-                          export after compilation */-    JSAtom export_name; /* exported variable name */-} JSExportEntry;--typedef struct JSStarExportEntry {-    int req_module_idx; /* in req_module_entries */-} JSStarExportEntry;--typedef struct JSImportEntry {-    int var_idx; /* closure variable index */-    JSAtom import_name;-    int req_module_idx; /* in req_module_entries */-} JSImportEntry;--struct JSModuleDef {-    JSRefCountHeader header; /* must come first, 32-bit */-    JSAtom module_name;-    struct list_head link;--    JSReqModuleEntry *req_module_entries;-    int req_module_entries_count;-    int req_module_entries_size;--    JSExportEntry *export_entries;-    int export_entries_count;-    int export_entries_size;--    JSStarExportEntry *star_export_entries;-    int star_export_entries_count;-    int star_export_entries_size;--    JSImportEntry *import_entries;-    int import_entries_count;-    int import_entries_size;--    JSValue module_ns;-    JSValue func_obj; /* only used for JS modules */-    JSModuleInitFunc *init_func; /* only used for C modules */-    BOOL resolved : 8;-    BOOL func_created : 8;-    BOOL instantiated : 8;-    BOOL evaluated : 8;-    BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */-    /* true if evaluation yielded an exception. It is saved in-       eval_exception */-    BOOL eval_has_exception : 8; -    JSValue eval_exception;-    JSValue meta_obj; /* for import.meta */-};--typedef struct JSJobEntry {-    struct list_head link;-    JSContext *ctx;-    JSJobFunc *job_func;-    int argc;-    JSValue argv[0];-} JSJobEntry;--typedef struct JSProperty {-    union {-        JSValue value;      /* JS_PROP_NORMAL */-        struct {            /* JS_PROP_GETSET */-            JSObject *getter; /* NULL if undefined */-            JSObject *setter; /* NULL if undefined */-        } getset;-        JSVarRef *var_ref;  /* JS_PROP_VARREF */-        struct {            /* JS_PROP_AUTOINIT */-            /* in order to use only 2 pointers, we compress the realm-               and the init function pointer */-            uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x)-                                       in the 2 low bits */-            void *opaque;-        } init;-    } u;-} JSProperty;--#define JS_PROP_INITIAL_SIZE 2-#define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */-#define JS_ARRAY_INITIAL_SIZE 2--typedef struct JSShapeProperty {-    uint32_t hash_next : 26; /* 0 if last in list */-    uint32_t flags : 6;   /* JS_PROP_XXX */-    JSAtom atom; /* JS_ATOM_NULL = free property entry */-} JSShapeProperty;--struct JSShape {-    /* hash table of size hash_mask + 1 before the start of the-       structure (see prop_hash_end()). */-    JSGCObjectHeader header;-    /* true if the shape is inserted in the shape hash table. If not,-       JSShape.hash is not valid */-    uint8_t is_hashed;-    /* If true, the shape may have small array index properties 'n' with 0-       <= n <= 2^31-1. If false, the shape is guaranteed not to have-       small array index properties */-    uint8_t has_small_array_index;-    uint32_t hash; /* current hash value */-    uint32_t prop_hash_mask;-    int prop_size; /* allocated properties */-    int prop_count; /* include deleted properties */-    int deleted_prop_count;-    JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */-    JSObject *proto;-    JSShapeProperty prop[0]; /* prop_size elements */-};--struct JSObject {-    union {-        JSGCObjectHeader header;-        struct {-            int __gc_ref_count; /* corresponds to header.ref_count */-            uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */-            -            uint8_t extensible : 1;-            uint8_t free_mark : 1; /* only used when freeing objects with cycles */-            uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */-            uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */-            uint8_t is_constructor : 1; /* TRUE if object is a constructor function */-            uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */-            uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */-            uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */-            uint16_t class_id; /* see JS_CLASS_x */-        };-    };-    /* byte offsets: 16/24 */-    JSShape *shape; /* prototype and property names + flag */-    JSProperty *prop; /* array of properties */-    /* byte offsets: 24/40 */-    struct JSMapRecord *first_weak_ref; /* XXX: use a bit and an external hash table? */-    /* byte offsets: 28/48 */-    union {-        void *opaque;-        struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */-        struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */-        struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */-        struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */-        struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */-#ifdef CONFIG_BIGNUM-        struct JSFloatEnv *float_env; /* JS_CLASS_FLOAT_ENV */-        struct JSOperatorSetData *operator_set; /* JS_CLASS_OPERATOR_SET */-#endif-        struct JSMapState *map_state;   /* JS_CLASS_MAP..JS_CLASS_WEAKSET */-        struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */-        struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */-        struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */-        struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */-        struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */-        struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */-        struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */-        struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */-        struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */-        struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */-        struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */-            /* also used by JS_CLASS_GENERATOR_FUNCTION, JS_CLASS_ASYNC_FUNCTION and JS_CLASS_ASYNC_GENERATOR_FUNCTION */-            struct JSFunctionBytecode *function_bytecode;-            JSVarRef **var_refs;-            JSObject *home_object; /* for 'super' access */-        } func;-        struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */-            JSContext *realm;-            JSCFunctionType c_function;-            uint8_t length;-            uint8_t cproto;-            int16_t magic;-        } cfunc;-        /* array part for fast arrays and typed arrays */-        struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */-            union {-                uint32_t size;          /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */-                struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */-            } u1;-            union {-                JSValue *values;        /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ -                void *ptr;              /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */-                int8_t *int8_ptr;       /* JS_CLASS_INT8_ARRAY */-                uint8_t *uint8_ptr;     /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */-                int16_t *int16_ptr;     /* JS_CLASS_INT16_ARRAY */-                uint16_t *uint16_ptr;   /* JS_CLASS_UINT16_ARRAY */-                int32_t *int32_ptr;     /* JS_CLASS_INT32_ARRAY */-                uint32_t *uint32_ptr;   /* JS_CLASS_UINT32_ARRAY */-                int64_t *int64_ptr;     /* JS_CLASS_INT64_ARRAY */-                uint64_t *uint64_ptr;   /* JS_CLASS_UINT64_ARRAY */-                float *float_ptr;       /* JS_CLASS_FLOAT32_ARRAY */-                double *double_ptr;     /* JS_CLASS_FLOAT64_ARRAY */-            } u;-            uint32_t count; /* <= 2^31-1. 0 for a detached typed array */-        } array;    /* 12/20 bytes */-        JSRegExp regexp;    /* JS_CLASS_REGEXP: 8/16 bytes */-        JSValue object_data;    /* for JS_SetObjectData(): 8/16/16 bytes */-    } u;-    /* byte sizes: 40/48/72 */-};-enum {-    __JS_ATOM_NULL = JS_ATOM_NULL,-#define DEF(name, str) JS_ATOM_ ## name,-#include "quickjs-atom.h"-#undef DEF-    JS_ATOM_END,-};-#define JS_ATOM_LAST_KEYWORD JS_ATOM_super-#define JS_ATOM_LAST_STRICT_KEYWORD JS_ATOM_yield--static const char js_atom_init[] =-#define DEF(name, str) str "\0"-#include "quickjs-atom.h"-#undef DEF-;--typedef enum OPCodeFormat {-#define FMT(f) OP_FMT_ ## f,-#define DEF(id, size, n_pop, n_push, f)-#include "quickjs-opcode.h"-#undef DEF-#undef FMT-} OPCodeFormat;--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,-};--static int JS_InitAtoms(JSRuntime *rt);-static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,-                               int atom_type);-static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);-static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);-static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,-                                  JSValueConst this_obj,-                                  int argc, JSValueConst *argv, int flags);-static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,-                                      JSValueConst this_obj,-                                      int argc, JSValueConst *argv, int flags);-static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,-                               JSValueConst this_obj, JSValueConst new_target,-                               int argc, JSValue *argv, int flags);-static JSValue JS_CallConstructorInternal(JSContext *ctx,-                                          JSValueConst func_obj,-                                          JSValueConst new_target,-                                          int argc, JSValue *argv, int flags);-static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,-                           int argc, JSValueConst *argv);-static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,-                             int argc, JSValueConst *argv);-static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,-                                            JSValue val);-static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,-                             JSValueConst val, int flags, int scope_idx);-JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);-static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);-static __maybe_unused void JS_DumpString(JSRuntime *rt,-                                                  const JSString *p);-static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);-static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);-static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);-static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,-                                                      JSValueConst val);-static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);-static __maybe_unused void JS_PrintValue(JSContext *ctx,-                                                  const char *str,-                                                  JSValueConst val);-static __maybe_unused void JS_DumpShapes(JSRuntime *rt);-static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv, int magic);-static void js_array_finalizer(JSRuntime *rt, JSValue val);-static void js_array_mark(JSRuntime *rt, JSValueConst val,-                          JS_MarkFunc *mark_func);-static void js_object_data_finalizer(JSRuntime *rt, JSValue val);-static void js_object_data_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_c_function_finalizer(JSRuntime *rt, JSValue val);-static void js_c_function_mark(JSRuntime *rt, JSValueConst val,-                               JS_MarkFunc *mark_func);-static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);-static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);-static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val);-static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_regexp_finalizer(JSRuntime *rt, JSValue val);-static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val);-static void js_typed_array_finalizer(JSRuntime *rt, JSValue val);-static void js_typed_array_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_proxy_finalizer(JSRuntime *rt, JSValue val);-static void js_proxy_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_map_finalizer(JSRuntime *rt, JSValue val);-static void js_map_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val);-static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val);-static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val);-static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_generator_finalizer(JSRuntime *rt, JSValue obj);-static void js_generator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_promise_finalizer(JSRuntime *rt, JSValue val);-static void js_promise_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val);-static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func);-#ifdef CONFIG_BIGNUM-static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);-static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,-                                 JS_MarkFunc *mark_func);-#endif-static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);-static int JS_ToBoolFree(JSContext *ctx, JSValue val);-static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);-static int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val);-static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val);-static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,-                                 JSValueConst flags);-static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,-                                              JSValue pattern, JSValue bc);-static void gc_decref(JSRuntime *rt);-static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,-                        const JSClassDef *class_def, JSAtom name);--typedef enum JSStrictEqModeEnum {-    JS_EQ_STRICT,-    JS_EQ_SAME_VALUE,-    JS_EQ_SAME_VALUE_ZERO,-} JSStrictEqModeEnum;--static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,-                          JSStrictEqModeEnum eq_mode);-static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2);-static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2);-static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2);-static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);-static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);-static JSProperty *add_property(JSContext *ctx,-                                JSObject *p, JSAtom prop, int prop_flags);-#ifdef CONFIG_BIGNUM-static void js_float_env_finalizer(JSRuntime *rt, JSValue val);-static JSValue JS_NewBigFloat(JSContext *ctx);-static inline bf_t *JS_GetBigFloat(JSValueConst val)-{-    JSBigFloat *p = JS_VALUE_GET_PTR(val);-    return &p->num;-}-static JSValue JS_NewBigDecimal(JSContext *ctx);-static inline bfdec_t *JS_GetBigDecimal(JSValueConst val)-{-    JSBigDecimal *p = JS_VALUE_GET_PTR(val);-    return &p->num;-}-static JSValue JS_NewBigInt(JSContext *ctx);-static inline bf_t *JS_GetBigInt(JSValueConst val)-{-    JSBigFloat *p = JS_VALUE_GET_PTR(val);-    return &p->num;-}-static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,-                                 BOOL convert_to_safe_integer);-static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);-static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);-static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);-static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val);-static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,-                                   BOOL allow_null_or_undefined);-static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val);-#endif-JSValue JS_ThrowOutOfMemory(JSContext *ctx);-static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);-static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);-static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,-                                   JSValueConst proto_val, BOOL throw_flag);-static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);-static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);-static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);-static int JS_CreateProperty(JSContext *ctx, JSObject *p,-                             JSAtom prop, JSValueConst val,-                             JSValueConst getter, JSValueConst setter,-                             int flags);-static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);-static void reset_weak_ref(JSRuntime *rt, JSObject *p);-static JSValue js_array_buffer_constructor3(JSContext *ctx,-                                            JSValueConst new_target,-                                            uint64_t len, JSClassID class_id,-                                            uint8_t *buf,-                                            JSFreeArrayBufferDataFunc *free_func,-                                            void *opaque, BOOL alloc_flag);-static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj);-static JSValue js_typed_array_constructor(JSContext *ctx,-                                          JSValueConst this_val,-                                          int argc, JSValueConst *argv,-                                          int classid);-static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);-static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);-static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);-static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,-                             BOOL is_arg);-static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,-                                          JSValueConst this_obj,-                                          int argc, JSValueConst *argv,-                                          int flags);-static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val);-static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,-                                           JS_MarkFunc *mark_func);-static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,-                               const char *input, size_t input_len,-                               const char *filename, int flags, int scope_idx);-static void js_free_module_def(JSContext *ctx, JSModuleDef *m);-static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,-                               JS_MarkFunc *mark_func);-static JSValue js_import_meta(JSContext *ctx);-static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier);-static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);-static JSValue js_new_promise_capability(JSContext *ctx,-                                         JSValue *resolving_funcs,-                                         JSValueConst ctor);-static __exception int perform_promise_then(JSContext *ctx,-                                            JSValueConst promise,-                                            JSValueConst *resolve_reject,-                                            JSValueConst *cap_resolving_funcs);-static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv, int magic);-static int js_string_compare(JSContext *ctx,-                             const JSString *p1, const JSString *p2);-static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val);-static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,-                               JSValue prop, JSValue val, int flags);-static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val);-static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val);-static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val);-static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,-                                     JSObject *p, JSAtom prop);-static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc);-static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,-                            JS_MarkFunc *mark_func);-static void JS_AddIntrinsicBasicObjects(JSContext *ctx);-static void js_free_shape(JSRuntime *rt, JSShape *sh);-static void js_free_shape_null(JSRuntime *rt, JSShape *sh);-static int js_shape_prepare_update(JSContext *ctx, JSObject *p,-                                   JSShapeProperty **pprs);-static int init_shape_hash(JSRuntime *rt);-static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,-                                       JSValueConst obj);-static __exception int js_get_length64(JSContext *ctx, int64_t *pres,-                                       JSValueConst obj);-static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);-static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,-                               JSValueConst array_arg);-static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,-                              JSValue **arrpp, uint32_t *countp);-static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,-                                              JSValueConst sync_iter);-static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val);-static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,-                                    JS_MarkFunc *mark_func);-static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,-                                       JSValueConst this_val,-                                       int argc, JSValueConst *argv, int flags);-static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);-static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,-                          JSGCObjectTypeEnum type);-static void remove_gc_object(JSGCObjectHeader *h);-static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);-static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);-static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,-                                 void *opaque);-static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,-                                          JSAtom atom, void *opaque);-void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);--static const JSClassExoticMethods js_arguments_exotic_methods;-static const JSClassExoticMethods js_string_exotic_methods;-static const JSClassExoticMethods js_proxy_exotic_methods;-static const JSClassExoticMethods js_module_ns_exotic_methods;-static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;--static void js_trigger_gc(JSRuntime *rt, size_t size)-{-    BOOL force_gc;-#ifdef FORCE_GC_AT_MALLOC-    force_gc = TRUE;-#else-    force_gc = ((rt->malloc_state.malloc_size + size) >-                rt->malloc_gc_threshold);-#endif-    if (force_gc) {-#ifdef DUMP_GC-        printf("GC: size=%" PRIu64 "\n",-               (uint64_t)rt->malloc_state.malloc_size);-#endif-        JS_RunGC(rt);-        rt->malloc_gc_threshold = rt->malloc_state.malloc_size +-            (rt->malloc_state.malloc_size >> 1);-    }-}--static size_t js_malloc_usable_size_unknown(const void *ptr)-{-    return 0;-}--void *js_malloc_rt(JSRuntime *rt, size_t size)-{-    return rt->mf.js_malloc(&rt->malloc_state, size);-}--void js_free_rt(JSRuntime *rt, void *ptr)-{-    rt->mf.js_free(&rt->malloc_state, ptr);-}--void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size)-{-    return rt->mf.js_realloc(&rt->malloc_state, ptr, size);-}--size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr)-{-    return rt->mf.js_malloc_usable_size(ptr);-}--void *js_mallocz_rt(JSRuntime *rt, size_t size)-{-    void *ptr;-    ptr = js_malloc_rt(rt, size);-    if (!ptr)-        return NULL;-    return memset(ptr, 0, size);-}--#ifdef CONFIG_BIGNUM-/* called by libbf */-static void *js_bf_realloc(void *opaque, void *ptr, size_t size)-{-    JSRuntime *rt = opaque;-    return js_realloc_rt(rt, ptr, size);-}-#endif /* CONFIG_BIGNUM */--/* Throw out of memory in case of error */-void *js_malloc(JSContext *ctx, size_t size)-{-    void *ptr;-    ptr = js_malloc_rt(ctx->rt, size);-    if (unlikely(!ptr)) {-        JS_ThrowOutOfMemory(ctx);-        return NULL;-    }-    return ptr;-}--/* Throw out of memory in case of error */-void *js_mallocz(JSContext *ctx, size_t size)-{-    void *ptr;-    ptr = js_mallocz_rt(ctx->rt, size);-    if (unlikely(!ptr)) {-        JS_ThrowOutOfMemory(ctx);-        return NULL;-    }-    return ptr;-}--void js_free(JSContext *ctx, void *ptr)-{-    js_free_rt(ctx->rt, ptr);-}--/* Throw out of memory in case of error */-void *js_realloc(JSContext *ctx, void *ptr, size_t size)-{-    void *ret;-    ret = js_realloc_rt(ctx->rt, ptr, size);-    if (unlikely(!ret && size != 0)) {-        JS_ThrowOutOfMemory(ctx);-        return NULL;-    }-    return ret;-}--/* store extra allocated size in *pslack if successful */-void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack)-{-    void *ret;-    ret = js_realloc_rt(ctx->rt, ptr, size);-    if (unlikely(!ret && size != 0)) {-        JS_ThrowOutOfMemory(ctx);-        return NULL;-    }-    if (pslack) {-        size_t new_size = js_malloc_usable_size_rt(ctx->rt, ret);-        *pslack = (new_size > size) ? new_size - size : 0;-    }-    return ret;-}--size_t js_malloc_usable_size(JSContext *ctx, const void *ptr)-{-    return js_malloc_usable_size_rt(ctx->rt, ptr);-}--/* Throw out of memory exception in case of error */-char *js_strndup(JSContext *ctx, const char *s, size_t n)-{-    char *ptr;-    ptr = js_malloc(ctx, n + 1);-    if (ptr) {-        memcpy(ptr, s, n);-        ptr[n] = '\0';-    }-    return ptr;-}--char *js_strdup(JSContext *ctx, const char *str)-{-    return js_strndup(ctx, str, strlen(str));-}--static no_inline int js_realloc_array(JSContext *ctx, void **parray,-                                      int elem_size, int *psize, int req_size)-{-    int new_size;-    size_t slack;-    void *new_array;-    /* XXX: potential arithmetic overflow */-    new_size = max_int(req_size, *psize * 3 / 2);-    new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack);-    if (!new_array)-        return -1;-    new_size += slack / elem_size;-    *psize = new_size;-    *parray = new_array;-    return 0;-}--/* resize the array and update its size if req_size > *psize */-static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size,-                                  int *psize, int req_size)-{-    if (unlikely(req_size > *psize))-        return js_realloc_array(ctx, parray, elem_size, psize, req_size);-    else-        return 0;-}--static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)-{-    dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);-}--static inline int is_digit(int c) {-    return c >= '0' && c <= '9';-}--typedef struct JSClassShortDef {-    JSAtom class_name;-    JSClassFinalizer *finalizer;-    JSClassGCMark *gc_mark;-} JSClassShortDef;--static JSClassShortDef const js_std_class_def[] = {-    { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_OBJECT */-    { JS_ATOM_Array, js_array_finalizer, js_array_mark },       /* JS_CLASS_ARRAY */-    { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */-    { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */-    { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */-    { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */-    { JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */-    { JS_ATOM_Arguments, js_array_finalizer, js_array_mark },   /* JS_CLASS_ARGUMENTS */-    { JS_ATOM_Arguments, NULL, NULL },                          /* JS_CLASS_MAPPED_ARGUMENTS */-    { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */-    { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_MODULE_NS */-    { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */-    { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */-    { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */-    { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */-    { JS_ATOM_GeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_GENERATOR_FUNCTION */-    { JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark },      /* JS_CLASS_FOR_IN_ITERATOR */-    { JS_ATOM_RegExp, js_regexp_finalizer, NULL },                              /* JS_CLASS_REGEXP */-    { JS_ATOM_ArrayBuffer, js_array_buffer_finalizer, NULL },                   /* JS_CLASS_ARRAY_BUFFER */-    { JS_ATOM_SharedArrayBuffer, js_array_buffer_finalizer, NULL },             /* JS_CLASS_SHARED_ARRAY_BUFFER */-    { JS_ATOM_Uint8ClampedArray, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8C_ARRAY */-    { JS_ATOM_Int8Array, js_typed_array_finalizer, js_typed_array_mark },       /* JS_CLASS_INT8_ARRAY */-    { JS_ATOM_Uint8Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_UINT8_ARRAY */-    { JS_ATOM_Int16Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_INT16_ARRAY */-    { JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark },     /* JS_CLASS_UINT16_ARRAY */-    { JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_INT32_ARRAY */-    { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark },     /* JS_CLASS_UINT32_ARRAY */-#ifdef CONFIG_BIGNUM-    { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark },   /* JS_CLASS_BIG_INT64_ARRAY */-    { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark },  /* JS_CLASS_BIG_UINT64_ARRAY */-#endif-    { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark },    /* JS_CLASS_FLOAT32_ARRAY */-    { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark },    /* JS_CLASS_FLOAT64_ARRAY */-    { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark },        /* JS_CLASS_DATAVIEW */-#ifdef CONFIG_BIGNUM-    { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark },      /* JS_CLASS_BIG_INT */-    { JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark },    /* JS_CLASS_BIG_FLOAT */-    { JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL },      /* JS_CLASS_FLOAT_ENV */-    { JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark },    /* JS_CLASS_BIG_DECIMAL */-    { JS_ATOM_OperatorSet, js_operator_set_finalizer, js_operator_set_mark },    /* JS_CLASS_OPERATOR_SET */-#endif-    { JS_ATOM_Map, js_map_finalizer, js_map_mark },             /* JS_CLASS_MAP */-    { JS_ATOM_Set, js_map_finalizer, js_map_mark },             /* JS_CLASS_SET */-    { JS_ATOM_WeakMap, js_map_finalizer, js_map_mark },         /* JS_CLASS_WEAKMAP */-    { JS_ATOM_WeakSet, js_map_finalizer, js_map_mark },         /* JS_CLASS_WEAKSET */-    { JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */-    { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */-    { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */-    { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */-    { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */-    { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */-};--static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,-                            int start, int count)-{-    JSClassDef cm_s, *cm = &cm_s;-    int i, class_id;--    for(i = 0; i < count; i++) {-        class_id = i + start;-        memset(cm, 0, sizeof(*cm));-        cm->finalizer = tab[i].finalizer;-        cm->gc_mark = tab[i].gc_mark;-        if (JS_NewClass1(rt, class_id, cm, tab[i].class_name) < 0)-            return -1;-    }-    return 0;-}--#ifdef CONFIG_BIGNUM-static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "unsupported operation");-}--static JSValue invalid_to_string(JSContext *ctx, JSValueConst val)-{-    return JS_ThrowUnsupportedOperation(ctx);-}--static JSValue invalid_from_string(JSContext *ctx, const char *buf,-                                   int radix, int flags, slimb_t *pexponent)-{-    return JS_NAN;-}--static int invalid_unary_arith(JSContext *ctx,-                               JSValue *pres, OPCodeEnum op, JSValue op1)-{-    JS_FreeValue(ctx, op1);-    JS_ThrowUnsupportedOperation(ctx);-    return -1;-}--static int invalid_binary_arith(JSContext *ctx, OPCodeEnum op,-                                JSValue *pres, JSValue op1, JSValue op2)-{-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    JS_ThrowUnsupportedOperation(ctx);-    return -1;-}--static JSValue invalid_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,-                                            int64_t exponent)-{-    return JS_ThrowUnsupportedOperation(ctx);-}--static int invalid_mul_pow10(JSContext *ctx, JSValue *sp)-{-    JS_ThrowUnsupportedOperation(ctx);-    return -1;-}--static void set_dummy_numeric_ops(JSNumericOperations *ops)-{-    ops->to_string = invalid_to_string;-    ops->from_string = invalid_from_string;-    ops->unary_arith = invalid_unary_arith;-    ops->binary_arith = invalid_binary_arith;-    ops->mul_pow10_to_float64 = invalid_mul_pow10_to_float64;-    ops->mul_pow10 = invalid_mul_pow10;-}--#endif /* CONFIG_BIGNUM */--#if !defined(CONFIG_STACK_CHECK)-/* no stack limitation */-static inline uint8_t *js_get_stack_pointer(void)-{-    return NULL;-}--static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)-{-    return FALSE;-}-#else-/* Note: OS and CPU dependent */-static inline uint8_t *js_get_stack_pointer(void)-{-    return __builtin_frame_address(0);-}--static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)-{-    size_t size;-    size = rt->stack_top - js_get_stack_pointer();-    return unlikely((size + alloca_size) > rt->stack_size);-}-#endif--JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)-{-    JSRuntime *rt;-    JSMallocState ms;--    memset(&ms, 0, sizeof(ms));-    ms.opaque = opaque;-    ms.malloc_limit = -1;--    rt = mf->js_malloc(&ms, sizeof(JSRuntime));-    if (!rt)-        return NULL;-    memset(rt, 0, sizeof(*rt));-    rt->mf = *mf;-    if (!rt->mf.js_malloc_usable_size) {-        /* use dummy function if none provided */-        rt->mf.js_malloc_usable_size = js_malloc_usable_size_unknown;-    }-    rt->malloc_state = ms;-    rt->malloc_gc_threshold = 256 * 1024;--#ifdef CONFIG_BIGNUM-    bf_context_init(&rt->bf_ctx, js_bf_realloc, rt);-    set_dummy_numeric_ops(&rt->bigint_ops);-    set_dummy_numeric_ops(&rt->bigfloat_ops);-    set_dummy_numeric_ops(&rt->bigdecimal_ops);-#endif--    init_list_head(&rt->context_list);-    init_list_head(&rt->gc_obj_list);-    init_list_head(&rt->gc_zero_ref_count_list);-    rt->gc_phase = JS_GC_PHASE_NONE;-    -#ifdef DUMP_LEAKS-    init_list_head(&rt->string_list);-#endif-    init_list_head(&rt->job_list);--    if (JS_InitAtoms(rt))-        goto fail;--    /* create the object, array and function classes */-    if (init_class_range(rt, js_std_class_def, JS_CLASS_OBJECT,-                         countof(js_std_class_def)) < 0)-        goto fail;-    rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods;-    rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods;-    rt->class_array[JS_CLASS_MODULE_NS].exotic = &js_module_ns_exotic_methods;--    rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function;-    rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_c_function_data_call;-    rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function;-    rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_generator_function_call;-    if (init_shape_hash(rt))-        goto fail;--    rt->stack_top = js_get_stack_pointer();-    rt->stack_size = JS_DEFAULT_STACK_SIZE;-    rt->current_exception = JS_NULL;--    return rt;- fail:-    JS_FreeRuntime(rt);-    return NULL;-}--void *JS_GetRuntimeOpaque(JSRuntime *rt)-{-    return rt->user_opaque;-}--void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)-{-    rt->user_opaque = opaque;-}--/* default memory allocation functions with memory limitation */-static inline size_t js_def_malloc_usable_size(void *ptr)-{-#if defined(__APPLE__)-    return malloc_size(ptr);-#elif defined(_WIN32)-    return _msize(ptr);-#elif defined(EMSCRIPTEN)-    return 0;-#elif defined(__linux__)-    return malloc_usable_size(ptr);-#else-    /* change this to `return 0;` if compilation fails */-    return malloc_usable_size(ptr);-#endif-}--static void *js_def_malloc(JSMallocState *s, size_t size)-{-    void *ptr;--    /* Do not allocate zero bytes: behavior is platform dependent */-    assert(size != 0);--    if (unlikely(s->malloc_size + size > s->malloc_limit))-        return NULL;--    ptr = malloc(size);-    if (!ptr)-        return NULL;--    s->malloc_count++;-    s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;-    return ptr;-}--static void js_def_free(JSMallocState *s, void *ptr)-{-    if (!ptr)-        return;--    s->malloc_count--;-    s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;-    free(ptr);-}--static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)-{-    size_t old_size;--    if (!ptr) {-        if (size == 0)-            return NULL;-        return js_def_malloc(s, size);-    }-    old_size = js_def_malloc_usable_size(ptr);-    if (size == 0) {-        s->malloc_count--;-        s->malloc_size -= old_size + MALLOC_OVERHEAD;-        free(ptr);-        return NULL;-    }-    if (s->malloc_size + size - old_size > s->malloc_limit)-        return NULL;--    ptr = realloc(ptr, size);-    if (!ptr)-        return NULL;--    s->malloc_size += js_def_malloc_usable_size(ptr) - old_size;-    return ptr;-}--static const JSMallocFunctions def_malloc_funcs = {-    js_def_malloc,-    js_def_free,-    js_def_realloc,-#if defined(__APPLE__)-    malloc_size,-#elif defined(_WIN32)-    (size_t (*)(const void *))_msize,-#elif defined(EMSCRIPTEN)-    NULL,-#elif defined(__linux__)-    (size_t (*)(const void *))malloc_usable_size,-#else-    /* change this to `NULL,` if compilation fails */-    malloc_usable_size,-#endif-};--JSRuntime *JS_NewRuntime(void)-{-    return JS_NewRuntime2(&def_malloc_funcs, NULL);-}--void JS_SetMemoryLimit(JSRuntime *rt, size_t limit)-{-    rt->malloc_state.malloc_limit = limit;-}--/* use -1 to disable automatic GC */-void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold)-{-    rt->malloc_gc_threshold = gc_threshold;-}--#define malloc(s) malloc_is_forbidden(s)-#define free(p) free_is_forbidden(p)-#define realloc(p,s) realloc_is_forbidden(p,s)--void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque)-{-    rt->interrupt_handler = cb;-    rt->interrupt_opaque = opaque;-}--void JS_SetCanBlock(JSRuntime *rt, BOOL can_block)-{-    rt->can_block = can_block;-}--void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,-                                      const JSSharedArrayBufferFunctions *sf)-{-    rt->sab_funcs = *sf;-}--/* return 0 if OK, < 0 if exception */-int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,-                  int argc, JSValueConst *argv)-{-    JSRuntime *rt = ctx->rt;-    JSJobEntry *e;-    int i;--    e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));-    if (!e)-        return -1;-    e->ctx = ctx;-    e->job_func = job_func;-    e->argc = argc;-    for(i = 0; i < argc; i++) {-        e->argv[i] = JS_DupValue(ctx, argv[i]);-    }-    list_add_tail(&e->link, &rt->job_list);-    return 0;-}--BOOL JS_IsJobPending(JSRuntime *rt)-{-    return !list_empty(&rt->job_list);-}--/* return < 0 if exception, 0 if no job pending, 1 if a job was-   executed successfully. the context of the job is stored in '*pctx' */-int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)-{-    JSContext *ctx;-    JSJobEntry *e;-    JSValue res;-    int i, ret;--    if (list_empty(&rt->job_list)) {-        *pctx = NULL;-        return 0;-    }--    /* get the first pending job and execute it */-    e = list_entry(rt->job_list.next, JSJobEntry, link);-    list_del(&e->link);-    ctx = e->ctx;-    res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv);-    for(i = 0; i < e->argc; i++)-        JS_FreeValue(ctx, e->argv[i]);-    if (JS_IsException(res))-        ret = -1;-    else-        ret = 1;-    JS_FreeValue(ctx, res);-    js_free(ctx, e);-    *pctx = ctx;-    return ret;-}--static inline uint32_t atom_get_free(const JSAtomStruct *p)-{-    return (uintptr_t)p >> 1;-}--static inline BOOL atom_is_free(const JSAtomStruct *p)-{-    return (uintptr_t)p & 1;-}--static inline JSAtomStruct *atom_set_free(uint32_t v)-{-    return (JSAtomStruct *)(((uintptr_t)v << 1) | 1);-}--/* Note: the string contents are uninitialized */-static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char)-{-    JSString *str;-    str = js_malloc_rt(rt, sizeof(JSString) + (max_len << is_wide_char) + 1 - is_wide_char);-    if (unlikely(!str))-        return NULL;-    str->header.ref_count = 1;-    str->is_wide_char = is_wide_char;-    str->len = max_len;-    str->atom_type = 0;-    str->hash = 0;          /* optional but costless */-    str->hash_next = 0;     /* optional */-#ifdef DUMP_LEAKS-    list_add_tail(&str->link, &rt->string_list);-#endif-    return str;-}--static JSString *js_alloc_string(JSContext *ctx, int max_len, int is_wide_char)-{-    JSString *p;-    p = js_alloc_string_rt(ctx->rt, max_len, is_wide_char);-    if (unlikely(!p)) {-        JS_ThrowOutOfMemory(ctx);-        return NULL;-    }-    return p;-}--/* same as JS_FreeValueRT() but faster */-static inline void js_free_string(JSRuntime *rt, JSString *str)-{-    if (--str->header.ref_count <= 0) {-        if (str->atom_type) {-            JS_FreeAtomStruct(rt, str);-        } else {-#ifdef DUMP_LEAKS-            list_del(&str->link);-#endif-            js_free_rt(rt, str);-        }-    }-}--void JS_SetRuntimeInfo(JSRuntime *rt, const char *s)-{-    if (rt)-        rt->rt_info = s;-}--void JS_FreeRuntime(JSRuntime *rt)-{-    struct list_head *el, *el1;-    int i;--    JS_FreeValueRT(rt, rt->current_exception);--    list_for_each_safe(el, el1, &rt->job_list) {-        JSJobEntry *e = list_entry(el, JSJobEntry, link);-        for(i = 0; i < e->argc; i++)-            JS_FreeValueRT(rt, e->argv[i]);-        js_free_rt(rt, e);-    }-    init_list_head(&rt->job_list);--    JS_RunGC(rt);--#ifdef DUMP_LEAKS-    /* leaking objects */-    {-        BOOL header_done;-        JSGCObjectHeader *p;-        int count;--        /* remove the internal refcounts to display only the object-           referenced externally */-        list_for_each(el, &rt->gc_obj_list) {-            p = list_entry(el, JSGCObjectHeader, link);-            p->mark = 0;-        }-        gc_decref(rt);--        header_done = FALSE;-        list_for_each(el, &rt->gc_obj_list) {-            p = list_entry(el, JSGCObjectHeader, link);-            if (p->ref_count != 0) {-                if (!header_done) {-                    printf("Object leaks:\n");-                    JS_DumpObjectHeader(rt);-                    header_done = TRUE;-                }-                JS_DumpGCObject(rt, p);-            }-        }--        count = 0;-        list_for_each(el, &rt->gc_obj_list) {-            p = list_entry(el, JSGCObjectHeader, link);-            if (p->ref_count == 0) {-                count++;-            }-        }-        if (count != 0)-            printf("Secondary object leaks: %d\n", count);-    }-#endif-    assert(list_empty(&rt->gc_obj_list));--    /* free the classes */-    for(i = 0; i < rt->class_count; i++) {-        JSClass *cl = &rt->class_array[i];-        if (cl->class_id != 0) {-            JS_FreeAtomRT(rt, cl->class_name);-        }-    }-    js_free_rt(rt, rt->class_array);--#ifdef CONFIG_BIGNUM-    bf_context_end(&rt->bf_ctx);-#endif--#ifdef DUMP_LEAKS-    /* only the atoms defined in JS_InitAtoms() should be left */-    {-        BOOL header_done = FALSE;--        for(i = 0; i < rt->atom_size; i++) {-            JSAtomStruct *p = rt->atom_array[i];-            if (!atom_is_free(p) /* && p->str*/) {-                if (i >= JS_ATOM_END || p->header.ref_count != 1) {-                    if (!header_done) {-                        header_done = TRUE;-                        if (rt->rt_info) {-                            printf("%s:1: atom leakage:", rt->rt_info);-                        } else {-                            printf("Atom leaks:\n"-                                   "    %6s %6s %s\n",-                                   "ID", "REFCNT", "NAME");-                        }-                    }-                    if (rt->rt_info) {-                        printf(" ");-                    } else {-                        printf("    %6u %6u ", i, p->header.ref_count);-                    }-                    switch (p->atom_type) {-                    case JS_ATOM_TYPE_STRING:-                        JS_DumpString(rt, p);-                        break;-                    case JS_ATOM_TYPE_GLOBAL_SYMBOL:-                        printf("Symbol.for(");-                        JS_DumpString(rt, p);-                        printf(")");-                        break;-                    case JS_ATOM_TYPE_SYMBOL:-                        if (p->hash == JS_ATOM_HASH_SYMBOL) {-                            printf("Symbol(");-                            JS_DumpString(rt, p);-                            printf(")");-                        } else {-                            printf("Private(");-                            JS_DumpString(rt, p);-                            printf(")");-                        }-                        break;-                    }-                    if (rt->rt_info) {-                        printf(":%u", p->header.ref_count);-                    } else {-                        printf("\n");-                    }-                }-            }-        }-        if (rt->rt_info && header_done)-            printf("\n");-    }-#endif--    /* free the atoms */-    for(i = 0; i < rt->atom_size; i++) {-        JSAtomStruct *p = rt->atom_array[i];-        if (!atom_is_free(p)) {-#ifdef DUMP_LEAKS-            list_del(&p->link);-#endif-            js_free_rt(rt, p);-        }-    }-    js_free_rt(rt, rt->atom_array);-    js_free_rt(rt, rt->atom_hash);-    js_free_rt(rt, rt->shape_hash);-#ifdef DUMP_LEAKS-    if (!list_empty(&rt->string_list)) {-        if (rt->rt_info) {-            printf("%s:1: string leakage:", rt->rt_info);-        } else {-            printf("String leaks:\n"-                   "    %6s %s\n",-                   "REFCNT", "VALUE");-        }-        list_for_each_safe(el, el1, &rt->string_list) {-            JSString *str = list_entry(el, JSString, link);-            if (rt->rt_info) {-                printf(" ");-            } else {-                printf("    %6u ", str->header.ref_count);-            }-            JS_DumpString(rt, str);-            if (rt->rt_info) {-                printf(":%u", str->header.ref_count);-            } else {-                printf("\n");-            }-            list_del(&str->link);-            js_free_rt(rt, str);-        }-        if (rt->rt_info)-            printf("\n");-    }-    {-        JSMallocState *s = &rt->malloc_state;-        if (s->malloc_count > 1) {-            if (rt->rt_info)-                printf("%s:1: ", rt->rt_info);-            printf("Memory leak: %"PRIu64" bytes lost in %"PRIu64" block%s\n",-                   (uint64_t)(s->malloc_size - sizeof(JSRuntime)),-                   (uint64_t)(s->malloc_count - 1), &"s"[s->malloc_count == 2]);-        }-    }-#endif--    {-        JSMallocState ms = rt->malloc_state;-        rt->mf.js_free(&ms, rt);-    }-}--JSContext *JS_NewContextRaw(JSRuntime *rt)-{-    JSContext *ctx;-    int i;--    ctx = js_mallocz_rt(rt, sizeof(JSContext));-    if (!ctx)-        return NULL;-    ctx->header.ref_count = 1;-    add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT);--    ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) *-                                    rt->class_count);-    if (!ctx->class_proto) {-        js_free_rt(rt, ctx);-        return NULL;-    }-    ctx->rt = rt;-    list_add_tail(&ctx->link, &rt->context_list);-#ifdef CONFIG_BIGNUM-    ctx->bf_ctx = &rt->bf_ctx;-    ctx->fp_env.prec = 113;-    ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL;-#endif-    for(i = 0; i < rt->class_count; i++)-        ctx->class_proto[i] = JS_NULL;-    ctx->array_ctor = JS_NULL;-    ctx->regexp_ctor = JS_NULL;-    ctx->promise_ctor = JS_NULL;-    init_list_head(&ctx->loaded_modules);--    JS_AddIntrinsicBasicObjects(ctx);-    return ctx;-}--JSContext *JS_NewContext(JSRuntime *rt)-{-    JSContext *ctx;--    ctx = JS_NewContextRaw(rt);-    if (!ctx)-        return NULL;--    JS_AddIntrinsicBaseObjects(ctx);-    JS_AddIntrinsicDate(ctx);-    JS_AddIntrinsicEval(ctx);-    JS_AddIntrinsicStringNormalize(ctx);-    JS_AddIntrinsicRegExp(ctx);-    JS_AddIntrinsicJSON(ctx);-    JS_AddIntrinsicProxy(ctx);-    JS_AddIntrinsicMapSet(ctx);-    JS_AddIntrinsicTypedArrays(ctx);-    JS_AddIntrinsicPromise(ctx);-#ifdef CONFIG_BIGNUM-    JS_AddIntrinsicBigInt(ctx);-#endif-    return ctx;-}--void *JS_GetContextOpaque(JSContext *ctx)-{-    return ctx->user_opaque;-}--void JS_SetContextOpaque(JSContext *ctx, void *opaque)-{-    ctx->user_opaque = opaque;-}--/* set the new value and free the old value after (freeing the value-   can reallocate the object data) */-static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val)-{-    JSValue old_val;-    old_val = *pval;-    *pval = new_val;-    JS_FreeValue(ctx, old_val);-}--void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj)-{-    JSRuntime *rt = ctx->rt;-    assert(class_id < rt->class_count);-    set_value(ctx, &ctx->class_proto[class_id], obj);-}--JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id)-{-    JSRuntime *rt = ctx->rt;-    assert(class_id < rt->class_count);-    return JS_DupValue(ctx, ctx->class_proto[class_id]);-}--typedef enum JSFreeModuleEnum {-    JS_FREE_MODULE_ALL,-    JS_FREE_MODULE_NOT_RESOLVED,-    JS_FREE_MODULE_NOT_EVALUATED,-} JSFreeModuleEnum;--/* XXX: would be more efficient with separate module lists */-static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)-{-    struct list_head *el, *el1;-    list_for_each_safe(el, el1, &ctx->loaded_modules) {-        JSModuleDef *m = list_entry(el, JSModuleDef, link);-        if (flag == JS_FREE_MODULE_ALL ||-            (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) ||-            (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated)) {-            js_free_module_def(ctx, m);-        }-    }-}--JSContext *JS_DupContext(JSContext *ctx)-{-    ctx->header.ref_count++;-    return ctx;-}--/* used by the GC */-static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,-                           JS_MarkFunc *mark_func)-{-    int i;-    struct list_head *el;--    /* modules are not seen by the GC, so we directly mark the objects-       referenced by each module */-    list_for_each(el, &ctx->loaded_modules) {-        JSModuleDef *m = list_entry(el, JSModuleDef, link);-        js_mark_module_def(rt, m, mark_func);-    }--    JS_MarkValue(rt, ctx->global_obj, mark_func);-    JS_MarkValue(rt, ctx->global_var_obj, mark_func);--    JS_MarkValue(rt, ctx->throw_type_error, mark_func);-    JS_MarkValue(rt, ctx->eval_obj, mark_func);--    JS_MarkValue(rt, ctx->array_proto_values, mark_func);-    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {-        JS_MarkValue(rt, ctx->native_error_proto[i], mark_func);-    }-    for(i = 0; i < rt->class_count; i++) {-        JS_MarkValue(rt, ctx->class_proto[i], mark_func);-    }-    JS_MarkValue(rt, ctx->iterator_proto, mark_func);-    JS_MarkValue(rt, ctx->async_iterator_proto, mark_func);-    JS_MarkValue(rt, ctx->promise_ctor, mark_func);-    JS_MarkValue(rt, ctx->array_ctor, mark_func);-    JS_MarkValue(rt, ctx->regexp_ctor, mark_func);-    JS_MarkValue(rt, ctx->function_ctor, mark_func);-    JS_MarkValue(rt, ctx->function_proto, mark_func);--    if (ctx->array_shape)-        mark_func(rt, &ctx->array_shape->header);-}--void JS_FreeContext(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    int i;--    if (--ctx->header.ref_count > 0)-        return;-    assert(ctx->header.ref_count == 0);-    -#ifdef DUMP_ATOMS-    JS_DumpAtoms(ctx->rt);-#endif-#ifdef DUMP_SHAPES-    JS_DumpShapes(ctx->rt);-#endif-#ifdef DUMP_OBJECTS-    {-        struct list_head *el;-        JSGCObjectHeader *p;-        printf("JSObjects: {\n");-        JS_DumpObjectHeader(ctx->rt);-        list_for_each(el, &rt->gc_obj_list) {-            p = list_entry(el, JSGCObjectHeader, link);-            JS_DumpGCObject(rt, p);-        }-        printf("}\n");-    }-#endif-#ifdef DUMP_MEM-    {-        JSMemoryUsage stats;-        JS_ComputeMemoryUsage(rt, &stats);-        JS_DumpMemoryUsage(stdout, &stats, rt);-    }-#endif--    js_free_modules(ctx, JS_FREE_MODULE_ALL);--    JS_FreeValue(ctx, ctx->global_obj);-    JS_FreeValue(ctx, ctx->global_var_obj);--    JS_FreeValue(ctx, ctx->throw_type_error);-    JS_FreeValue(ctx, ctx->eval_obj);--    JS_FreeValue(ctx, ctx->array_proto_values);-    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {-        JS_FreeValue(ctx, ctx->native_error_proto[i]);-    }-    for(i = 0; i < rt->class_count; i++) {-        JS_FreeValue(ctx, ctx->class_proto[i]);-    }-    js_free_rt(rt, ctx->class_proto);-    JS_FreeValue(ctx, ctx->iterator_proto);-    JS_FreeValue(ctx, ctx->async_iterator_proto);-    JS_FreeValue(ctx, ctx->promise_ctor);-    JS_FreeValue(ctx, ctx->array_ctor);-    JS_FreeValue(ctx, ctx->regexp_ctor);-    JS_FreeValue(ctx, ctx->function_ctor);-    JS_FreeValue(ctx, ctx->function_proto);--    js_free_shape_null(ctx->rt, ctx->array_shape);--    list_del(&ctx->link);-    remove_gc_object(&ctx->header);-    js_free_rt(ctx->rt, ctx);-}--JSRuntime *JS_GetRuntime(JSContext *ctx)-{-    return ctx->rt;-}--void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size)-{-    rt->stack_size = stack_size;-}--static inline BOOL is_strict_mode(JSContext *ctx)-{-    JSStackFrame *sf = ctx->rt->current_stack_frame;-    return (sf && (sf->js_mode & JS_MODE_STRICT));-}--#ifdef CONFIG_BIGNUM-static inline BOOL is_math_mode(JSContext *ctx)-{-    JSStackFrame *sf = ctx->rt->current_stack_frame;-    return (sf && (sf->js_mode & JS_MODE_MATH));-}-#endif--/* JSAtom support */--#define JS_ATOM_TAG_INT (1U << 31)-#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1)-#define JS_ATOM_MAX     ((1U << 30) - 1)--/* return the max count from the hash size */-#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)--static inline BOOL __JS_AtomIsConst(JSAtom v)-{-#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1-        return (int32_t)v <= 0;-#else-        return (int32_t)v < JS_ATOM_END;-#endif-}--static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)-{-    return (v & JS_ATOM_TAG_INT) != 0;-}--static inline JSAtom __JS_AtomFromUInt32(uint32_t v)-{-    return v | JS_ATOM_TAG_INT;-}--static inline uint32_t __JS_AtomToUInt32(JSAtom atom)-{-    return atom & ~JS_ATOM_TAG_INT;-}--static inline int is_num(int c)-{-    return c >= '0' && c <= '9';-}--/* return TRUE if the string is a number n with 0 <= n <= 2^32-1 */-static inline BOOL is_num_string(uint32_t *pval, const JSString *p)-{-    uint32_t n;-    uint64_t n64;-    int c, i, len;--    len = p->len;-    if (len == 0 || len > 10)-        return FALSE;-    if (p->is_wide_char)-        c = p->u.str16[0];-    else-        c = p->u.str8[0];-    if (is_num(c)) {-        if (c == '0') {-            if (len != 1)-                return FALSE;-            n = 0;-        } else {-            n = c - '0';-            for(i = 1; i < len; i++) {-                if (p->is_wide_char)-                    c = p->u.str16[i];-                else-                    c = p->u.str8[i];-                if (!is_num(c))-                    return FALSE;-                n64 = (uint64_t)n * 10 + (c - '0');-                if ((n64 >> 32) != 0)-                    return FALSE;-                n = n64;-            }-        }-        *pval = n;-        return TRUE;-    } else {-        return FALSE;-    }-}--/* XXX: could use faster version ? */-static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h)-{-    size_t i;--    for(i = 0; i < len; i++)-        h = h * 263 + str[i];-    return h;-}--static inline uint32_t hash_string16(const uint16_t *str,-                                     size_t len, uint32_t h)-{-    size_t i;--    for(i = 0; i < len; i++)-        h = h * 263 + str[i];-    return h;-}--static uint32_t hash_string(const JSString *str, uint32_t h)-{-    if (str->is_wide_char)-        h = hash_string16(str->u.str16, str->len, h);-    else-        h = hash_string8(str->u.str8, str->len, h);-    return h;-}--static __maybe_unused void JS_DumpString(JSRuntime *rt,-                                                  const JSString *p)-{-    int i, c, sep;--    if (p == NULL) {-        printf("<null>");-        return;-    }-    printf("%d", p->header.ref_count);-    sep = (p->header.ref_count == 1) ? '\"' : '\'';-    putchar(sep);-    for(i = 0; i < p->len; i++) {-        if (p->is_wide_char)-            c = p->u.str16[i];-        else-            c = p->u.str8[i];-        if (c == sep || c == '\\') {-            putchar('\\');-            putchar(c);-        } else if (c >= ' ' && c <= 126) {-            putchar(c);-        } else if (c == '\n') {-            putchar('\\');-            putchar('n');-        } else {-            printf("\\u%04x", c);-        }-    }-    putchar(sep);-}--static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)-{-    JSAtomStruct *p;-    int h, i;-    /* This only dumps hashed atoms, not JS_ATOM_TYPE_SYMBOL atoms */-    printf("JSAtom count=%d size=%d hash_size=%d:\n",-           rt->atom_count, rt->atom_size, rt->atom_hash_size);-    printf("JSAtom hash table: {\n");-    for(i = 0; i < rt->atom_hash_size; i++) {-        h = rt->atom_hash[i];-        if (h) {-            printf("  %d:", i);-            while (h) {-                p = rt->atom_array[h];-                printf(" ");-                JS_DumpString(rt, p);-                h = p->hash_next;-            }-            printf("\n");-        }-    }-    printf("}\n");-    printf("JSAtom table: {\n");-    for(i = 0; i < rt->atom_size; i++) {-        p = rt->atom_array[i];-        if (!atom_is_free(p)) {-            printf("  %d: { %d %08x ", i, p->atom_type, p->hash);-            if (!(p->len == 0 && p->is_wide_char != 0))-                JS_DumpString(rt, p);-            printf(" %d }\n", p->hash_next);-        }-    }-    printf("}\n");-}--static int JS_ResizeAtomHash(JSRuntime *rt, int new_hash_size)-{-    JSAtomStruct *p;-    uint32_t new_hash_mask, h, i, hash_next1, j, *new_hash;--    assert((new_hash_size & (new_hash_size - 1)) == 0); /* power of two */-    new_hash_mask = new_hash_size - 1;-    new_hash = js_mallocz_rt(rt, sizeof(rt->atom_hash[0]) * new_hash_size);-    if (!new_hash)-        return -1;-    for(i = 0; i < rt->atom_hash_size; i++) {-        h = rt->atom_hash[i];-        while (h != 0) {-            p = rt->atom_array[h];-            hash_next1 = p->hash_next;-            /* add in new hash table */-            j = p->hash & new_hash_mask;-            p->hash_next = new_hash[j];-            new_hash[j] = h;-            h = hash_next1;-        }-    }-    js_free_rt(rt, rt->atom_hash);-    rt->atom_hash = new_hash;-    rt->atom_hash_size = new_hash_size;-    rt->atom_count_resize = JS_ATOM_COUNT_RESIZE(new_hash_size);-    //    JS_DumpAtoms(rt);-    return 0;-}--static int JS_InitAtoms(JSRuntime *rt)-{-    int i, len, atom_type;-    const char *p;--    rt->atom_hash_size = 0;-    rt->atom_hash = NULL;-    rt->atom_count = 0;-    rt->atom_size = 0;-    rt->atom_free_index = 0;-    if (JS_ResizeAtomHash(rt, 256))     /* there are at least 195 predefined atoms */-        return -1;--    p = js_atom_init;-    for(i = 1; i < JS_ATOM_END; i++) {-        if (i == JS_ATOM_Private_brand)-            atom_type = JS_ATOM_TYPE_PRIVATE;-        else if (i >= JS_ATOM_Symbol_toPrimitive)-            atom_type = JS_ATOM_TYPE_SYMBOL;-        else-            atom_type = JS_ATOM_TYPE_STRING;-        len = strlen(p);-        if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)-            return -1;-        p = p + len + 1;-    }-    return 0;-}--static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)-{-    JSAtomStruct *p;--    if (!__JS_AtomIsConst(v)) {-        p = rt->atom_array[v];-        p->header.ref_count++;-    }-    return v;-}--JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)-{-    JSRuntime *rt;-    JSAtomStruct *p;--    if (!__JS_AtomIsConst(v)) {-        rt = ctx->rt;-        p = rt->atom_array[v];-        p->header.ref_count++;-    }-    return v;-}--static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)-{-    JSRuntime *rt;-    JSAtomStruct *p;--    rt = ctx->rt;-    if (__JS_AtomIsTaggedInt(v))-        return JS_ATOM_KIND_STRING;-    p = rt->atom_array[v];-    switch(p->atom_type) {-    case JS_ATOM_TYPE_STRING:-        return JS_ATOM_KIND_STRING;-    case JS_ATOM_TYPE_GLOBAL_SYMBOL:-        return JS_ATOM_KIND_SYMBOL;-    case JS_ATOM_TYPE_SYMBOL:-        switch(p->hash) {-        case JS_ATOM_HASH_SYMBOL:-            return JS_ATOM_KIND_SYMBOL;-        case JS_ATOM_HASH_PRIVATE:-            return JS_ATOM_KIND_PRIVATE;-        default:-            abort();-        }-    default:-        abort();-    }-}--static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v)-{-    return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING;-}--static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)-{-    uint32_t i = p->hash_next;  /* atom_index */-    if (p->atom_type != JS_ATOM_TYPE_SYMBOL) {-        JSAtomStruct *p1;--        i = rt->atom_hash[p->hash & (rt->atom_hash_size - 1)];-        p1 = rt->atom_array[i];-        while (p1 != p) {-            assert(i != 0);-            i = p1->hash_next;-            p1 = rt->atom_array[i];-        }-    }-    return i;-}--/* string case (internal). Return JS_ATOM_NULL if error. 'str' is-   freed. */-static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)-{-    uint32_t h, h1, i;-    JSAtomStruct *p;-    int len;--#if 0-    printf("__JS_NewAtom: ");  JS_DumpString(rt, str); printf("\n");-#endif-    if (atom_type < JS_ATOM_TYPE_SYMBOL) {-        /* str is not NULL */-        if (str->atom_type == atom_type) {-            /* str is the atom, return its index */-            i = js_get_atom_index(rt, str);-            /* reduce string refcount and increase atom's unless constant */-            if (__JS_AtomIsConst(i))-                str->header.ref_count--;-            return i;-        }-        /* try and locate an already registered atom */-        len = str->len;-        h = hash_string(str, atom_type);-        h &= JS_ATOM_HASH_MASK;-        h1 = h & (rt->atom_hash_size - 1);-        i = rt->atom_hash[h1];-        while (i != 0) {-            p = rt->atom_array[i];-            if (p->hash == h &&-                p->atom_type == atom_type &&-                p->len == len &&-                js_string_memcmp(p, str, len) == 0) {-                if (!__JS_AtomIsConst(i))-                    p->header.ref_count++;-                goto done;-            }-            i = p->hash_next;-        }-    } else {-        h1 = 0; /* avoid warning */-        if (atom_type == JS_ATOM_TYPE_SYMBOL) {-            h = JS_ATOM_HASH_SYMBOL;-        } else {-            h = JS_ATOM_HASH_PRIVATE;-            atom_type = JS_ATOM_TYPE_SYMBOL;-        }-    }--    if (rt->atom_free_index == 0) {-        /* allow new atom entries */-        uint32_t new_size, start;-        JSAtomStruct **new_array;--        /* alloc new with size progression 3/2:-           4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092-           preallocating space for predefined atoms (at least 195).-         */-        new_size = max_int(211, rt->atom_size * 3 / 2);-        if (new_size > JS_ATOM_MAX)-            goto fail;-        /* XXX: should use realloc2 to use slack space */-        new_array = js_realloc_rt(rt, rt->atom_array, sizeof(*new_array) * new_size);-        if (!new_array)-            goto fail;-        /* Note: the atom 0 is not used */-        start = rt->atom_size;-        if (start == 0) {-            /* JS_ATOM_NULL entry */-            p = js_mallocz_rt(rt, sizeof(JSAtomStruct));-            if (!p) {-                js_free_rt(rt, new_array);-                goto fail;-            }-            p->header.ref_count = 1;  /* not refcounted */-            p->atom_type = JS_ATOM_TYPE_SYMBOL;-#ifdef DUMP_LEAKS-            list_add_tail(&p->link, &rt->string_list);-#endif-            new_array[0] = p;-            rt->atom_count++;-            start = 1;-        }-        rt->atom_size = new_size;-        rt->atom_array = new_array;-        rt->atom_free_index = start;-        for(i = start; i < new_size; i++) {-            uint32_t next;-            if (i == (new_size - 1))-                next = 0;-            else-                next = i + 1;-            rt->atom_array[i] = atom_set_free(next);-        }-    }--    if (str) {-        if (str->atom_type == 0) {-            p = str;-            p->atom_type = atom_type;-        } else {-            p = js_malloc_rt(rt, sizeof(JSString) +-                             (str->len << str->is_wide_char) +-                             1 - str->is_wide_char);-            if (unlikely(!p))-                goto fail;-            p->header.ref_count = 1;-            p->is_wide_char = str->is_wide_char;-            p->len = str->len;-#ifdef DUMP_LEAKS-            list_add_tail(&p->link, &rt->string_list);-#endif-            memcpy(p->u.str8, str->u.str8, (str->len << str->is_wide_char) +-                   1 - str->is_wide_char);-            js_free_string(rt, str);-        }-    } else {-        p = js_malloc_rt(rt, sizeof(JSAtomStruct)); /* empty wide string */-        if (!p)-            return JS_ATOM_NULL;-        p->header.ref_count = 1;-        p->is_wide_char = 1;    /* Hack to represent NULL as a JSString */-        p->len = 0;-#ifdef DUMP_LEAKS-        list_add_tail(&p->link, &rt->string_list);-#endif-    }--    /* use an already free entry */-    i = rt->atom_free_index;-    rt->atom_free_index = atom_get_free(rt->atom_array[i]);-    rt->atom_array[i] = p;--    p->hash = h;-    p->hash_next = i;   /* atom_index */-    p->atom_type = atom_type;--    rt->atom_count++;--    if (atom_type != JS_ATOM_TYPE_SYMBOL) {-        p->hash_next = rt->atom_hash[h1];-        rt->atom_hash[h1] = i;-        if (unlikely(rt->atom_count >= rt->atom_count_resize))-            JS_ResizeAtomHash(rt, rt->atom_hash_size * 2);-    }--    //    JS_DumpAtoms(rt);-    return i;-- fail:-    i = JS_ATOM_NULL;- done:-    if (str)-        js_free_string(rt, str);-    return i;-}--/* only works with zero terminated 8 bit strings */-static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,-                               int atom_type)-{-    JSString *p;-    p = js_alloc_string_rt(rt, len, 0);-    if (!p)-        return JS_ATOM_NULL;-    memcpy(p->u.str8, str, len);-    p->u.str8[len] = '\0';-    return __JS_NewAtom(rt, p, atom_type);-}--static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,-                            int atom_type)-{-    uint32_t h, h1, i;-    JSAtomStruct *p;--    h = hash_string8((const uint8_t *)str, len, JS_ATOM_TYPE_STRING);-    h &= JS_ATOM_HASH_MASK;-    h1 = h & (rt->atom_hash_size - 1);-    i = rt->atom_hash[h1];-    while (i != 0) {-        p = rt->atom_array[i];-        if (p->hash == h &&-            p->atom_type == JS_ATOM_TYPE_STRING &&-            p->len == len &&-            p->is_wide_char == 0 &&-            memcmp(p->u.str8, str, len) == 0) {-            if (!__JS_AtomIsConst(i))-                p->header.ref_count++;-            return i;-        }-        i = p->hash_next;-    }-    return JS_ATOM_NULL;-}--static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)-{-#if 0   /* JS_ATOM_NULL is not refcounted: __JS_AtomIsConst() includes 0 */-    if (unlikely(i == JS_ATOM_NULL)) {-        p->header.ref_count = INT32_MAX / 2;-        return;-    }-#endif-    uint32_t i = p->hash_next;  /* atom_index */-    if (p->atom_type != JS_ATOM_TYPE_SYMBOL) {-        JSAtomStruct *p0, *p1;-        uint32_t h0;--        h0 = p->hash & (rt->atom_hash_size - 1);-        i = rt->atom_hash[h0];-        p1 = rt->atom_array[i];-        if (p1 == p) {-            rt->atom_hash[h0] = p1->hash_next;-        } else {-            for(;;) {-                assert(i != 0);-                p0 = p1;-                i = p1->hash_next;-                p1 = rt->atom_array[i];-                if (p1 == p) {-                    p0->hash_next = p1->hash_next;-                    break;-                }-            }-        }-    }-    /* insert in free atom list */-    rt->atom_array[i] = atom_set_free(rt->atom_free_index);-    rt->atom_free_index = i;-    /* free the string structure */-#ifdef DUMP_LEAKS-    list_del(&p->link);-#endif-    js_free_rt(rt, p);-    rt->atom_count--;-    assert(rt->atom_count >= 0);-}--static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)-{-    JSAtomStruct *p;--    p = rt->atom_array[i];-    if (--p->header.ref_count > 0)-        return;-    JS_FreeAtomStruct(rt, p);-}--/* Warning: 'p' is freed */-static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)-{-    JSRuntime *rt = ctx->rt;-    uint32_t n;-    if (is_num_string(&n, p)) {-        if (n <= JS_ATOM_MAX_INT) {-            js_free_string(rt, p);-            return __JS_AtomFromUInt32(n);-        }-    }-    /* XXX: should generate an exception */-    return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);-}--JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)-{-    JSValue val;--    if (len == 0 || !is_digit(*str)) {-        JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);-        if (atom)-            return atom;-    }-    val = JS_NewStringLen(ctx, str, len);-    if (JS_IsException(val))-        return JS_ATOM_NULL;-    return JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(val));-}--JSAtom JS_NewAtom(JSContext *ctx, const char *str)-{-    return JS_NewAtomLen(ctx, str, strlen(str));-}--JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)-{-    if (n <= JS_ATOM_MAX_INT) {-        return __JS_AtomFromUInt32(n);-    } else {-        char buf[11];-        JSValue val;-        snprintf(buf, sizeof(buf), "%u", n);-        val = JS_NewString(ctx, buf);-        if (JS_IsException(val))-            return JS_ATOM_NULL;-        return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),-                            JS_ATOM_TYPE_STRING);-    }-}--static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)-{-    if ((uint64_t)n <= JS_ATOM_MAX_INT) {-        return __JS_AtomFromUInt32((uint32_t)n);-    } else {-        char buf[24];-        JSValue val;-        snprintf(buf, sizeof(buf), "%" PRId64 , n);-        val = JS_NewString(ctx, buf);-        if (JS_IsException(val))-            return JS_ATOM_NULL;-        return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),-                            JS_ATOM_TYPE_STRING);-    }-}--/* 'p' is freed */-static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)-{-    JSRuntime *rt = ctx->rt;-    JSAtom atom;-    atom = __JS_NewAtom(rt, p, atom_type);-    if (atom == JS_ATOM_NULL)-        return JS_ThrowOutOfMemory(ctx);-    return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);-}--/* descr must be a non-numeric string atom */-static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,-                                    int atom_type)-{-    JSRuntime *rt = ctx->rt;-    JSString *p;--    assert(!__JS_AtomIsTaggedInt(descr));-    assert(descr < rt->atom_size);-    p = rt->atom_array[descr];-    JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));-    return JS_NewSymbol(ctx, p, atom_type);-}--#define ATOM_GET_STR_BUF_SIZE 64--/* Should only be used for debug. */-static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,-                                   JSAtom atom)-{-    if (__JS_AtomIsTaggedInt(atom)) {-        snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));-    } else {-        JSAtomStruct *p;-        assert(atom < rt->atom_size);-        if (atom == JS_ATOM_NULL) {-            snprintf(buf, buf_size, "<null>");-        } else {-            int i, c;-            char *q;-            JSString *str;--            q = buf;-            p = rt->atom_array[atom];-            assert(!atom_is_free(p));-            str = p;-            if (str) {-                if (!str->is_wide_char) {-                    /* special case ASCII strings */-                    c = 0;-                    for(i = 0; i < str->len; i++) {-                        c |= str->u.str8[i];-                    }-                    if (c < 0x80)-                        return (const char *)str->u.str8;-                }-                for(i = 0; i < str->len; i++) {-                    if (str->is_wide_char)-                        c = str->u.str16[i];-                    else-                        c = str->u.str8[i];-                    if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX)-                        break;-                    if (c < 128) {-                        *q++ = c;-                    } else {-                        q += unicode_to_utf8((uint8_t *)q, c);-                    }-                }-            }-            *q = '\0';-        }-    }-    return buf;-}--static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom atom)-{-    return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);-}--static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)-{-    char buf[ATOM_GET_STR_BUF_SIZE];--    if (__JS_AtomIsTaggedInt(atom)) {-        snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));-        return JS_NewString(ctx, buf);-    } else {-        JSRuntime *rt = ctx->rt;-        JSAtomStruct *p;-        assert(atom < rt->atom_size);-        p = rt->atom_array[atom];-        if (p->atom_type == JS_ATOM_TYPE_STRING) {-            goto ret_string;-        } else if (force_string) {-            if (p->len == 0 && p->is_wide_char != 0) {-                /* no description string */-                p = rt->atom_array[JS_ATOM_empty_string];-            }-        ret_string:-            return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));-        } else {-            return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p));-        }-    }-}--JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)-{-    return __JS_AtomToValue(ctx, atom, FALSE);-}--JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)-{-    return __JS_AtomToValue(ctx, atom, TRUE);-}--/* return TRUE if the atom is an array index (i.e. 0 <= index <=-   2^32-2 and return its value */-static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)-{-    if (__JS_AtomIsTaggedInt(atom)) {-        *pval = __JS_AtomToUInt32(atom);-        return TRUE;-    } else {-        JSRuntime *rt = ctx->rt;-        JSAtomStruct *p;-        uint32_t val;--        assert(atom < rt->atom_size);-        p = rt->atom_array[atom];-        if (p->atom_type == JS_ATOM_TYPE_STRING &&-            is_num_string(&val, p) && val != -1) {-            *pval = val;-            return TRUE;-        } else {-            *pval = 0;-            return FALSE;-        }-    }-}--/* This test must be fast if atom is not a numeric index (e.g. a-   method name). Return JS_UNDEFINED if not a numeric-   index. JS_EXCEPTION can also be returned. */-static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)-{-    JSRuntime *rt = ctx->rt;-    JSAtomStruct *p1;-    JSString *p;-    int c, len, ret;-    JSValue num, str;--    if (__JS_AtomIsTaggedInt(atom))-        return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));-    assert(atom < rt->atom_size);-    p1 = rt->atom_array[atom];-    if (p1->atom_type != JS_ATOM_TYPE_STRING)-        return JS_UNDEFINED;-    p = p1;-    len = p->len;-    if (p->is_wide_char) {-        const uint16_t *r = p->u.str16, *r_end = p->u.str16 + len;-        if (r >= r_end)-            return JS_UNDEFINED;-        c = *r;-        if (c == '-') {-            if (r >= r_end)-                return JS_UNDEFINED;-            r++;-            c = *r;-            /* -0 case is specific */-            if (c == '0' && len == 2)-                goto minus_zero;-        }-        /* XXX: should test NaN, but the tests do not check it */-        if (!is_num(c)) {-            /* XXX: String should be normalized, therefore 8-bit only */-            const uint16_t nfinity16[7] = { 'n', 'f', 'i', 'n', 'i', 't', 'y' };-            if (!(c =='I' && (r_end - r) == 8 &&-                  !memcmp(r + 1, nfinity16, sizeof(nfinity16))))-                return JS_UNDEFINED;-        }-    } else {-        const uint8_t *r = p->u.str8, *r_end = p->u.str8 + len;-        if (r >= r_end)-            return JS_UNDEFINED;-        c = *r;-        if (c == '-') {-            if (r >= r_end)-                return JS_UNDEFINED;-            r++;-            c = *r;-            /* -0 case is specific */-            if (c == '0' && len == 2) {-            minus_zero:-                return __JS_NewFloat64(ctx, -0.0);-            }-        }-        if (!is_num(c)) {-            if (!(c =='I' && (r_end - r) == 8 &&-                  !memcmp(r + 1, "nfinity", 7)))-                return JS_UNDEFINED;-        }-    }-    /* XXX: bignum: would be better to only accept integer to avoid-       relying on current floating point precision */-    /* this is ECMA CanonicalNumericIndexString primitive */-    num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p));-    if (JS_IsException(num))-        return num;-    str = JS_ToString(ctx, num);-    if (JS_IsException(str)) {-        JS_FreeValue(ctx, num);-        return str;-    }-    ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str));-    JS_FreeValue(ctx, str);-    if (ret == 0) {-        return num;-    } else {-        JS_FreeValue(ctx, num);-        return JS_UNDEFINED;-    }-}--/* return -1 if exception or TRUE/FALSE */-static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)-{-    JSValue num;-    num = JS_AtomIsNumericIndex1(ctx, atom);-    if (likely(JS_IsUndefined(num)))-        return FALSE;-    if (JS_IsException(num))-        return -1;-    JS_FreeValue(ctx, num);-    return TRUE;-}--void JS_FreeAtom(JSContext *ctx, JSAtom v)-{-    if (!__JS_AtomIsConst(v))-        __JS_FreeAtom(ctx->rt, v);-}--void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)-{-    if (!__JS_AtomIsConst(v))-        __JS_FreeAtom(rt, v);-}--/* return TRUE if 'v' is a symbol with a string description */-static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)-{-    JSRuntime *rt;-    JSAtomStruct *p;--    rt = ctx->rt;-    if (__JS_AtomIsTaggedInt(v))-        return FALSE;-    p = rt->atom_array[v];-    return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&-              p->hash == JS_ATOM_HASH_SYMBOL) ||-             p->atom_type == JS_ATOM_TYPE_GLOBAL_SYMBOL) &&-            !(p->len == 0 && p->is_wide_char != 0));-}--static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    const char *p;-    int i;--    /* XXX: should handle embedded null characters */-    /* XXX: should move encoding code to JS_AtomGetStr */-    p = JS_AtomGetStr(ctx, buf, sizeof(buf), atom);-    for (i = 0; p[i]; i++) {-        int c = (unsigned char)p[i];-        if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||-              (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0)))-            break;-    }-    if (i > 0 && p[i] == '\0') {-        printf("%s", p);-    } else {-        putchar('"');-        printf("%.*s", i, p);-        for (; p[i]; i++) {-            int c = (unsigned char)p[i];-            if (c == '\"' || c == '\\') {-                putchar('\\');-                putchar(c);-            } else if (c >= ' ' && c <= 126) {-                putchar(c);-            } else if (c == '\n') {-                putchar('\\');-                putchar('n');-            } else {-                printf("\\u%04x", c);-            }-        }-        putchar('\"');-    }-}--/* free with JS_FreeCString() */-const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)-{-    JSValue str;-    const char *cstr;--    str = JS_AtomToString(ctx, atom);-    if (JS_IsException(str))-        return NULL;-    cstr = JS_ToCString(ctx, str);-    JS_FreeValue(ctx, str);-    return cstr;-}--/* return a string atom containing name concatenated with str1 */-static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1)-{-    JSValue str;-    JSAtom atom;-    const char *cstr;-    char *cstr2;-    size_t len, len1;-    -    str = JS_AtomToString(ctx, name);-    if (JS_IsException(str))-        return JS_ATOM_NULL;-    cstr = JS_ToCStringLen(ctx, &len, str);-    if (!cstr)-        goto fail;-    len1 = strlen(str1);-    cstr2 = js_malloc(ctx, len + len1 + 1);-    if (!cstr2)-        goto fail;-    memcpy(cstr2, cstr, len);-    memcpy(cstr2 + len, str1, len1);-    cstr2[len + len1] = '\0';-    atom = JS_NewAtomLen(ctx, cstr2, len + len1);-    js_free(ctx, cstr2);-    JS_FreeCString(ctx, cstr);-    JS_FreeValue(ctx, str);-    return atom;- fail:-    JS_FreeCString(ctx, cstr);-    JS_FreeValue(ctx, str);-    return JS_ATOM_NULL;-}--static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n)-{-    char buf[16];-    snprintf(buf, sizeof(buf), "%u", n);-    return js_atom_concat_str(ctx, name, buf);-}--static inline BOOL JS_IsEmptyString(JSValueConst v)-{-    return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0;-}--/* JSClass support */--/* a new class ID is allocated if *pclass_id != 0 */-JSClassID JS_NewClassID(JSClassID *pclass_id)-{-    JSClassID class_id;-    /* XXX: make it thread safe */-    class_id = *pclass_id;-    if (class_id == 0) {-        class_id = js_class_id_alloc++;-        *pclass_id = class_id;-    }-    return class_id;-}--BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)-{-    return (class_id < rt->class_count &&-            rt->class_array[class_id].class_id != 0);-}--/* create a new object internal class. Return -1 if error, 0 if-   OK. The finalizer can be NULL if none is needed. */-static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,-                        const JSClassDef *class_def, JSAtom name)-{-    int new_size, i;-    JSClass *cl, *new_class_array;-    struct list_head *el;--    if (class_id < rt->class_count &&-        rt->class_array[class_id].class_id != 0)-        return -1;--    if (class_id >= rt->class_count) {-        new_size = max_int(JS_CLASS_INIT_COUNT,-                           max_int(class_id + 1, rt->class_count * 3 / 2));--        /* reallocate the context class prototype array, if any */-        list_for_each(el, &rt->context_list) {-            JSContext *ctx = list_entry(el, JSContext, link);-            JSValue *new_tab;-            new_tab = js_realloc_rt(rt, ctx->class_proto,-                                    sizeof(ctx->class_proto[0]) * new_size);-            if (!new_tab)-                return -1;-            for(i = rt->class_count; i < new_size; i++)-                new_tab[i] = JS_NULL;-            ctx->class_proto = new_tab;-        }-        /* reallocate the class array */-        new_class_array = js_realloc_rt(rt, rt->class_array,-                                        sizeof(JSClass) * new_size);-        if (!new_class_array)-            return -1;-        memset(new_class_array + rt->class_count, 0,-               (new_size - rt->class_count) * sizeof(JSClass));-        rt->class_array = new_class_array;-        rt->class_count = new_size;-    }-    cl = &rt->class_array[class_id];-    cl->class_id = class_id;-    cl->class_name = JS_DupAtomRT(rt, name);-    cl->finalizer = class_def->finalizer;-    cl->gc_mark = class_def->gc_mark;-    cl->call = class_def->call;-    cl->exotic = class_def->exotic;-    return 0;-}--int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)-{-    int ret, len;-    JSAtom name;--    len = strlen(class_def->class_name);-    name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);-    if (name == JS_ATOM_NULL) {-        name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);-        if (name == JS_ATOM_NULL)-            return -1;-    }-    ret = JS_NewClass1(rt, class_id, class_def, name);-    JS_FreeAtomRT(rt, name);-    return ret;-}--static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len)-{-    JSString *str;--    if (len <= 0) {-        return JS_AtomToString(ctx, JS_ATOM_empty_string);-    }-    str = js_alloc_string(ctx, len, 0);-    if (!str)-        return JS_EXCEPTION;-    memcpy(str->u.str8, buf, len);-    str->u.str8[len] = '\0';-    return JS_MKPTR(JS_TAG_STRING, str);-}--static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len)-{-    JSString *str;-    str = js_alloc_string(ctx, len, 1);-    if (!str)-        return JS_EXCEPTION;-    memcpy(str->u.str16, buf, len * 2);-    return JS_MKPTR(JS_TAG_STRING, str);-}--static JSValue js_new_string_char(JSContext *ctx, uint16_t c)-{-    if (c < 0x100) {-        uint8_t ch8 = c;-        return js_new_string8(ctx, &ch8, 1);-    } else {-        uint16_t ch16 = c;-        return js_new_string16(ctx, &ch16, 1);-    }-}--static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)-{-    int len = end - start;-    if (start == 0 && end == p->len) {-        return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));-    }-    if (p->is_wide_char && len > 0) {-        JSString *str;-        int i;-        uint16_t c = 0;-        for (i = start; i < end; i++) {-            c |= p->u.str16[i];-        }-        if (c > 0xFF)-            return js_new_string16(ctx, p->u.str16 + start, len);--        str = js_alloc_string(ctx, len, 0);-        if (!str)-            return JS_EXCEPTION;-        for (i = 0; i < len; i++) {-            str->u.str8[i] = p->u.str16[start + i];-        }-        str->u.str8[len] = '\0';-        return JS_MKPTR(JS_TAG_STRING, str);-    } else {-        return js_new_string8(ctx, p->u.str8 + start, len);-    }-}--typedef struct StringBuffer {-    JSContext *ctx;-    JSString *str;-    int len;-    int size;-    int is_wide_char;-    int error_status;-} StringBuffer;--/* It is valid to call string_buffer_end() and all string_buffer functions even-   if string_buffer_init() or another string_buffer function returns an error.-   If the error_status is set, string_buffer_end() returns JS_EXCEPTION.- */-static int string_buffer_init2(JSContext *ctx, StringBuffer *s, int size,-                               int is_wide)-{-    s->ctx = ctx;-    s->size = size;-    s->len = 0;-    s->is_wide_char = is_wide;-    s->error_status = 0;-    s->str = js_alloc_string(ctx, size, is_wide);-    if (unlikely(!s->str)) {-        s->size = 0;-        return s->error_status = -1;-    }-#ifdef DUMP_LEAKS-    /* the StringBuffer may reallocate the JSString, only link it at the end */-    list_del(&s->str->link);-#endif-    return 0;-}--static inline int string_buffer_init(JSContext *ctx, StringBuffer *s, int size)-{-    return string_buffer_init2(ctx, s, size, 0);-}--static void string_buffer_free(StringBuffer *s)-{-    js_free(s->ctx, s->str);-    s->str = NULL;-}--static int string_buffer_set_error(StringBuffer *s)-{-    js_free(s->ctx, s->str);-    s->str = NULL;-    s->size = 0;-    s->len = 0;-    return s->error_status = -1;-}--static no_inline int string_buffer_widen(StringBuffer *s, int size)-{-    JSString *str;-    size_t slack;-    int i;--    if (s->error_status)-        return -1;--    str = js_realloc2(s->ctx, s->str, sizeof(JSString) + (size << 1), &slack);-    if (!str)-        return string_buffer_set_error(s);-    size += slack >> 1;-    for(i = s->len; i-- > 0;) {-        str->u.str16[i] = str->u.str8[i];-    }-    s->is_wide_char = 1;-    s->size = size;-    s->str = str;-    return 0;-}--static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c)-{-    JSString *new_str;-    int new_size;-    size_t new_size_bytes, slack;--    if (s->error_status)-        return -1;--    if (new_len > JS_STRING_LEN_MAX) {-        JS_ThrowInternalError(s->ctx, "string too long");-        return string_buffer_set_error(s);-    }-    new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX);-    if (!s->is_wide_char && c >= 0x100) {-        return string_buffer_widen(s, new_size);-    }-    new_size_bytes = sizeof(JSString) + (new_size << s->is_wide_char) + 1 - s->is_wide_char;-    new_str = js_realloc2(s->ctx, s->str, new_size_bytes, &slack);-    if (!new_str)-        return string_buffer_set_error(s);-    new_size = min_int(new_size + (slack >> s->is_wide_char), JS_STRING_LEN_MAX);-    s->size = new_size;-    s->str = new_str;-    return 0;-}--static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c)-{-    if (unlikely(s->len >= s->size)) {-        if (string_buffer_realloc(s, s->len + 1, c))-            return -1;-    }-    if (s->is_wide_char) {-        s->str->u.str16[s->len++] = c;-    } else if (c < 0x100) {-        s->str->u.str8[s->len++] = c;-    } else {-        if (string_buffer_widen(s, s->size))-            return -1;-        s->str->u.str16[s->len++] = c;-    }-    return 0;-}--/* 0 <= c <= 0xff */-static int string_buffer_putc8(StringBuffer *s, uint32_t c)-{-    if (unlikely(s->len >= s->size)) {-        if (string_buffer_realloc(s, s->len + 1, c))-            return -1;-    }-    if (s->is_wide_char) {-        s->str->u.str16[s->len++] = c;-    } else {-        s->str->u.str8[s->len++] = c;-    }-    return 0;-}--/* 0 <= c <= 0xffff */-static int string_buffer_putc16(StringBuffer *s, uint32_t c)-{-    if (likely(s->len < s->size)) {-        if (s->is_wide_char) {-            s->str->u.str16[s->len++] = c;-            return 0;-        } else if (c < 0x100) {-            s->str->u.str8[s->len++] = c;-            return 0;-        }-    }-    return string_buffer_putc_slow(s, c);-}--/* 0 <= c <= 0x10ffff */-static int string_buffer_putc(StringBuffer *s, uint32_t c)-{-    if (unlikely(c >= 0x10000)) {-        /* surrogate pair */-        c -= 0x10000;-        if (string_buffer_putc16(s, (c >> 10) + 0xd800))-            return -1;-        c = (c & 0x3ff) + 0xdc00;-    }-    return string_buffer_putc16(s, c);-}--static int string_get(const JSString *p, int idx) {-    return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx];-}--static int string_getc(const JSString *p, int *pidx)-{-    int idx, c, c1;-    idx = *pidx;-    if (p->is_wide_char) {-        c = p->u.str16[idx++];-        if (c >= 0xd800 && c < 0xdc00 && idx < p->len) {-            c1 = p->u.str16[idx];-            if (c1 >= 0xdc00 && c1 < 0xe000) {-                c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;-                idx++;-            }-        }-    } else {-        c = p->u.str8[idx++];-    }-    *pidx = idx;-    return c;-}--static int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len)-{-    int i;--    if (s->len + len > s->size) {-        if (string_buffer_realloc(s, s->len + len, 0))-            return -1;-    }-    if (s->is_wide_char) {-        for (i = 0; i < len; i++) {-            s->str->u.str16[s->len + i] = p[i];-        }-        s->len += len;-    } else {-        memcpy(&s->str->u.str8[s->len], p, len);-        s->len += len;-    }-    return 0;-}--static int string_buffer_write16(StringBuffer *s, const uint16_t *p, int len)-{-    int c = 0, i;--    for (i = 0; i < len; i++) {-        c |= p[i];-    }-    if (s->len + len > s->size) {-        if (string_buffer_realloc(s, s->len + len, c))-            return -1;-    } else if (!s->is_wide_char && c >= 0x100) {-        if (string_buffer_widen(s, s->size))-            return -1;-    }-    if (s->is_wide_char) {-        memcpy(&s->str->u.str16[s->len], p, len << 1);-        s->len += len;-    } else {-        for (i = 0; i < len; i++) {-            s->str->u.str8[s->len + i] = p[i];-        }-        s->len += len;-    }-    return 0;-}--/* appending an ASCII string */-static int string_buffer_puts8(StringBuffer *s, const char *str)-{-    return string_buffer_write8(s, (const uint8_t *)str, strlen(str));-}--static int string_buffer_concat(StringBuffer *s, const JSString *p,-                                uint32_t from, uint32_t to)-{-    if (to <= from)-        return 0;-    if (p->is_wide_char)-        return string_buffer_write16(s, p->u.str16 + from, to - from);-    else-        return string_buffer_write8(s, p->u.str8 + from, to - from);-}--static int string_buffer_concat_value(StringBuffer *s, JSValueConst v)-{-    JSString *p;-    JSValue v1;-    int res;--    if (s->error_status) {-        /* prevent exception overload */-        return -1;-    }-    if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) {-        v1 = JS_ToString(s->ctx, v);-        if (JS_IsException(v1))-            return string_buffer_set_error(s);-        p = JS_VALUE_GET_STRING(v1);-        res = string_buffer_concat(s, p, 0, p->len);-        JS_FreeValue(s->ctx, v1);-        return res;-    }-    p = JS_VALUE_GET_STRING(v);-    return string_buffer_concat(s, p, 0, p->len);-}--static int string_buffer_concat_value_free(StringBuffer *s, JSValue v)-{-    JSString *p;-    int res;--    if (s->error_status) {-        /* prevent exception overload */-        JS_FreeValue(s->ctx, v);-        return -1;-    }-    if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) {-        v = JS_ToStringFree(s->ctx, v);-        if (JS_IsException(v))-            return string_buffer_set_error(s);-    }-    p = JS_VALUE_GET_STRING(v);-    res = string_buffer_concat(s, p, 0, p->len);-    JS_FreeValue(s->ctx, v);-    return res;-}--static int string_buffer_fill(StringBuffer *s, int c, int count)-{-    /* XXX: optimize */-    if (s->len + count > s->size) {-        if (string_buffer_realloc(s, s->len + count, c))-            return -1;-    }-    while (count-- > 0) {-        if (string_buffer_putc16(s, c))-            return -1;-    }-    return 0;-}--static JSValue string_buffer_end(StringBuffer *s)-{-    JSString *str;-    str = s->str;-    if (s->error_status)-        return JS_EXCEPTION;-    if (s->len == 0) {-        js_free(s->ctx, str);-        s->str = NULL;-        return JS_AtomToString(s->ctx, JS_ATOM_empty_string);-    }-    if (s->len < s->size) {-        /* smaller size so js_realloc should not fail, but OK if it does */-        /* XXX: should add some slack to avoid unnecessary calls */-        /* XXX: might need to use malloc+free to ensure smaller size */-        str = js_realloc_rt(s->ctx->rt, str, sizeof(JSString) +-                            (s->len << s->is_wide_char) + 1 - s->is_wide_char);-        if (str == NULL)-            str = s->str;-        s->str = str;-    }-    if (!s->is_wide_char)-        str->u.str8[s->len] = 0;-#ifdef DUMP_LEAKS-    list_add_tail(&str->link, &s->ctx->rt->string_list);-#endif-    str->is_wide_char = s->is_wide_char;-    str->len = s->len;-    s->str = NULL;-    return JS_MKPTR(JS_TAG_STRING, str);-}--/* create a string from a UTF-8 buffer */-JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)-{-    const uint8_t *p, *p_end, *p_start, *p_next;-    uint32_t c;-    StringBuffer b_s, *b = &b_s;-    size_t len1;-    -    p_start = (const uint8_t *)buf;-    p_end = p_start + buf_len;-    p = p_start;-    while (p < p_end && *p < 128)-        p++;-    len1 = p - p_start;-    if (len1 > JS_STRING_LEN_MAX)-        return JS_ThrowInternalError(ctx, "string too long");-    if (p == p_end) {-        /* ASCII string */-        return js_new_string8(ctx, (const uint8_t *)buf, buf_len);-    } else {-        if (string_buffer_init(ctx, b, buf_len))-            goto fail;-        string_buffer_write8(b, p_start, len1);-        while (p < p_end) {-            if (*p < 128) {-                string_buffer_putc8(b, *p++);-            } else {-                /* parse utf-8 sequence, return 0xFFFFFFFF for error */-                c = unicode_from_utf8(p, p_end - p, &p_next);-                if (c < 0x10000) {-                    p = p_next;-                } else if (c <= 0x10FFFF) {-                    p = p_next;-                    /* surrogate pair */-                    c -= 0x10000;-                    string_buffer_putc16(b, (c >> 10) + 0xd800);-                    c = (c & 0x3ff) + 0xdc00;-                } else {-                    /* invalid char */-                    c = 0xfffd;-                    /* skip the invalid chars */-                    /* XXX: seems incorrect. Why not just use c = *p++; ? */-                    while (p < p_end && (*p >= 0x80 && *p < 0xc0))-                        p++;-                    if (p < p_end) {-                        p++;-                        while (p < p_end && (*p >= 0x80 && *p < 0xc0))-                            p++;-                    }-                }-                string_buffer_putc16(b, c);-            }-        }-    }-    return string_buffer_end(b);-- fail:-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue JS_ConcatString3(JSContext *ctx, const char *str1,-                                JSValue str2, const char *str3)-{-    StringBuffer b_s, *b = &b_s;-    int len1, len3;-    JSString *p;--    if (unlikely(JS_VALUE_GET_TAG(str2) != JS_TAG_STRING)) {-        str2 = JS_ToStringFree(ctx, str2);-        if (JS_IsException(str2))-            goto fail;-    }-    p = JS_VALUE_GET_STRING(str2);-    len1 = strlen(str1);-    len3 = strlen(str3);--    if (string_buffer_init2(ctx, b, len1 + p->len + len3, p->is_wide_char))-        goto fail;--    string_buffer_write8(b, (const uint8_t *)str1, len1);-    string_buffer_concat(b, p, 0, p->len);-    string_buffer_write8(b, (const uint8_t *)str3, len3);--    JS_FreeValue(ctx, str2);-    return string_buffer_end(b);-- fail:-    JS_FreeValue(ctx, str2);-    return JS_EXCEPTION;-}--JSValue JS_NewString(JSContext *ctx, const char *str)-{-    return JS_NewStringLen(ctx, str, strlen(str));-}--JSValue JS_NewAtomString(JSContext *ctx, const char *str)-{-    JSAtom atom = JS_NewAtom(ctx, str);-    if (atom == JS_ATOM_NULL)-        return JS_EXCEPTION;-    JSValue val = JS_AtomToString(ctx, atom);-    JS_FreeAtom(ctx, atom);-    return val;-}--/* return (NULL, 0) if exception. */-/* return pointer into a JSString with a live ref_count */-/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */-const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BOOL cesu8)-{-    JSValue val;-    JSString *str, *str_new;-    int pos, len, c, c1;-    uint8_t *q;--    if (JS_VALUE_GET_TAG(val1) != JS_TAG_STRING) {-        val = JS_ToString(ctx, val1);-        if (JS_IsException(val))-            goto fail;-    } else {-        val = JS_DupValue(ctx, val1);-    }--    str = JS_VALUE_GET_STRING(val);-    len = str->len;-    if (!str->is_wide_char) {-        const uint8_t *src = str->u.str8;-        int count;--        /* count the number of non-ASCII characters */-        /* Scanning the whole string is required for ASCII strings,-           and computing the number of non-ASCII bytes is less expensive-           than testing each byte, hence this method is faster for ASCII-           strings, which is the most common case.-         */-        count = 0;-        for (pos = 0; pos < len; pos++) {-            count += src[pos] >> 7;-        }-        if (count == 0) {-            if (plen)-                *plen = len;-            return (const char *)src;-        }-        str_new = js_alloc_string(ctx, len + count, 0);-        if (!str_new)-            goto fail;-        q = str_new->u.str8;-        for (pos = 0; pos < len; pos++) {-            c = src[pos];-            if (c < 0x80) {-                *q++ = c;-            } else {-                *q++ = (c >> 6) | 0xc0;-                *q++ = (c & 0x3f) | 0x80;-            }-        }-    } else {-        const uint16_t *src = str->u.str16;-        /* Allocate 3 bytes per 16 bit code point. Surrogate pairs may-           produce 4 bytes but use 2 code points.-         */-        str_new = js_alloc_string(ctx, len * 3, 0);-        if (!str_new)-            goto fail;-        q = str_new->u.str8;-        pos = 0;-        while (pos < len) {-            c = src[pos++];-            if (c < 0x80) {-                *q++ = c;-            } else {-                if (c >= 0xd800 && c < 0xdc00) {-                    if (pos < len && !cesu8) {-                        c1 = src[pos];-                        if (c1 >= 0xdc00 && c1 < 0xe000) {-                            pos++;-                            /* surrogate pair */-                            c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;-                        } else {-                            /* Keep unmatched surrogate code points */-                            /* c = 0xfffd; */ /* error */-                        }-                    } else {-                        /* Keep unmatched surrogate code points */-                        /* c = 0xfffd; */ /* error */-                    }-                }-                q += unicode_to_utf8(q, c);-            }-        }-    }--    *q = '\0';-    str_new->len = q - str_new->u.str8;-    JS_FreeValue(ctx, val);-    if (plen)-        *plen = str_new->len;-    return (const char *)str_new->u.str8;- fail:-    if (plen)-        *plen = 0;-    return NULL;-}--void JS_FreeCString(JSContext *ctx, const char *ptr)-{-    JSString *p;-    if (!ptr)-        return;-    /* purposely removing constness */-    p = (JSString *)(void *)(ptr - offsetof(JSString, u));-    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, p));-}--static int memcmp16_8(const uint16_t *src1, const uint8_t *src2, int len)-{-    int c, i;-    for(i = 0; i < len; i++) {-        c = src1[i] - src2[i];-        if (c != 0)-            return c;-    }-    return 0;-}--static int memcmp16(const uint16_t *src1, const uint16_t *src2, int len)-{-    int c, i;-    for(i = 0; i < len; i++) {-        c = src1[i] - src2[i];-        if (c != 0)-            return c;-    }-    return 0;-}--static int js_string_memcmp(const JSString *p1, const JSString *p2, int len)-{-    int res;--    if (likely(!p1->is_wide_char)) {-        if (likely(!p2->is_wide_char))-            res = memcmp(p1->u.str8, p2->u.str8, len);-        else-            res = -memcmp16_8(p2->u.str16, p1->u.str8, len);-    } else {-        if (!p2->is_wide_char)-            res = memcmp16_8(p1->u.str16, p2->u.str8, len);-        else-            res = memcmp16(p1->u.str16, p2->u.str16, len);-    }-    return res;-}--/* return < 0, 0 or > 0 */-static int js_string_compare(JSContext *ctx,-                             const JSString *p1, const JSString *p2)-{-    int res, len;-    len = min_int(p1->len, p2->len);-    res = js_string_memcmp(p1, p2, len);-    if (res == 0) {-        if (p1->len == p2->len)-            res = 0;-        else if (p1->len < p2->len)-            res = -1;-        else-            res = 1;-    }-    return res;-}--static void copy_str16(uint16_t *dst, const JSString *p, int offset, int len)-{-    if (p->is_wide_char) {-        memcpy(dst, p->u.str16 + offset, len * 2);-    } else {-        const uint8_t *src1 = p->u.str8 + offset;-        int i;--        for(i = 0; i < len; i++)-            dst[i] = src1[i];-    }-}--static JSValue JS_ConcatString1(JSContext *ctx,-                                const JSString *p1, const JSString *p2)-{-    JSString *p;-    uint32_t len;-    int is_wide_char;--    len = p1->len + p2->len;-    if (len > JS_STRING_LEN_MAX)-        return JS_ThrowInternalError(ctx, "string too long");-    is_wide_char = p1->is_wide_char | p2->is_wide_char;-    p = js_alloc_string(ctx, len, is_wide_char);-    if (!p)-        return JS_EXCEPTION;-    if (!is_wide_char) {-        memcpy(p->u.str8, p1->u.str8, p1->len);-        memcpy(p->u.str8 + p1->len, p2->u.str8, p2->len);-        p->u.str8[len] = '\0';-    } else {-        copy_str16(p->u.str16, p1, 0, p1->len);-        copy_str16(p->u.str16 + p1->len, p2, 0, p2->len);-    }-    return JS_MKPTR(JS_TAG_STRING, p);-}--/* op1 and op2 are converted to strings. For convience, op1 or op2 =-   JS_EXCEPTION are accepted and return JS_EXCEPTION.  */-static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)-{-    JSValue ret;-    JSString *p1, *p2;--    if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING)) {-        op1 = JS_ToStringFree(ctx, op1);-        if (JS_IsException(op1)) {-            JS_FreeValue(ctx, op2);-            return JS_EXCEPTION;-        }-    }-    if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING)) {-        op2 = JS_ToStringFree(ctx, op2);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            return JS_EXCEPTION;-        }-    }-    p1 = JS_VALUE_GET_STRING(op1);-    p2 = JS_VALUE_GET_STRING(op2);--    /* XXX: could also check if p1 is empty */-    if (p2->len == 0) {-        goto ret_op1;-    }-    if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char-    &&  js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) {-        /* Concatenate in place in available space at the end of p1 */-        if (p1->is_wide_char) {-            memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);-            p1->len += p2->len;-        } else {-            memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);-            p1->len += p2->len;-            p1->u.str8[p1->len] = '\0';-        }-    ret_op1:-        JS_FreeValue(ctx, op2);-        return op1;-    }-    ret = JS_ConcatString1(ctx, p1, p2);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return ret;-}--/* Shape support */--static inline size_t get_shape_size(size_t hash_size, size_t prop_size)-{-    return hash_size * sizeof(uint32_t) + sizeof(JSShape) +-        prop_size * sizeof(JSShapeProperty);-}--static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size)-{-    return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size);-}--static inline uint32_t *prop_hash_end(JSShape *sh)-{-    return (uint32_t *)sh;-}--static inline void *get_alloc_from_shape(JSShape *sh)-{-    return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1);-}--static inline JSShapeProperty *get_shape_prop(JSShape *sh)-{-    return sh->prop;-}--static int init_shape_hash(JSRuntime *rt)-{-    rt->shape_hash_bits = 4;   /* 16 shapes */-    rt->shape_hash_size = 1 << rt->shape_hash_bits;-    rt->shape_hash_count = 0;-    rt->shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) *-                                   rt->shape_hash_size);-    if (!rt->shape_hash)-        return -1;-    return 0;-}--/* same magic hash multiplier as the Linux kernel */-static uint32_t shape_hash(uint32_t h, uint32_t val)-{-    return (h + val) * 0x9e370001;-}--/* truncate the shape hash to 'hash_bits' bits */-static uint32_t get_shape_hash(uint32_t h, int hash_bits)-{-    return h >> (32 - hash_bits);-}--static uint32_t shape_initial_hash(JSObject *proto)-{-    uint32_t h;-    h = shape_hash(1, (uintptr_t)proto);-    if (sizeof(proto) > 4)-        h = shape_hash(h, (uint64_t)(uintptr_t)proto >> 32);-    return h;-}--static int resize_shape_hash(JSRuntime *rt, int new_shape_hash_bits)-{-    int new_shape_hash_size, i;-    uint32_t h;-    JSShape **new_shape_hash, *sh, *sh_next;--    new_shape_hash_size = 1 << new_shape_hash_bits;-    new_shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) *-                                   new_shape_hash_size);-    if (!new_shape_hash)-        return -1;-    for(i = 0; i < rt->shape_hash_size; i++) {-        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh_next) {-            sh_next = sh->shape_hash_next;-            h = get_shape_hash(sh->hash, new_shape_hash_bits);-            sh->shape_hash_next = new_shape_hash[h];-            new_shape_hash[h] = sh;-        }-    }-    js_free_rt(rt, rt->shape_hash);-    rt->shape_hash_bits = new_shape_hash_bits;-    rt->shape_hash_size = new_shape_hash_size;-    rt->shape_hash = new_shape_hash;-    return 0;-}--static void js_shape_hash_link(JSRuntime *rt, JSShape *sh)-{-    uint32_t h;-    h = get_shape_hash(sh->hash, rt->shape_hash_bits);-    sh->shape_hash_next = rt->shape_hash[h];-    rt->shape_hash[h] = sh;-    rt->shape_hash_count++;-}--static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh)-{-    uint32_t h;-    JSShape **psh;--    h = get_shape_hash(sh->hash, rt->shape_hash_bits);-    psh = &rt->shape_hash[h];-    while (*psh != sh)-        psh = &(*psh)->shape_hash_next;-    *psh = sh->shape_hash_next;-    rt->shape_hash_count--;-}--/* create a new empty shape with prototype 'proto' */-static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto,-                                        int hash_size, int prop_size)-{-    JSRuntime *rt = ctx->rt;-    void *sh_alloc;-    JSShape *sh;--    /* resize the shape hash table if necessary */-    if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) {-        resize_shape_hash(rt, rt->shape_hash_bits + 1);-    }--    sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size));-    if (!sh_alloc)-        return NULL;-    sh = get_shape_from_alloc(sh_alloc, hash_size);-    sh->header.ref_count = 1;-    add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);-    if (proto)-        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));-    sh->proto = proto;-    memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) *-           hash_size);-    sh->prop_hash_mask = hash_size - 1;-    sh->prop_size = prop_size;-    sh->prop_count = 0;-    sh->deleted_prop_count = 0;-    -    /* insert in the hash table */-    sh->hash = shape_initial_hash(proto);-    sh->is_hashed = TRUE;-    sh->has_small_array_index = FALSE;-    js_shape_hash_link(ctx->rt, sh);-    return sh;-}--static JSShape *js_new_shape(JSContext *ctx, JSObject *proto)-{-    return js_new_shape2(ctx, proto, JS_PROP_INITIAL_HASH_SIZE,-                         JS_PROP_INITIAL_SIZE);-}--/* The shape is cloned. The new shape is not inserted in the shape-   hash table */-static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1)-{-    JSShape *sh;-    void *sh_alloc, *sh_alloc1;-    size_t size;-    JSShapeProperty *pr;-    uint32_t i, hash_size;--    hash_size = sh1->prop_hash_mask + 1;-    size = get_shape_size(hash_size, sh1->prop_size);-    sh_alloc = js_malloc(ctx, size);-    if (!sh_alloc)-        return NULL;-    sh_alloc1 = get_alloc_from_shape(sh1);-    memcpy(sh_alloc, sh_alloc1, size);-    sh = get_shape_from_alloc(sh_alloc, hash_size);-    sh->header.ref_count = 1;-    add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);-    sh->is_hashed = FALSE;-    if (sh->proto) {-        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));-    }-    for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {-        JS_DupAtom(ctx, pr->atom);-    }-    return sh;-}--static JSShape *js_dup_shape(JSShape *sh)-{-    sh->header.ref_count++;-    return sh;-}--static void js_free_shape0(JSRuntime *rt, JSShape *sh)-{-    uint32_t i;-    JSShapeProperty *pr;--    assert(sh->header.ref_count == 0);-    if (sh->is_hashed)-        js_shape_hash_unlink(rt, sh);-    if (sh->proto != NULL) {-        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, sh->proto));-    }-    pr = get_shape_prop(sh);-    for(i = 0; i < sh->prop_count; i++) {-        JS_FreeAtomRT(rt, pr->atom);-        pr++;-    }-    remove_gc_object(&sh->header);-    js_free_rt(rt, get_alloc_from_shape(sh));-}--static void js_free_shape(JSRuntime *rt, JSShape *sh)-{-    if (unlikely(--sh->header.ref_count <= 0)) {-        js_free_shape0(rt, sh);-    }-}--static void js_free_shape_null(JSRuntime *rt, JSShape *sh)-{-    if (sh)-        js_free_shape(rt, sh);-}--/* make space to hold at least 'count' properties */-static no_inline int resize_properties(JSContext *ctx, JSShape **psh,-                                       JSObject *p, uint32_t count)-{-    JSShape *sh;-    uint32_t new_size, new_hash_size, new_hash_mask, i;-    JSShapeProperty *pr;-    void *sh_alloc;-    intptr_t h;--    sh = *psh;-    new_size = max_int(count, sh->prop_size * 3 / 2);-    /* Reallocate prop array first to avoid crash or size inconsistency-       in case of memory allocation failure */-    if (p) {-        JSProperty *new_prop;-        new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);-        if (unlikely(!new_prop))-            return -1;-        p->prop = new_prop;-    }-    new_hash_size = sh->prop_hash_mask + 1;-    while (new_hash_size < new_size)-        new_hash_size = 2 * new_hash_size;-    if (new_hash_size != (sh->prop_hash_mask + 1)) {-        JSShape *old_sh;-        /* resize the hash table and the properties */-        old_sh = sh;-        sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));-        if (!sh_alloc)-            return -1;-        sh = get_shape_from_alloc(sh_alloc, new_hash_size);-        list_del(&old_sh->header.link);-        /* copy all the fields and the properties */-        memcpy(sh, old_sh,-               sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);-        list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);-        new_hash_mask = new_hash_size - 1;-        sh->prop_hash_mask = new_hash_mask;-        memset(prop_hash_end(sh) - new_hash_size, 0,-               sizeof(prop_hash_end(sh)[0]) * new_hash_size);-        for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) {-            if (pr->atom != JS_ATOM_NULL) {-                h = ((uintptr_t)pr->atom & new_hash_mask);-                pr->hash_next = prop_hash_end(sh)[-h - 1];-                prop_hash_end(sh)[-h - 1] = i + 1;-            }-        }-        js_free(ctx, get_alloc_from_shape(old_sh));-    } else {-        /* only resize the properties */-        list_del(&sh->header.link);-        sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),-                              get_shape_size(new_hash_size, new_size));-        if (unlikely(!sh_alloc)) {-            /* insert again in the GC list */-            list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);-            return -1;-        }-        sh = get_shape_from_alloc(sh_alloc, new_hash_size);-        list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);-    }-    *psh = sh;-    sh->prop_size = new_size;-    return 0;-}--/* remove the deleted properties. */-static int compact_properties(JSContext *ctx, JSObject *p)-{-    JSShape *sh, *old_sh;-    void *sh_alloc;-    intptr_t h;-    uint32_t new_hash_size, i, j, new_hash_mask, new_size;-    JSShapeProperty *old_pr, *pr;-    JSProperty *prop, *new_prop;-    -    sh = p->shape;-    assert(!sh->is_hashed);--    new_size = max_int(JS_PROP_INITIAL_SIZE,-                       sh->prop_count - sh->deleted_prop_count);-    assert(new_size <= sh->prop_size);--    new_hash_size = sh->prop_hash_mask + 1;-    while ((new_hash_size / 2) >= new_size)-        new_hash_size = new_hash_size / 2;-    new_hash_mask = new_hash_size - 1;--    /* resize the hash table and the properties */-    old_sh = sh;-    sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));-    if (!sh_alloc)-        return -1;-    sh = get_shape_from_alloc(sh_alloc, new_hash_size);-    list_del(&old_sh->header.link);-    memcpy(sh, old_sh, sizeof(JSShape));-    list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);-    -    memset(prop_hash_end(sh) - new_hash_size, 0,-           sizeof(prop_hash_end(sh)[0]) * new_hash_size);--    j = 0;-    old_pr = old_sh->prop;-    pr = sh->prop;-    prop = p->prop;-    for(i = 0; i < sh->prop_count; i++) {-        if (old_pr->atom != JS_ATOM_NULL) {-            pr->atom = old_pr->atom;-            pr->flags = old_pr->flags;-            h = ((uintptr_t)old_pr->atom & new_hash_mask);-            pr->hash_next = prop_hash_end(sh)[-h - 1];-            prop_hash_end(sh)[-h - 1] = j + 1;-            prop[j] = prop[i];-            j++;-            pr++;-        }-        old_pr++;-    }-    assert(j == (sh->prop_count - sh->deleted_prop_count));-    sh->prop_hash_mask = new_hash_mask;-    sh->prop_size = new_size;-    sh->deleted_prop_count = 0;-    sh->prop_count = j;--    p->shape = sh;-    js_free(ctx, get_alloc_from_shape(old_sh));-    -    /* reduce the size of the object properties */-    new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);-    if (new_prop)-        p->prop = new_prop;-    return 0;-}--static int add_shape_property(JSContext *ctx, JSShape **psh,-                              JSObject *p, JSAtom atom, int prop_flags)-{-    JSRuntime *rt = ctx->rt;-    JSShape *sh = *psh;-    JSShapeProperty *pr, *prop;-    uint32_t hash_mask, new_shape_hash = 0;-    intptr_t h;--    /* update the shape hash */-    if (sh->is_hashed) {-        js_shape_hash_unlink(rt, sh);-        new_shape_hash = shape_hash(shape_hash(sh->hash, atom), prop_flags);-    }--    if (unlikely(sh->prop_count >= sh->prop_size)) {-        if (resize_properties(ctx, psh, p, sh->prop_count + 1)) {-            /* in case of error, reinsert in the hash table.-               sh is still valid if resize_properties() failed */-            if (sh->is_hashed)-                js_shape_hash_link(rt, sh);-            return -1;-        }-        sh = *psh;-    }-    if (sh->is_hashed) {-        sh->hash = new_shape_hash;-        js_shape_hash_link(rt, sh);-    }-    /* Initialize the new shape property.-       The object property at p->prop[sh->prop_count] is uninitialized */-    prop = get_shape_prop(sh);-    pr = &prop[sh->prop_count++];-    pr->atom = JS_DupAtom(ctx, atom);-    pr->flags = prop_flags;-    sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);-    /* add in hash table */-    hash_mask = sh->prop_hash_mask;-    h = atom & hash_mask;-    pr->hash_next = prop_hash_end(sh)[-h - 1];-    prop_hash_end(sh)[-h - 1] = sh->prop_count;-    return 0;-}--/* find a hashed empty shape matching the prototype. Return NULL if-   not found */-static JSShape *find_hashed_shape_proto(JSRuntime *rt, JSObject *proto)-{-    JSShape *sh1;-    uint32_t h, h1;--    h = shape_initial_hash(proto);-    h1 = get_shape_hash(h, rt->shape_hash_bits);-    for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) {-        if (sh1->hash == h &&-            sh1->proto == proto &&-            sh1->prop_count == 0) {-            return sh1;-        }-    }-    return NULL;-}--/* find a hashed shape matching sh + (prop, prop_flags). Return NULL if-   not found */-static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,-                                       JSAtom atom, int prop_flags)-{-    JSShape *sh1;-    uint32_t h, h1, i, n;--    h = sh->hash;-    h = shape_hash(h, atom);-    h = shape_hash(h, prop_flags);-    h1 = get_shape_hash(h, rt->shape_hash_bits);-    for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) {-        /* we test the hash first so that the rest is done only if the-           shapes really match */-        if (sh1->hash == h &&-            sh1->proto == sh->proto &&-            sh1->prop_count == ((n = sh->prop_count) + 1)) {-            for(i = 0; i < n; i++) {-                if (unlikely(sh1->prop[i].atom != sh->prop[i].atom) ||-                    unlikely(sh1->prop[i].flags != sh->prop[i].flags))-                    goto next;-            }-            if (unlikely(sh1->prop[n].atom != atom) ||-                unlikely(sh1->prop[n].flags != prop_flags))-                goto next;-            return sh1;-        }-    next: ;-    }-    return NULL;-}--static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)-{-    char atom_buf[ATOM_GET_STR_BUF_SIZE];-    int j;--    /* XXX: should output readable class prototype */-    printf("%5d %3d%c %14p %5d %5d", i,-           sh->header.ref_count, " *"[sh->is_hashed],-           (void *)sh->proto, sh->prop_size, sh->prop_count);-    for(j = 0; j < sh->prop_count; j++) {-        printf(" %s", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf),-                                      sh->prop[j].atom));-    }-    printf("\n");-}--static __maybe_unused void JS_DumpShapes(JSRuntime *rt)-{-    int i;-    JSShape *sh;-    struct list_head *el;-    JSObject *p;-    JSGCObjectHeader *gp;-    -    printf("JSShapes: {\n");-    printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS");-    for(i = 0; i < rt->shape_hash_size; i++) {-        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) {-            JS_DumpShape(rt, i, sh);-            assert(sh->is_hashed);-        }-    }-    /* dump non-hashed shapes */-    list_for_each(el, &rt->gc_obj_list) {-        gp = list_entry(el, JSGCObjectHeader, link);-        if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {-            p = (JSObject *)gp;-            if (!p->shape->is_hashed) {-                JS_DumpShape(rt, -1, p->shape);-            }-        }-    }-    printf("}\n");-}--static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id)-{-    JSObject *p;--    js_trigger_gc(ctx->rt, sizeof(JSObject));-    p = js_malloc(ctx, sizeof(JSObject));-    if (unlikely(!p))-        goto fail;-    p->class_id = class_id;-    p->extensible = TRUE;-    p->free_mark = 0;-    p->is_exotic = 0;-    p->fast_array = 0;-    p->is_constructor = 0;-    p->is_uncatchable_error = 0;-    p->tmp_mark = 0;-    p->is_HTMLDDA = 0;-    p->first_weak_ref = NULL;-    p->u.opaque = NULL;-    p->shape = sh;-    p->prop = js_malloc(ctx, sizeof(JSProperty) * sh->prop_size);-    if (unlikely(!p->prop)) {-        js_free(ctx, p);-    fail:-        js_free_shape(ctx->rt, sh);-        return JS_EXCEPTION;-    }--    switch(class_id) {-    case JS_CLASS_OBJECT:-        break;-    case JS_CLASS_ARRAY:-        {-            JSProperty *pr;-            p->is_exotic = 1;-            p->fast_array = 1;-            p->u.array.u.values = NULL;-            p->u.array.count = 0;-            p->u.array.u1.size = 0;-            /* the length property is always the first one */-            if (likely(sh == ctx->array_shape)) {-                pr = &p->prop[0];-            } else {-                /* only used for the first array */-                /* cannot fail */-                pr = add_property(ctx, p, JS_ATOM_length,-                                  JS_PROP_WRITABLE | JS_PROP_LENGTH);-            }-            pr->u.value = JS_NewInt32(ctx, 0);-        }-        break;-    case JS_CLASS_C_FUNCTION:-        p->prop[0].u.value = JS_UNDEFINED;-        break;-    case JS_CLASS_ARGUMENTS:-    case JS_CLASS_UINT8C_ARRAY:-    case JS_CLASS_INT8_ARRAY:-    case JS_CLASS_UINT8_ARRAY:-    case JS_CLASS_INT16_ARRAY:-    case JS_CLASS_UINT16_ARRAY:-    case JS_CLASS_INT32_ARRAY:-    case JS_CLASS_UINT32_ARRAY:-#ifdef CONFIG_BIGNUM-    case JS_CLASS_BIG_INT64_ARRAY:-    case JS_CLASS_BIG_UINT64_ARRAY:-#endif-    case JS_CLASS_FLOAT32_ARRAY:-    case JS_CLASS_FLOAT64_ARRAY:-        p->is_exotic = 1;-        p->fast_array = 1;-        p->u.array.u.ptr = NULL;-        p->u.array.count = 0;-        break;-    case JS_CLASS_DATAVIEW:-        p->u.array.u.ptr = NULL;-        p->u.array.count = 0;-        break;-    case JS_CLASS_NUMBER:-    case JS_CLASS_STRING:-    case JS_CLASS_BOOLEAN:-    case JS_CLASS_SYMBOL:-    case JS_CLASS_DATE:-#ifdef CONFIG_BIGNUM-    case JS_CLASS_BIG_INT:-    case JS_CLASS_BIG_FLOAT:-    case JS_CLASS_BIG_DECIMAL:-#endif-        p->u.object_data = JS_UNDEFINED;-        goto set_exotic;-    case JS_CLASS_REGEXP:-        p->u.regexp.pattern = NULL;-        p->u.regexp.bytecode = NULL;-        goto set_exotic;-    default:-    set_exotic:-        if (ctx->rt->class_array[class_id].exotic) {-            p->is_exotic = 1;-        }-        break;-    }-    p->header.ref_count = 1;-    add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT);-    return JS_MKPTR(JS_TAG_OBJECT, p);-}--static JSObject *get_proto_obj(JSValueConst proto_val)-{-    if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT)-        return NULL;-    else-        return JS_VALUE_GET_OBJ(proto_val);-}--/* WARNING: proto must be an object or JS_NULL */-JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val,-                               JSClassID class_id)-{-    JSShape *sh;-    JSObject *proto;--    proto = get_proto_obj(proto_val);-    sh = find_hashed_shape_proto(ctx->rt, proto);-    if (likely(sh)) {-        sh = js_dup_shape(sh);-    } else {-        sh = js_new_shape(ctx, proto);-        if (!sh)-            return JS_EXCEPTION;-    }-    return JS_NewObjectFromShape(ctx, sh, class_id);-}--#if 0-static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;--    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(obj);-        switch(p->class_id) {-        case JS_CLASS_NUMBER:-        case JS_CLASS_STRING:-        case JS_CLASS_BOOLEAN:-        case JS_CLASS_SYMBOL:-        case JS_CLASS_DATE:-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT:-        case JS_CLASS_BIG_FLOAT:-        case JS_CLASS_BIG_DECIMAL:-#endif-            return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_UNDEFINED;-}-#endif--static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)-{-    JSObject *p;--    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(obj);-        switch(p->class_id) {-        case JS_CLASS_NUMBER:-        case JS_CLASS_STRING:-        case JS_CLASS_BOOLEAN:-        case JS_CLASS_SYMBOL:-        case JS_CLASS_DATE:-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT:-        case JS_CLASS_BIG_FLOAT:-        case JS_CLASS_BIG_DECIMAL:-#endif-            JS_FreeValue(ctx, p->u.object_data);-            p->u.object_data = val;-            return 0;-        }-    }-    JS_FreeValue(ctx, val);-    if (!JS_IsException(obj))-        JS_ThrowTypeError(ctx, "invalid object type");-    return -1;-}--JSValue JS_NewObjectClass(JSContext *ctx, int class_id)-{-    return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id);-}--JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto)-{-    return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT);-}--JSValue JS_NewArray(JSContext *ctx)-{-    return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape),-                                 JS_CLASS_ARRAY);-}--JSValue JS_NewObject(JSContext *ctx)-{-    /* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */-    return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);-}--static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj,-                                       JSAtom name, int len)-{-    /* ES6 feature non compatible with ES5.1: length is configurable */-    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len),-                           JS_PROP_CONFIGURABLE);-    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name,-                           JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE);-}--static BOOL js_class_has_bytecode(JSClassID class_id)-{-    return (class_id == JS_CLASS_BYTECODE_FUNCTION ||-            class_id == JS_CLASS_GENERATOR_FUNCTION ||-            class_id == JS_CLASS_ASYNC_FUNCTION ||-            class_id == JS_CLASS_ASYNC_GENERATOR_FUNCTION);-}--/* return NULL without exception if not a function or no bytecode */-static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return NULL;-    p = JS_VALUE_GET_OBJ(val);-    if (!js_class_has_bytecode(p->class_id))-        return NULL;-    return p->u.func.function_bytecode;-}--static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj,-                                      JSValueConst home_obj)-{-    JSObject *p, *p1;-    JSFunctionBytecode *b;--    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)-        return;-    p = JS_VALUE_GET_OBJ(func_obj);-    if (!js_class_has_bytecode(p->class_id))-        return;-    b = p->u.func.function_bytecode;-    if (b->need_home_object) {-        p1 = p->u.func.home_object;-        if (p1) {-            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));-        }-        if (JS_VALUE_GET_TAG(home_obj) == JS_TAG_OBJECT)-            p1 = JS_VALUE_GET_OBJ(JS_DupValue(ctx, home_obj));-        else-            p1 = NULL;-        p->u.func.home_object = p1;-    }-}--static JSValue js_get_function_name(JSContext *ctx, JSAtom name)-{-    JSValue name_str;--    name_str = JS_AtomToString(ctx, name);-    if (JS_AtomSymbolHasDescription(ctx, name)) {-        name_str = JS_ConcatString3(ctx, "[", name_str, "]");-    }-    return name_str;-}--/* Modify the name of a method according to the atom and-   'flags'. 'flags' is a bitmask of JS_PROP_HAS_GET and-   JS_PROP_HAS_SET. Also set the home object of the method.-   Return < 0 if exception. */-static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj,-                                    JSAtom name, int flags, JSValueConst home_obj)-{-    JSValue name_str;--    name_str = js_get_function_name(ctx, name);-    if (flags & JS_PROP_HAS_GET) {-        name_str = JS_ConcatString3(ctx, "get ", name_str, "");-    } else if (flags & JS_PROP_HAS_SET) {-        name_str = JS_ConcatString3(ctx, "set ", name_str, "");-    }-    if (JS_IsException(name_str))-        return -1;-    if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name_str,-                               JS_PROP_CONFIGURABLE) < 0)-        return -1;-    js_method_set_home_object(ctx, func_obj, home_obj);-    return 0;-}--/* Note: at least 'length' arguments will be readable in 'argv' */-static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,-                                const char *name,-                                int length, JSCFunctionEnum cproto, int magic,-                                JSValueConst proto_val)-{-    JSValue func_obj;-    JSObject *p;-    JSAtom name_atom;-    -    func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION);-    if (JS_IsException(func_obj))-        return func_obj;-    p = JS_VALUE_GET_OBJ(func_obj);-    p->u.cfunc.realm = JS_DupContext(ctx);-    p->u.cfunc.c_function.generic = func;-    p->u.cfunc.length = length;-    p->u.cfunc.cproto = cproto;-    p->u.cfunc.magic = magic;-    p->is_constructor = (cproto == JS_CFUNC_constructor ||-                         cproto == JS_CFUNC_constructor_magic ||-                         cproto == JS_CFUNC_constructor_or_func ||-                         cproto == JS_CFUNC_constructor_or_func_magic);-    if (!name)-        name = "";-    name_atom = JS_NewAtom(ctx, name);-    js_function_set_properties(ctx, func_obj, name_atom, length);-    JS_FreeAtom(ctx, name_atom);-    return func_obj;-}--/* Note: at least 'length' arguments will be readable in 'argv' */-JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,-                         const char *name,-                         int length, JSCFunctionEnum cproto, int magic)-{-    return JS_NewCFunction3(ctx, func, name, length, cproto, magic,-                            ctx->function_proto);-}--typedef struct JSCFunctionDataRecord {-    JSCFunctionData *func;-    uint8_t length;-    uint8_t data_len;-    uint16_t magic;-    JSValue data[0];-} JSCFunctionDataRecord;--static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val)-{-    JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA);-    int i;--    if (s) {-        for(i = 0; i < s->data_len; i++) {-            JS_FreeValueRT(rt, s->data[i]);-        }-        js_free_rt(rt, s);-    }-}--static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,-                                    JS_MarkFunc *mark_func)-{-    JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA);-    int i;--    if (s) {-        for(i = 0; i < s->data_len; i++) {-            JS_MarkValue(rt, s->data[i], mark_func);-        }-    }-}--static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,-                                       JSValueConst this_val,-                                       int argc, JSValueConst *argv, int flags)-{-    JSCFunctionDataRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA);-    JSValueConst *arg_buf;-    int i;--    /* XXX: could add the function on the stack for debug */-    if (unlikely(argc < s->length)) {-        arg_buf = alloca(sizeof(arg_buf[0]) * s->length);-        for(i = 0; i < argc; i++)-            arg_buf[i] = argv[i];-        for(i = argc; i < s->length; i++)-            arg_buf[i] = JS_UNDEFINED;-    } else {-        arg_buf = argv;-    }--    return s->func(ctx, this_val, argc, arg_buf, s->magic, s->data);-}--JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,-                            int length, int magic, int data_len,-                            JSValueConst *data)-{-    JSCFunctionDataRecord *s;-    JSValue func_obj;-    int i;--    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,-                                      JS_CLASS_C_FUNCTION_DATA);-    if (JS_IsException(func_obj))-        return func_obj;-    s = js_malloc(ctx, sizeof(*s) + data_len * sizeof(JSValue));-    if (!s) {-        JS_FreeValue(ctx, func_obj);-        return JS_EXCEPTION;-    }-    s->func = func;-    s->length = length;-    s->data_len = data_len;-    s->magic = magic;-    for(i = 0; i < data_len; i++)-        s->data[i] = JS_DupValue(ctx, data[i]);-    JS_SetOpaque(func_obj, s);-    js_function_set_properties(ctx, func_obj,-                               JS_ATOM_empty_string, length);-    return func_obj;-}--static JSContext *js_autoinit_get_realm(JSProperty *pr)-{-    return (JSContext *)(pr->u.init.realm_and_id & ~3);-}--static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr)-{-    return pr->u.init.realm_and_id & 3;-}--static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)-{-    JS_FreeContext(js_autoinit_get_realm(pr));-}--static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,-                             JS_MarkFunc *mark_func)-{-    mark_func(rt, &js_autoinit_get_realm(pr)->header);-}--static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)-{-    if (unlikely(prop_flags & JS_PROP_TMASK)) {-        if ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-            if (pr->u.getset.getter)-                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));-            if (pr->u.getset.setter)-                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));-        } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-            free_var_ref(rt, pr->u.var_ref);-        } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-            js_autoinit_free(rt, pr);-        }-    } else {-        JS_FreeValueRT(rt, pr->u.value);-    }-}--static force_inline JSShapeProperty *find_own_property1(JSObject *p,-                                                        JSAtom atom)-{-    JSShape *sh;-    JSShapeProperty *pr, *prop;-    intptr_t h;-    sh = p->shape;-    h = (uintptr_t)atom & sh->prop_hash_mask;-    h = prop_hash_end(sh)[-h - 1];-    prop = get_shape_prop(sh);-    while (h) {-        pr = &prop[h - 1];-        if (likely(pr->atom == atom)) {-            return pr;-        }-        h = pr->hash_next;-    }-    return NULL;-}--static force_inline JSShapeProperty *find_own_property(JSProperty **ppr,-                                                       JSObject *p,-                                                       JSAtom atom)-{-    JSShape *sh;-    JSShapeProperty *pr, *prop;-    intptr_t h;-    sh = p->shape;-    h = (uintptr_t)atom & sh->prop_hash_mask;-    h = prop_hash_end(sh)[-h - 1];-    prop = get_shape_prop(sh);-    while (h) {-        pr = &prop[h - 1];-        if (likely(pr->atom == atom)) {-            *ppr = &p->prop[h - 1];-            /* the compiler should be able to assume that pr != NULL here */-            return pr;-        }-        h = pr->hash_next;-    }-    *ppr = NULL;-    return NULL;-}--/* indicate that the object may be part of a function prototype cycle */-static void set_cycle_flag(JSContext *ctx, JSValueConst obj)-{-}--static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)-{-    if (var_ref) {-        assert(var_ref->header.ref_count > 0);-        if (--var_ref->header.ref_count == 0) {-            if (var_ref->is_detached) {-                JS_FreeValueRT(rt, var_ref->value);-                remove_gc_object(&var_ref->header);-            } else {-                list_del(&var_ref->header.link); /* still on the stack */-            }-            js_free_rt(rt, var_ref);-        }-    }-}--static void js_array_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    int i;--    for(i = 0; i < p->u.array.count; i++) {-        JS_FreeValueRT(rt, p->u.array.u.values[i]);-    }-    js_free_rt(rt, p->u.array.u.values);-}--static void js_array_mark(JSRuntime *rt, JSValueConst val,-                          JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    int i;--    for(i = 0; i < p->u.array.count; i++) {-        JS_MarkValue(rt, p->u.array.u.values[i], mark_func);-    }-}--static void js_object_data_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JS_FreeValueRT(rt, p->u.object_data);-    p->u.object_data = JS_UNDEFINED;-}--static void js_object_data_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JS_MarkValue(rt, p->u.object_data, mark_func);-}--static void js_c_function_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);--    if (p->u.cfunc.realm)-        JS_FreeContext(p->u.cfunc.realm);-}--static void js_c_function_mark(JSRuntime *rt, JSValueConst val,-                               JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);--    if (p->u.cfunc.realm)-        mark_func(rt, &p->u.cfunc.realm->header);-}--static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p1, *p = JS_VALUE_GET_OBJ(val);-    JSFunctionBytecode *b;-    JSVarRef **var_refs;-    int i;--    p1 = p->u.func.home_object;-    if (p1) {-        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, p1));-    }-    b = p->u.func.function_bytecode;-    if (b) {-        var_refs = p->u.func.var_refs;-        if (var_refs) {-            for(i = 0; i < b->closure_var_count; i++)-                free_var_ref(rt, var_refs[i]);-            js_free_rt(rt, var_refs);-        }-        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b));-    }-}--static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,-                                      JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSVarRef **var_refs = p->u.func.var_refs;-    JSFunctionBytecode *b = p->u.func.function_bytecode;-    int i;--    if (p->u.func.home_object) {-        JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object),-                     mark_func);-    }-    if (b) {-        if (var_refs) {-            for(i = 0; i < b->closure_var_count; i++) {-                JSVarRef *var_ref = var_refs[i];-                if (var_ref && var_ref->is_detached) {-                    mark_func(rt, &var_ref->header);-                }-            }-        }-        /* must mark the function bytecode because template objects may be-           part of a cycle */-        JS_MarkValue(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), mark_func);-    }-}--static void js_bound_function_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSBoundFunction *bf = p->u.bound_function;-    int i;--    JS_FreeValueRT(rt, bf->func_obj);-    JS_FreeValueRT(rt, bf->this_val);-    for(i = 0; i < bf->argc; i++) {-        JS_FreeValueRT(rt, bf->argv[i]);-    }-    js_free_rt(rt, bf);-}--static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSBoundFunction *bf = p->u.bound_function;-    int i;--    JS_MarkValue(rt, bf->func_obj, mark_func);-    JS_MarkValue(rt, bf->this_val, mark_func);-    for(i = 0; i < bf->argc; i++)-        JS_MarkValue(rt, bf->argv[i], mark_func);-}--static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSForInIterator *it = p->u.for_in_iterator;-    JS_FreeValueRT(rt, it->obj);-    js_free_rt(rt, it);-}--static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,-                                JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSForInIterator *it = p->u.for_in_iterator;-    JS_MarkValue(rt, it->obj, mark_func);-}--static void free_object(JSRuntime *rt, JSObject *p)-{-    int i;-    JSClassFinalizer *finalizer;-    JSShape *sh;-    JSShapeProperty *pr;--    p->free_mark = 1; /* used to tell the object is invalid when-                         freeing cycles */-    /* free all the fields */-    sh = p->shape;-    pr = get_shape_prop(sh);-    for(i = 0; i < sh->prop_count; i++) {-        free_property(rt, &p->prop[i], pr->flags);-        pr++;-    }-    js_free_rt(rt, p->prop);-    /* as an optimization we destroy the shape immediately without-       putting it in gc_zero_ref_count_list */-    js_free_shape(rt, sh);--    /* fail safe */-    p->shape = NULL;-    p->prop = NULL;--    if (unlikely(p->first_weak_ref)) {-        reset_weak_ref(rt, p);-    }--    finalizer = rt->class_array[p->class_id].finalizer;-    if (finalizer)-        (*finalizer)(rt, JS_MKPTR(JS_TAG_OBJECT, p));--    /* fail safe */-    p->class_id = 0;-    p->u.opaque = NULL;-    p->u.func.var_refs = NULL;-    p->u.func.home_object = NULL;--    remove_gc_object(&p->header);-    if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && p->header.ref_count != 0) {-        list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list);-    } else {-        js_free_rt(rt, p);-    }-}--static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)-{-    switch(gp->gc_obj_type) {-    case JS_GC_OBJ_TYPE_JS_OBJECT:-        free_object(rt, (JSObject *)gp);-        break;-    case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:-        free_function_bytecode(rt, (JSFunctionBytecode *)gp);-        break;-    default:-        abort();-    }-}--static void free_zero_refcount(JSRuntime *rt)-{-    struct list_head *el;-    JSGCObjectHeader *p;-    -    rt->gc_phase = JS_GC_PHASE_DECREF;-    for(;;) {-        el = rt->gc_zero_ref_count_list.next;-        if (el == &rt->gc_zero_ref_count_list)-            break;-        p = list_entry(el, JSGCObjectHeader, link);-        assert(p->ref_count == 0);-        free_gc_object(rt, p);-    }-    rt->gc_phase = JS_GC_PHASE_NONE;-}--/* called with the ref_count of 'v' reaches zero. */-void __JS_FreeValueRT(JSRuntime *rt, JSValue v)-{-    uint32_t tag = JS_VALUE_GET_TAG(v);--#ifdef DUMP_FREE-    {-        printf("Freeing ");-        if (tag == JS_TAG_OBJECT) {-            JS_DumpObject(rt, JS_VALUE_GET_OBJ(v));-        } else {-            JS_DumpValueShort(rt, v);-            printf("\n");-        }-    }-#endif--    switch(tag) {-    case JS_TAG_STRING:-        {-            JSString *p = JS_VALUE_GET_STRING(v);-            if (p->atom_type) {-                JS_FreeAtomStruct(rt, p);-            } else {-#ifdef DUMP_LEAKS-                list_del(&p->link);-#endif-                js_free_rt(rt, p);-            }-        }-        break;-    case JS_TAG_OBJECT:-    case JS_TAG_FUNCTION_BYTECODE:-        {-            JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);-            if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {-                list_del(&p->link);-                list_add(&p->link, &rt->gc_zero_ref_count_list);-                if (rt->gc_phase == JS_GC_PHASE_NONE) {-                    free_zero_refcount(rt);-                }-            }-        }-        break;-    case JS_TAG_MODULE:-        abort(); /* never freed here */-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *bf = JS_VALUE_GET_PTR(v);-            bf_delete(&bf->num);-            js_free_rt(rt, bf);-        }-        break;-    case JS_TAG_BIG_DECIMAL:-        {-            JSBigDecimal *bf = JS_VALUE_GET_PTR(v);-            bfdec_delete(&bf->num);-            js_free_rt(rt, bf);-        }-        break;-#endif-    case JS_TAG_SYMBOL:-        {-            JSAtomStruct *p = JS_VALUE_GET_PTR(v);-            JS_FreeAtomStruct(rt, p);-        }-        break;-    default:-        printf("__JS_FreeValue: unknown tag=%d\n", tag);-        abort();-    }-}--void __JS_FreeValue(JSContext *ctx, JSValue v)-{-    __JS_FreeValueRT(ctx->rt, v);-}--/* garbage collection */--static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,-                          JSGCObjectTypeEnum type)-{-    h->mark = 0;-    h->gc_obj_type = type;-    list_add_tail(&h->link, &rt->gc_obj_list);-}--static void remove_gc_object(JSGCObjectHeader *h)-{-    list_del(&h->link);-}--void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)-{-    if (JS_VALUE_HAS_REF_COUNT(val)) {-        switch(JS_VALUE_GET_TAG(val)) {-        case JS_TAG_OBJECT:-        case JS_TAG_FUNCTION_BYTECODE:-            mark_func(rt, JS_VALUE_GET_PTR(val));-            break;-        default:-            break;-        }-    }-}--static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,-                          JS_MarkFunc *mark_func)-{-    switch(gp->gc_obj_type) {-    case JS_GC_OBJ_TYPE_JS_OBJECT:-        {-            JSObject *p = (JSObject *)gp;-            JSShapeProperty *prs;-            JSShape *sh;-            int i;-            sh = p->shape;-            mark_func(rt, &sh->header);-            /* mark all the fields */-            prs = get_shape_prop(sh);-            for(i = 0; i < sh->prop_count; i++) {-                JSProperty *pr = &p->prop[i];-                if (prs->atom != JS_ATOM_NULL) {-                    if (prs->flags & JS_PROP_TMASK) {-                        if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                            if (pr->u.getset.getter)-                                mark_func(rt, &pr->u.getset.getter->header);-                            if (pr->u.getset.setter)-                                mark_func(rt, &pr->u.getset.setter->header);-                        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                            if (pr->u.var_ref->is_detached) {-                                /* Note: the tag does not matter-                                   provided it is a GC object */-                                mark_func(rt, &pr->u.var_ref->header);-                            }-                        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                            js_autoinit_mark(rt, pr, mark_func);-                        }-                    } else {-                        JS_MarkValue(rt, pr->u.value, mark_func);-                    }-                }-                prs++;-            }--            if (p->class_id != JS_CLASS_OBJECT) {-                JSClassGCMark *gc_mark;-                gc_mark = rt->class_array[p->class_id].gc_mark;-                if (gc_mark)-                    gc_mark(rt, JS_MKPTR(JS_TAG_OBJECT, p), mark_func);-            }-        }-        break;-    case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:-        /* the template objects can be part of a cycle */-        {-            JSFunctionBytecode *b = (JSFunctionBytecode *)gp;-            int i;-            for(i = 0; i < b->cpool_count; i++) {-                JS_MarkValue(rt, b->cpool[i], mark_func);-            }-            if (b->realm)-                mark_func(rt, &b->realm->header);-        }-        break;-    case JS_GC_OBJ_TYPE_VAR_REF:-        {-            JSVarRef *var_ref = (JSVarRef *)gp;-            /* only detached variable referenced are taken into account */-            assert(var_ref->is_detached);-            JS_MarkValue(rt, *var_ref->pvalue, mark_func);-        }-        break;-    case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:-        {-            JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp;-            if (s->is_active)-                async_func_mark(rt, &s->func_state, mark_func);-            JS_MarkValue(rt, s->resolving_funcs[0], mark_func);-            JS_MarkValue(rt, s->resolving_funcs[1], mark_func);-        }-        break;-    case JS_GC_OBJ_TYPE_SHAPE:-        {-            JSShape *sh = (JSShape *)gp;-            if (sh->proto != NULL) {-                mark_func(rt, &sh->proto->header);-            }-        }-        break;-    case JS_GC_OBJ_TYPE_JS_CONTEXT:-        {-            JSContext *ctx = (JSContext *)gp;-            JS_MarkContext(rt, ctx, mark_func);-        }-        break;-    default:-        abort();-    }-}--static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p)-{-    assert(p->ref_count > 0);-    p->ref_count--;-    if (p->ref_count == 0 && p->mark == 1) {-        list_del(&p->link);-        list_add_tail(&p->link, &rt->tmp_obj_list);-    }-}--static void gc_decref(JSRuntime *rt)-{-    struct list_head *el, *el1;-    JSGCObjectHeader *p;-    -    init_list_head(&rt->tmp_obj_list);--    /* decrement the refcount of all the children of all the GC-       objects and move the GC objects with zero refcount to-       tmp_obj_list */-    list_for_each_safe(el, el1, &rt->gc_obj_list) {-        p = list_entry(el, JSGCObjectHeader, link);-        assert(p->mark == 0);-        mark_children(rt, p, gc_decref_child);-        p->mark = 1;-        if (p->ref_count == 0) {-            list_del(&p->link);-            list_add_tail(&p->link, &rt->tmp_obj_list);-        }-    }-}--static void gc_scan_incref_child(JSRuntime *rt, JSGCObjectHeader *p)-{-    p->ref_count++;-    if (p->ref_count == 1) {-        /* ref_count was 0: remove from tmp_obj_list and add at the-           end of gc_obj_list */-        list_del(&p->link);-        list_add_tail(&p->link, &rt->gc_obj_list);-        p->mark = 0; /* reset the mark for the next GC call */-    }-}--static void gc_scan_incref_child2(JSRuntime *rt, JSGCObjectHeader *p)-{-    p->ref_count++;-}--static void gc_scan(JSRuntime *rt)-{-    struct list_head *el;-    JSGCObjectHeader *p;--    /* keep the objects with a refcount > 0 and their children. */-    list_for_each(el, &rt->gc_obj_list) {-        p = list_entry(el, JSGCObjectHeader, link);-        assert(p->ref_count > 0);-        p->mark = 0; /* reset the mark for the next GC call */-        mark_children(rt, p, gc_scan_incref_child);-    }-    -    /* restore the refcount of the objects to be deleted. */-    list_for_each(el, &rt->tmp_obj_list) {-        p = list_entry(el, JSGCObjectHeader, link);-        mark_children(rt, p, gc_scan_incref_child2);-    }-}--static void gc_free_cycles(JSRuntime *rt)-{-    struct list_head *el, *el1;-    JSGCObjectHeader *p;-#ifdef DUMP_GC_FREE-    BOOL header_done = FALSE;-#endif--    rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES;--    for(;;) {-        el = rt->tmp_obj_list.next;-        if (el == &rt->tmp_obj_list)-            break;-        p = list_entry(el, JSGCObjectHeader, link);-        /* Only need to free the GC object associated with JS-           values. The rest will be automatically removed because they-           must be referenced by them. */-        switch(p->gc_obj_type) {-        case JS_GC_OBJ_TYPE_JS_OBJECT:-        case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:-#ifdef DUMP_GC_FREE-            if (!header_done) {-                printf("Freeing cycles:\n");-                JS_DumpObjectHeader(rt);-                header_done = TRUE;-            }-            JS_DumpGCObject(rt, p);-#endif-            free_gc_object(rt, p);-            break;-        default:-            list_del(&p->link);-            list_add_tail(&p->link, &rt->gc_zero_ref_count_list);-            break;-        }-    }-    rt->gc_phase = JS_GC_PHASE_NONE;-           -    list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) {-        p = list_entry(el, JSGCObjectHeader, link);-        assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||-               p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);-        js_free_rt(rt, p);-    }--    init_list_head(&rt->gc_zero_ref_count_list);-}--void JS_RunGC(JSRuntime *rt)-{-    /* decrement the reference of the children of each object. mark =-       1 after this pass. */-    gc_decref(rt);--    /* keep the GC objects with a non zero refcount and their childs */-    gc_scan(rt);--    /* free the GC objects in a cycle */-    gc_free_cycles(rt);-}--/* Return false if not an object or if the object has already been-   freed (zombie objects are visible in finalizers when freeing-   cycles). */-BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj)-{-    JSObject *p;-    if (!JS_IsObject(obj))-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    return !p->free_mark;-}--/* Compute memory used by various object types */-/* XXX: poor man's approach to handling multiply referenced objects */-typedef struct JSMemoryUsage_helper {-    double memory_used_count;-    double str_count;-    double str_size;-    int64_t js_func_count;-    double js_func_size;-    int64_t js_func_code_size;-    int64_t js_func_pc2line_count;-    int64_t js_func_pc2line_size;-} JSMemoryUsage_helper;--static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp);--static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp)-{-    if (!str->atom_type) {  /* atoms are handled separately */-        double s_ref_count = str->header.ref_count;-        hp->str_count += 1 / s_ref_count;-        hp->str_size += ((sizeof(*str) + (str->len << str->is_wide_char) +-                          1 - str->is_wide_char) / s_ref_count);-    }-}--static void compute_bytecode_size(JSFunctionBytecode *b, JSMemoryUsage_helper *hp)-{-    int memory_used_count, js_func_size, i;--    memory_used_count = 0;-    js_func_size = offsetof(JSFunctionBytecode, debug);-    if (b->vardefs) {-        js_func_size += (b->arg_count + b->var_count) * sizeof(*b->vardefs);-    }-    if (b->cpool) {-        js_func_size += b->cpool_count * sizeof(*b->cpool);-        for (i = 0; i < b->cpool_count; i++) {-            JSValueConst val = b->cpool[i];-            compute_value_size(val, hp);-        }-    }-    if (b->closure_var) {-        js_func_size += b->closure_var_count * sizeof(*b->closure_var);-    }-    if (!b->read_only_bytecode && b->byte_code_buf) {-        hp->js_func_code_size += b->byte_code_len;-    }-    if (b->has_debug) {-        js_func_size += sizeof(*b) - offsetof(JSFunctionBytecode, debug);-        if (b->debug.source) {-            memory_used_count++;-            js_func_size += b->debug.source_len + 1;-        }-        if (b->debug.pc2line_len) {-            memory_used_count++;-            hp->js_func_pc2line_count += 1;-            hp->js_func_pc2line_size += b->debug.pc2line_len;-        }-    }-    hp->js_func_size += js_func_size;-    hp->js_func_count += 1;-    hp->memory_used_count += memory_used_count;-}--static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)-{-    switch(JS_VALUE_GET_TAG(val)) {-    case JS_TAG_STRING:-        compute_jsstring_size(JS_VALUE_GET_STRING(val), hp);-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-    case JS_TAG_BIG_DECIMAL:-        /* should track JSBigFloat usage */-        break;-#endif-    }-}--void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)-{-    struct list_head *el, *el1;-    int i;-    JSMemoryUsage_helper mem = { 0 }, *hp = &mem;--    memset(s, 0, sizeof(*s));-    s->malloc_count = rt->malloc_state.malloc_count;-    s->malloc_size = rt->malloc_state.malloc_size;-    s->malloc_limit = rt->malloc_state.malloc_limit;--    s->memory_used_count = 2; /* rt + rt->class_array */-    s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;--    list_for_each(el, &rt->context_list) {-        JSContext *ctx = list_entry(el, JSContext, link);-        JSShape *sh = ctx->array_shape;-        s->memory_used_count += 2; /* ctx + ctx->class_proto */-        s->memory_used_size += sizeof(JSContext) +-            sizeof(JSValue) * rt->class_count;-        s->binary_object_count += ctx->binary_object_count;-        s->binary_object_size += ctx->binary_object_size;--        /* the hashed shapes are counted separately */-        if (sh && !sh->is_hashed) {-            int hash_size = sh->prop_hash_mask + 1;-            s->shape_count++;-            s->shape_size += get_shape_size(hash_size, sh->prop_size);-        }-        list_for_each(el1, &ctx->loaded_modules) {-            JSModuleDef *m = list_entry(el1, JSModuleDef, link);-            s->memory_used_count += 1;-            s->memory_used_size += sizeof(*m);-            if (m->req_module_entries) {-                s->memory_used_count += 1;-                s->memory_used_size += m->req_module_entries_count * sizeof(*m->req_module_entries);-            }-            if (m->export_entries) {-                s->memory_used_count += 1;-                s->memory_used_size += m->export_entries_count * sizeof(*m->export_entries);-                for (i = 0; i < m->export_entries_count; i++) {-                    JSExportEntry *me = &m->export_entries[i];-                    if (me->export_type == JS_EXPORT_TYPE_LOCAL && me->u.local.var_ref) {-                        /* potential multiple count */-                        s->memory_used_count += 1;-                        compute_value_size(me->u.local.var_ref->value, hp);-                    }-                }-            }-            if (m->star_export_entries) {-                s->memory_used_count += 1;-                s->memory_used_size += m->star_export_entries_count * sizeof(*m->star_export_entries);-            }-            if (m->import_entries) {-                s->memory_used_count += 1;-                s->memory_used_size += m->import_entries_count * sizeof(*m->import_entries);-            }-            compute_value_size(m->module_ns, hp);-            compute_value_size(m->func_obj, hp);-        }-    }--    list_for_each(el, &rt->gc_obj_list) {-        JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link);-        JSObject *p;-        JSShape *sh;-        JSShapeProperty *prs;--        /* XXX: could count the other GC object types too */-        if (gp->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE) {-            compute_bytecode_size((JSFunctionBytecode *)gp, hp);-            continue;-        } else if (gp->gc_obj_type != JS_GC_OBJ_TYPE_JS_OBJECT) {-            continue;-        }-        p = (JSObject *)gp;-        sh = p->shape;-        s->obj_count++;-        if (p->prop) {-            s->memory_used_count++;-            s->prop_size += sh->prop_size * sizeof(*p->prop);-            s->prop_count += sh->prop_count;-            prs = get_shape_prop(sh);-            for(i = 0; i < sh->prop_count; i++) {-                JSProperty *pr = &p->prop[i];-                if (prs->atom != JS_ATOM_NULL && !(prs->flags & JS_PROP_TMASK)) {-                    compute_value_size(pr->u.value, hp);-                }-                prs++;-            }-        }-        /* the hashed shapes are counted separately */-        if (!sh->is_hashed) {-            int hash_size = sh->prop_hash_mask + 1;-            s->shape_count++;-            s->shape_size += get_shape_size(hash_size, sh->prop_size);-        }--        switch(p->class_id) {-        case JS_CLASS_ARRAY:             /* u.array | length */-        case JS_CLASS_ARGUMENTS:         /* u.array | length */-            s->array_count++;-            if (p->fast_array) {-                s->fast_array_count++;-                if (p->u.array.u.values) {-                    s->memory_used_count++;-                    s->memory_used_size += p->u.array.count *-                        sizeof(*p->u.array.u.values);-                    s->fast_array_elements += p->u.array.count;-                    for (i = 0; i < p->u.array.count; i++) {-                        compute_value_size(p->u.array.u.values[i], hp);-                    }-                }-            }-            break;-        case JS_CLASS_NUMBER:            /* u.object_data */-        case JS_CLASS_STRING:            /* u.object_data */-        case JS_CLASS_BOOLEAN:           /* u.object_data */-        case JS_CLASS_SYMBOL:            /* u.object_data */-        case JS_CLASS_DATE:              /* u.object_data */-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT:           /* u.object_data */-        case JS_CLASS_BIG_FLOAT:         /* u.object_data */-        case JS_CLASS_BIG_DECIMAL:         /* u.object_data */-#endif-            compute_value_size(p->u.object_data, hp);-            break;-        case JS_CLASS_C_FUNCTION:        /* u.cfunc */-            s->c_func_count++;-            break;-        case JS_CLASS_BYTECODE_FUNCTION: /* u.func */-            {-                JSFunctionBytecode *b = p->u.func.function_bytecode;-                JSVarRef **var_refs = p->u.func.var_refs;-                /* home_object: object will be accounted for in list scan */-                if (var_refs) {-                    s->memory_used_count++;-                    s->js_func_size += b->closure_var_count * sizeof(*var_refs);-                    for (i = 0; i < b->closure_var_count; i++) {-                        if (var_refs[i]) {-                            double ref_count = var_refs[i]->header.ref_count;-                            s->memory_used_count += 1 / ref_count;-                            s->js_func_size += sizeof(*var_refs[i]) / ref_count;-                            /* handle non object closed values */-                            if (var_refs[i]->pvalue == &var_refs[i]->value) {-                                /* potential multiple count */-                                compute_value_size(var_refs[i]->value, hp);-                            }-                        }-                    }-                }-            }-            break;-        case JS_CLASS_BOUND_FUNCTION:    /* u.bound_function */-            {-                JSBoundFunction *bf = p->u.bound_function;-                /* func_obj and this_val are objects */-                for (i = 0; i < bf->argc; i++) {-                    compute_value_size(bf->argv[i], hp);-                }-                s->memory_used_count += 1;-                s->memory_used_size += sizeof(*bf) + bf->argc * sizeof(*bf->argv);-            }-            break;-        case JS_CLASS_C_FUNCTION_DATA:   /* u.c_function_data_record */-            {-                JSCFunctionDataRecord *fd = p->u.c_function_data_record;-                if (fd) {-                    for (i = 0; i < fd->data_len; i++) {-                        compute_value_size(fd->data[i], hp);-                    }-                    s->memory_used_count += 1;-                    s->memory_used_size += sizeof(*fd) + fd->data_len * sizeof(*fd->data);-                }-            }-            break;-        case JS_CLASS_REGEXP:            /* u.regexp */-            compute_jsstring_size(p->u.regexp.pattern, hp);-            compute_jsstring_size(p->u.regexp.bytecode, hp);-            break;--        case JS_CLASS_FOR_IN_ITERATOR:   /* u.for_in_iterator */-            {-                JSForInIterator *it = p->u.for_in_iterator;-                if (it) {-                    compute_value_size(it->obj, hp);-                    s->memory_used_count += 1;-                    s->memory_used_size += sizeof(*it);-                }-            }-            break;-        case JS_CLASS_ARRAY_BUFFER:      /* u.array_buffer */-        case JS_CLASS_SHARED_ARRAY_BUFFER: /* u.array_buffer */-            {-                JSArrayBuffer *abuf = p->u.array_buffer;-                if (abuf) {-                    s->memory_used_count += 1;-                    s->memory_used_size += sizeof(*abuf);-                    if (abuf->data) {-                        s->memory_used_count += 1;-                        s->memory_used_size += abuf->byte_length;-                    }-                }-            }-            break;-        case JS_CLASS_GENERATOR:         /* u.generator_data */-        case JS_CLASS_UINT8C_ARRAY:      /* u.typed_array / u.array */-        case JS_CLASS_INT8_ARRAY:        /* u.typed_array / u.array */-        case JS_CLASS_UINT8_ARRAY:       /* u.typed_array / u.array */-        case JS_CLASS_INT16_ARRAY:       /* u.typed_array / u.array */-        case JS_CLASS_UINT16_ARRAY:      /* u.typed_array / u.array */-        case JS_CLASS_INT32_ARRAY:       /* u.typed_array / u.array */-        case JS_CLASS_UINT32_ARRAY:      /* u.typed_array / u.array */-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT64_ARRAY:   /* u.typed_array / u.array */-        case JS_CLASS_BIG_UINT64_ARRAY:  /* u.typed_array / u.array */-#endif-        case JS_CLASS_FLOAT32_ARRAY:     /* u.typed_array / u.array */-        case JS_CLASS_FLOAT64_ARRAY:     /* u.typed_array / u.array */-        case JS_CLASS_DATAVIEW:          /* u.typed_array */-#ifdef CONFIG_BIGNUM-        case JS_CLASS_FLOAT_ENV:         /* u.float_env */-#endif-        case JS_CLASS_MAP:               /* u.map_state */-        case JS_CLASS_SET:               /* u.map_state */-        case JS_CLASS_WEAKMAP:           /* u.map_state */-        case JS_CLASS_WEAKSET:           /* u.map_state */-        case JS_CLASS_MAP_ITERATOR:      /* u.map_iterator_data */-        case JS_CLASS_SET_ITERATOR:      /* u.map_iterator_data */-        case JS_CLASS_ARRAY_ITERATOR:    /* u.array_iterator_data */-        case JS_CLASS_STRING_ITERATOR:   /* u.array_iterator_data */-        case JS_CLASS_PROXY:             /* u.proxy_data */-        case JS_CLASS_PROMISE:           /* u.promise_data */-        case JS_CLASS_PROMISE_RESOLVE_FUNCTION:  /* u.promise_function_data */-        case JS_CLASS_PROMISE_REJECT_FUNCTION:   /* u.promise_function_data */-        case JS_CLASS_ASYNC_FUNCTION_RESOLVE:    /* u.async_function_data */-        case JS_CLASS_ASYNC_FUNCTION_REJECT:     /* u.async_function_data */-        case JS_CLASS_ASYNC_FROM_SYNC_ITERATOR:  /* u.async_from_sync_iterator_data */-        case JS_CLASS_ASYNC_GENERATOR:   /* u.async_generator_data */-            /* TODO */-        default:-            /* XXX: class definition should have an opaque block size */-            if (p->u.opaque) {-                s->memory_used_count += 1;-            }-            break;-        }-    }-    s->obj_size += s->obj_count * sizeof(JSObject);--    /* hashed shapes */-    s->memory_used_count++; /* rt->shape_hash */-    s->memory_used_size += sizeof(rt->shape_hash[0]) * rt->shape_hash_size;-    for(i = 0; i < rt->shape_hash_size; i++) {-        JSShape *sh;-        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) {-            int hash_size = sh->prop_hash_mask + 1;-            s->shape_count++;-            s->shape_size += get_shape_size(hash_size, sh->prop_size);-        }-    }--    /* atoms */-    s->memory_used_count += 2; /* rt->atom_array, rt->atom_hash */-    s->atom_count = rt->atom_count;-    s->atom_size = sizeof(rt->atom_array[0]) * rt->atom_size +-        sizeof(rt->atom_hash[0]) * rt->atom_hash_size;-    for(i = 0; i < rt->atom_size; i++) {-        JSAtomStruct *p = rt->atom_array[i];-        if (!atom_is_free(p)) {-            s->atom_size += (sizeof(*p) + (p->len << p->is_wide_char) +-                             1 - p->is_wide_char);-        }-    }-    s->str_count = round(mem.str_count);-    s->str_size = round(mem.str_size);-    s->js_func_count = mem.js_func_count;-    s->js_func_size = round(mem.js_func_size);-    s->js_func_code_size = mem.js_func_code_size;-    s->js_func_pc2line_count = mem.js_func_pc2line_count;-    s->js_func_pc2line_size = mem.js_func_pc2line_size;-    s->memory_used_count += round(mem.memory_used_count) +-        s->atom_count + s->str_count +-        s->obj_count + s->shape_count +-        s->js_func_count + s->js_func_pc2line_count;-    s->memory_used_size += s->atom_size + s->str_size +-        s->obj_size + s->prop_size + s->shape_size +-        s->js_func_size + s->js_func_code_size + s->js_func_pc2line_size;-}--void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)-{-    fprintf(fp, "QuickJS memory usage -- "-#ifdef CONFIG_BIGNUM-            "BigNum "-#endif-            CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",-            (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit);-#if 1-    if (rt) {-        static const struct {-            const char *name;-            size_t size;-        } object_types[] = {-            { "JSRuntime", sizeof(JSRuntime) },-            { "JSContext", sizeof(JSContext) },-            { "JSObject", sizeof(JSObject) },-            { "JSString", sizeof(JSString) },-            { "JSFunctionBytecode", sizeof(JSFunctionBytecode) },-        };-        int i, usage_size_ok = 0;-        for(i = 0; i < countof(object_types); i++) {-            unsigned int size = object_types[i].size;-            void *p = js_malloc_rt(rt, size);-            if (p) {-                unsigned int size1 = js_malloc_usable_size_rt(rt, p);-                if (size1 >= size) {-                    usage_size_ok = 1;-                    fprintf(fp, "  %3u + %-2u  %s\n",-                            size, size1 - size, object_types[i].name);-                }-                js_free_rt(rt, p);-            }-        }-        if (!usage_size_ok) {-            fprintf(fp, "  malloc_usable_size unavailable\n");-        }-        {-            int obj_classes[JS_CLASS_INIT_COUNT + 1] = { 0 };-            int class_id;-            struct list_head *el;-            list_for_each(el, &rt->gc_obj_list) {-                JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link);-                JSObject *p;-                if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {-                    p = (JSObject *)gp;-                    obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++;-                }-            }-            fprintf(fp, "\n" "JSObject classes\n");-            if (obj_classes[0])-                fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[0], 0, "none");-            for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {-                if (obj_classes[class_id]) {-                    char buf[ATOM_GET_STR_BUF_SIZE];-                    fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[class_id], class_id,-                            JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name));-                }-            }-            if (obj_classes[JS_CLASS_INIT_COUNT])-                fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[JS_CLASS_INIT_COUNT], 0, "other");-        }-        fprintf(fp, "\n");-    }-#endif-    fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE");--    if (s->malloc_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per block)\n",-                "memory allocated", s->malloc_count, s->malloc_size,-                (double)s->malloc_size / s->malloc_count);-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%d overhead, %0.1f average slack)\n",-                "memory used", s->memory_used_count, s->memory_used_size,-                MALLOC_OVERHEAD, ((double)(s->malloc_size - s->memory_used_size) /-                                  s->memory_used_count));-    }-    if (s->atom_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per atom)\n",-                "atoms", s->atom_count, s->atom_size,-                (double)s->atom_size / s->atom_count);-    }-    if (s->str_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per string)\n",-                "strings", s->str_count, s->str_size,-                (double)s->str_size / s->str_count);-    }-    if (s->obj_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per object)\n",-                "objects", s->obj_count, s->obj_size,-                (double)s->obj_size / s->obj_count);-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per object)\n",-                "  properties", s->prop_count, s->prop_size,-                (double)s->prop_count / s->obj_count);-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per shape)\n",-                "  shapes", s->shape_count, s->shape_size,-                (double)s->shape_size / s->shape_count);-    }-    if (s->js_func_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",-                "bytecode functions", s->js_func_count, s->js_func_size);-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per function)\n",-                "  bytecode", s->js_func_count, s->js_func_code_size,-                (double)s->js_func_code_size / s->js_func_count);-        if (s->js_func_pc2line_count) {-            fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per function)\n",-                    "  pc2line", s->js_func_pc2line_count,-                    s->js_func_pc2line_size,-                    (double)s->js_func_pc2line_size / s->js_func_pc2line_count);-        }-    }-    if (s->c_func_count) {-        fprintf(fp, "%-20s %8"PRId64"\n", "C functions", s->c_func_count);-    }-    if (s->array_count) {-        fprintf(fp, "%-20s %8"PRId64"\n", "arrays", s->array_count);-        if (s->fast_array_count) {-            fprintf(fp, "%-20s %8"PRId64"\n", "  fast arrays", s->fast_array_count);-            fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per fast array)\n",-                    "  elements", s->fast_array_elements,-                    s->fast_array_elements * (int)sizeof(JSValue),-                    (double)s->fast_array_elements / s->fast_array_count);-        }-    }-    if (s->binary_object_count) {-        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",-                "binary objects", s->binary_object_count, s->binary_object_size);-    }-}--JSValue JS_GetGlobalObject(JSContext *ctx)-{-    return JS_DupValue(ctx, ctx->global_obj);-}--/* WARNING: obj is freed */-JSValue JS_Throw(JSContext *ctx, JSValue obj)-{-    JSRuntime *rt = ctx->rt;-    JS_FreeValue(ctx, rt->current_exception);-    rt->current_exception = obj;-    return JS_EXCEPTION;-}--/* return the pending exception (cannot be called twice). */-JSValue JS_GetException(JSContext *ctx)-{-    JSValue val;-    JSRuntime *rt = ctx->rt;-    val = rt->current_exception;-    rt->current_exception = JS_NULL;-    return val;-}--static void dbuf_put_leb128(DynBuf *s, uint32_t v)-{-    uint32_t a;-    for(;;) {-        a = v & 0x7f;-        v >>= 7;-        if (v != 0) {-            dbuf_putc(s, a | 0x80);-        } else {-            dbuf_putc(s, a);-            break;-        }-    }-}--static void dbuf_put_sleb128(DynBuf *s, int32_t v1)-{-    uint32_t v = v1;-    dbuf_put_leb128(s, (2 * v) ^ -(v >> 31));-}--static int get_leb128(uint32_t *pval, const uint8_t *buf,-                      const uint8_t *buf_end)-{-    const uint8_t *ptr = buf;-    uint32_t v, a, i;-    v = 0;-    for(i = 0; i < 5; i++) {-        if (unlikely(ptr >= buf_end))-            break;-        a = *ptr++;-        v |= (a & 0x7f) << (i * 7);-        if (!(a & 0x80)) {-            *pval = v;-            return ptr - buf;-        }-    }-    *pval = 0;-    return -1;-}--static int get_sleb128(int32_t *pval, const uint8_t *buf,-                       const uint8_t *buf_end)-{-    int ret;-    uint32_t val;-    ret = get_leb128(&val, buf, buf_end);-    if (ret < 0) {-        *pval = 0;-        return -1;-    }-    *pval = (val >> 1) ^ -(val & 1);-    return ret;-}--static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,-                         uint32_t pc_value)-{-    const uint8_t *p_end, *p;-    int new_line_num, line_num, pc, v, ret;-    unsigned int op;--    if (!b->has_debug || !b->debug.pc2line_buf) {-        /* function was stripped */-        return -1;-    }--    p = b->debug.pc2line_buf;-    p_end = p + b->debug.pc2line_len;-    pc = 0;-    line_num = b->debug.line_num;-    while (p < p_end) {-        op = *p++;-        if (op == 0) {-            uint32_t val;-            ret = get_leb128(&val, p, p_end);-            if (ret < 0)-                goto fail;-            pc += val;-            p += ret;-            ret = get_sleb128(&v, p, p_end);-            if (ret < 0) {-            fail:-                /* should never happen */-                return b->debug.line_num;-            }-            p += ret;-            new_line_num = line_num + v;-        } else {-            op -= PC2LINE_OP_FIRST;-            pc += (op / PC2LINE_RANGE);-            new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE;-        }-        if (pc_value < pc)-            return line_num;-        line_num = new_line_num;-    }-    return line_num;-}--/* in order to avoid executing arbitrary code during the stack trace-   generation, we only look at simple 'name' properties containing a-   string. */-static const char *get_func_name(JSContext *ctx, JSValueConst func)-{-    JSProperty *pr;-    JSShapeProperty *prs;-    JSValueConst val;-    -    if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)-        return NULL;-    prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name);-    if (!prs)-        return NULL;-    if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)-        return NULL;-    val = pr->u.value;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)-        return NULL;-    return JS_ToCString(ctx, val);-}--#define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0)-/* only taken into account if filename is provided */-#define JS_BACKTRACE_FLAG_SINGLE_LEVEL     (1 << 1)--/* if filename != NULL, an additional level is added with the filename-   and line number information (used for parse error). */-static void build_backtrace(JSContext *ctx, JSValueConst error_obj,-                            const char *filename, int line_num,-                            int backtrace_flags)-{-    JSStackFrame *sf;-    JSValue str;-    DynBuf dbuf;-    const char *func_name_str;-    const char *str1;-    JSObject *p;-    BOOL backtrace_barrier;-    -    js_dbuf_init(ctx, &dbuf);-    if (filename) {-        dbuf_printf(&dbuf, "    at %s", filename);-        if (line_num != -1)-            dbuf_printf(&dbuf, ":%d", line_num);-        dbuf_putc(&dbuf, '\n');-        str = JS_NewString(ctx, filename);-        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-        if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)-            goto done;-    }-    for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {-        if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {-            backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;-            continue;-        }-        func_name_str = get_func_name(ctx, sf->cur_func);-        if (!func_name_str || func_name_str[0] == '\0')-            str1 = "<anonymous>";-        else-            str1 = func_name_str;-        dbuf_printf(&dbuf, "    at %s", str1);-        JS_FreeCString(ctx, func_name_str);--        p = JS_VALUE_GET_OBJ(sf->cur_func);-        backtrace_barrier = FALSE;-        if (js_class_has_bytecode(p->class_id)) {-            JSFunctionBytecode *b;-            const char *atom_str;-            int line_num1;--            b = p->u.func.function_bytecode;-            backtrace_barrier = b->backtrace_barrier;-            if (b->has_debug) {-                line_num1 = find_line_num(ctx, b,-                                          sf->cur_pc - b->byte_code_buf - 1);-                atom_str = JS_AtomToCString(ctx, b->debug.filename);-                dbuf_printf(&dbuf, " (%s",-                            atom_str ? atom_str : "<null>");-                JS_FreeCString(ctx, atom_str);-                if (line_num1 != -1)-                    dbuf_printf(&dbuf, ":%d", line_num1);-                dbuf_putc(&dbuf, ')');-            }-        } else {-            dbuf_printf(&dbuf, " (native)");-        }-        dbuf_putc(&dbuf, '\n');-        /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */-        if (backtrace_barrier)-            break;-    }- done:-    dbuf_putc(&dbuf, '\0');-    if (dbuf_error(&dbuf))-        str = JS_NULL;-    else-        str = JS_NewString(ctx, (char *)dbuf.buf);-    dbuf_free(&dbuf);-    JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str,-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-}--/* Note: it is important that no exception is returned by this function */-static BOOL is_backtrace_needed(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    if (p->class_id != JS_CLASS_ERROR)-        return FALSE;-    if (find_own_property1(p, JS_ATOM_stack))-        return FALSE;-    return TRUE;-}--JSValue JS_NewError(JSContext *ctx)-{-    return JS_NewObjectClass(ctx, JS_CLASS_ERROR);-}--static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,-                              const char *fmt, va_list ap, BOOL add_backtrace)-{-    char buf[256];-    JSValue obj, ret;--    vsnprintf(buf, sizeof(buf), fmt, ap);-    obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num],-                                 JS_CLASS_ERROR);-    if (unlikely(JS_IsException(obj))) {-        /* out of memory: throw JS_NULL to avoid recursing */-        obj = JS_NULL;-    } else {-        JS_DefinePropertyValue(ctx, obj, JS_ATOM_message,-                               JS_NewString(ctx, buf),-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    }-    if (add_backtrace) {-        build_backtrace(ctx, obj, NULL, 0, 0);-    }-    ret = JS_Throw(ctx, obj);-    return ret;-}--static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,-                             const char *fmt, va_list ap)-{-    JSRuntime *rt = ctx->rt;-    JSStackFrame *sf;-    BOOL add_backtrace;--    /* the backtrace is added later if called from a bytecode function */-    sf = rt->current_stack_frame;-    add_backtrace = !rt->in_out_of_memory &&-        (!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL));-    return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);-}--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)-{-    JSValue val;-    va_list ap;--    va_start(ap, fmt);-    val = JS_ThrowError(ctx, JS_SYNTAX_ERROR, fmt, ap);-    va_end(ap);-    return val;-}--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)-{-    JSValue val;-    va_list ap;--    va_start(ap, fmt);-    val = JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap);-    va_end(ap);-    return val;-}--static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)-{-    va_list ap;--    if ((flags & JS_PROP_THROW) ||-        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {-        va_start(ap, fmt);-        JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap);-        va_end(ap);-        return -1;-    } else {-        return FALSE;-    }-}--/* never use it directly */-static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    return JS_ThrowTypeError(ctx, fmt,-                             JS_AtomGetStr(ctx, buf, sizeof(buf), atom));-}--/* never use it directly */-static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    return JS_ThrowSyntaxError(ctx, fmt,-                             JS_AtomGetStr(ctx, buf, sizeof(buf), atom));-}--/* %s is replaced by 'atom'. The macro is used so that gcc can check-    the format string. */-#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")-#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")--static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)-{-    if ((flags & JS_PROP_THROW) ||-        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {-        JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom);-        return -1;-    } else {-        return FALSE;-    }-}--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)-{-    JSValue val;-    va_list ap;--    va_start(ap, fmt);-    val = JS_ThrowError(ctx, JS_REFERENCE_ERROR, fmt, ap);-    va_end(ap);-    return val;-}--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)-{-    JSValue val;-    va_list ap;--    va_start(ap, fmt);-    val = JS_ThrowError(ctx, JS_RANGE_ERROR, fmt, ap);-    va_end(ap);-    return val;-}--JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)-{-    JSValue val;-    va_list ap;--    va_start(ap, fmt);-    val = JS_ThrowError(ctx, JS_INTERNAL_ERROR, fmt, ap);-    va_end(ap);-    return val;-}--JSValue JS_ThrowOutOfMemory(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    if (!rt->in_out_of_memory) {-        rt->in_out_of_memory = TRUE;-        JS_ThrowInternalError(ctx, "out of memory");-        rt->in_out_of_memory = FALSE;-    }-    return JS_EXCEPTION;-}--static JSValue JS_ThrowStackOverflow(JSContext *ctx)-{-    return JS_ThrowInternalError(ctx, "stack overflow");-}--static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "not an object");-}--static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "not a symbol");-}--static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    return JS_ThrowReferenceError(ctx, "'%s' is not defined",-                                  JS_AtomGetStr(ctx, buf, sizeof(buf), name));-}--static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    return JS_ThrowReferenceError(ctx, "%s is not initialized",-                                  name == JS_ATOM_NULL ? "lexical variable" :-                                  JS_AtomGetStr(ctx, buf, sizeof(buf), name));-}--static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)-{-    JSRuntime *rt = ctx->rt;-    JSAtom name;-    name = rt->class_array[class_id].class_name;-    return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);-}--static no_inline __exception int __js_poll_interrupts(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;-    if (rt->interrupt_handler) {-        if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {-            /* XXX: should set a specific flag to avoid catching */-            JS_ThrowInternalError(ctx, "interrupted");-            JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);-            return -1;-        }-    }-    return 0;-}--static inline __exception int js_poll_interrupts(JSContext *ctx)-{-    if (unlikely(--ctx->interrupt_counter <= 0)) {-        return __js_poll_interrupts(ctx);-    } else {-        return 0;-    }-}--/* return -1 (exception) or TRUE/FALSE */-static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,-                                   JSValueConst proto_val,-                                   BOOL throw_flag)-{-    JSObject *proto, *p, *p1;-    JSShape *sh;--    if (throw_flag) {-        if (JS_VALUE_GET_TAG(obj) == JS_TAG_NULL ||-            JS_VALUE_GET_TAG(obj) == JS_TAG_UNDEFINED)-            goto not_obj;-    } else {-        if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-            goto not_obj;-    }-    p = JS_VALUE_GET_OBJ(obj);-    if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) {-        if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_NULL) {-        not_obj:-            JS_ThrowTypeErrorNotAnObject(ctx);-            return -1;-        }-        proto = NULL;-    } else {-        proto = JS_VALUE_GET_OBJ(proto_val);-    }--    if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return TRUE;--    if (unlikely(p->class_id == JS_CLASS_PROXY))-        return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag);-    sh = p->shape;-    if (sh->proto == proto)-        return TRUE;-    if (!p->extensible) {-        if (throw_flag) {-            JS_ThrowTypeError(ctx, "object is not extensible");-            return -1;-        } else {-            return FALSE;-        }-    }-    if (proto) {-        /* check if there is a cycle */-        p1 = proto;-        do {-            if (p1 == p) {-                if (throw_flag) {-                    JS_ThrowTypeError(ctx, "circular prototype chain");-                    return -1;-                } else {-                    return FALSE;-                }-            }-            /* Note: for Proxy objects, proto is NULL */-            p1 = p1->shape->proto;-        } while (p1 != NULL);-        JS_DupValue(ctx, proto_val);-    }--    if (js_shape_prepare_update(ctx, p, NULL))-        return -1;-    sh = p->shape;-    if (sh->proto)-        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));-    sh->proto = proto;-    return TRUE;-}--/* return -1 (exception) or TRUE/FALSE */-int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)-{-    return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);-}--/* Only works for primitive types, otherwise return JS_NULL. */-static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)-{-    switch(JS_VALUE_GET_NORM_TAG(val)) {-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        val = ctx->class_proto[JS_CLASS_BIG_INT];-        break;-    case JS_TAG_BIG_FLOAT:-        val = ctx->class_proto[JS_CLASS_BIG_FLOAT];-        break;-    case JS_TAG_BIG_DECIMAL:-        val = ctx->class_proto[JS_CLASS_BIG_DECIMAL];-        break;-#endif-    case JS_TAG_INT:-    case JS_TAG_FLOAT64:-        val = ctx->class_proto[JS_CLASS_NUMBER];-        break;-    case JS_TAG_BOOL:-        val = ctx->class_proto[JS_CLASS_BOOLEAN];-        break;-    case JS_TAG_STRING:-        val = ctx->class_proto[JS_CLASS_STRING];-        break;-    case JS_TAG_SYMBOL:-        val = ctx->class_proto[JS_CLASS_SYMBOL];-        break;-    case JS_TAG_OBJECT:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-    default:-        val = JS_NULL;-        break;-    }-    return val;-}--/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */-JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)-{-    JSValue val;-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        JSObject *p;-        p = JS_VALUE_GET_OBJ(obj);-        if (unlikely(p->class_id == JS_CLASS_PROXY)) {-            val = js_proxy_getPrototypeOf(ctx, obj);-        } else {-            p = p->shape->proto;-            if (!p)-                val = JS_NULL;-            else-                val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-        }-    } else {-        val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj));-    }-    return val;-}--static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)-{-    JSValue obj1;-    obj1 = JS_GetPrototype(ctx, obj);-    JS_FreeValue(ctx, obj);-    return obj1;-}--/* return TRUE, FALSE or (-1) in case of exception */-static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,-                                   JSValueConst obj)-{-    JSValue obj_proto;-    JSObject *proto;-    const JSObject *p, *proto1;-    BOOL ret;--    if (!JS_IsFunction(ctx, obj))-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    if (p->class_id == JS_CLASS_BOUND_FUNCTION) {-        JSBoundFunction *s = p->u.bound_function;-        return JS_IsInstanceOf(ctx, val, s->func_obj);-    }--    /* Only explicitly boxed values are instances of constructors */-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype);-    if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) {-        if (!JS_IsException(obj_proto))-            JS_ThrowTypeError(ctx, "operand 'prototype' property is not an object");-        ret = -1;-        goto done;-    }-    proto = JS_VALUE_GET_OBJ(obj_proto);-    p = JS_VALUE_GET_OBJ(val);-    for(;;) {-        proto1 = p->shape->proto;-        if (!proto1) {-            /* slow case if proxy in the prototype chain */-            if (unlikely(p->class_id == JS_CLASS_PROXY)) {-                JSValue obj1;-                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));-                for(;;) {-                    obj1 = JS_GetPrototypeFree(ctx, obj1);-                    if (JS_IsException(obj1)) {-                        ret = -1;-                        break;-                    }-                    if (JS_IsNull(obj1)) {-                        ret = FALSE;-                        break;-                    }-                    if (proto == JS_VALUE_GET_OBJ(obj1)) {-                        JS_FreeValue(ctx, obj1);-                        ret = TRUE;-                        break;-                    }-                    /* must check for timeout to avoid infinite loop */-                    if (js_poll_interrupts(ctx)) {-                        JS_FreeValue(ctx, obj1);-                        ret = -1;-                        break;-                    }-                }-            } else {-                ret = FALSE;-            }-            break;-        }-        p = proto1;-        if (proto == p) {-            ret = TRUE;-            break;-        }-    }-done:-    JS_FreeValue(ctx, obj_proto);-    return ret;-}--/* return TRUE, FALSE or (-1) in case of exception */-int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj)-{-    JSValue method;--    if (!JS_IsObject(obj))-        goto fail;-    method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_hasInstance);-    if (JS_IsException(method))-        return -1;-    if (!JS_IsNull(method) && !JS_IsUndefined(method)) {-        JSValue ret;-        ret = JS_CallFree(ctx, method, obj, 1, &val);-        return JS_ToBoolFree(ctx, ret);-    }--    /* legacy case */-    if (!JS_IsFunction(ctx, obj)) {-    fail:-        JS_ThrowTypeError(ctx, "invalid 'instanceof' right operand");-        return -1;-    }-    return JS_OrdinaryIsInstanceOf(ctx, val, obj);-}--typedef int JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);--static JSAutoInitFunc *js_autoinit_func_table[] = {-    js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */-    js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */-    JS_InstantiateFunctionListItem, /* JS_AUTOINIT_ID_PROP */-};--static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,-                               JSProperty *pr)-{-    int ret;-    JSContext *realm;-    JSAutoInitFunc *func;-    -    realm = js_autoinit_get_realm(pr);-    func = js_autoinit_func_table[js_autoinit_get_id(pr)];-    ret = func(realm, p, prop, pr->u.init.opaque);-    return ret;-}--JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,-                               JSAtom prop, JSValueConst this_obj,-                               BOOL throw_ref_error)-{-    JSObject *p;-    JSProperty *pr;-    JSShapeProperty *prs;-    uint32_t tag;--    tag = JS_VALUE_GET_TAG(obj);-    if (unlikely(tag != JS_TAG_OBJECT)) {-        switch(tag) {-        case JS_TAG_NULL:-            return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop);-        case JS_TAG_UNDEFINED:-            return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", prop);-        case JS_TAG_EXCEPTION:-            return JS_EXCEPTION;-        case JS_TAG_STRING:-            {-                JSString *p1 = JS_VALUE_GET_STRING(obj);-                if (__JS_AtomIsTaggedInt(prop)) {-                    uint32_t idx, ch;-                    idx = __JS_AtomToUInt32(prop);-                    if (idx < p1->len) {-                        if (p1->is_wide_char)-                            ch = p1->u.str16[idx];-                        else-                            ch = p1->u.str8[idx];-                        return js_new_string_char(ctx, ch);-                    }-                } else if (prop == JS_ATOM_length) {-                    return JS_NewInt32(ctx, p1->len);-                }-            }-            break;-        default:-            break;-        }-        /* cannot raise an exception */-        p = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));-        if (!p)-            return JS_UNDEFINED;-    } else {-        p = JS_VALUE_GET_OBJ(obj);-    }--    for(;;) {-        prs = find_own_property(&pr, p, prop);-        if (prs) {-            /* found */-            if (unlikely(prs->flags & JS_PROP_TMASK)) {-                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                    if (unlikely(!pr->u.getset.getter)) {-                        return JS_UNDEFINED;-                    } else {-                        JSValue func = JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter);-                        /* Note: the field could be removed in the getter */-                        func = JS_DupValue(ctx, func);-                        return JS_CallFree(ctx, func, this_obj, 0, NULL);-                    }-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                    JSValue val = *pr->u.var_ref->pvalue;-                    if (unlikely(JS_IsUninitialized(val)))-                        return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-                    return JS_DupValue(ctx, val);-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                    /* Instantiate property and retry */-                    if (JS_AutoInitProperty(ctx, p, prop, pr))-                        return JS_EXCEPTION;-                    continue;-                }-            } else {-                return JS_DupValue(ctx, pr->u.value);-            }-        }-        if (unlikely(p->is_exotic)) {-            /* exotic behaviors */-            if (p->fast_array) {-                if (__JS_AtomIsTaggedInt(prop)) {-                    uint32_t idx = __JS_AtomToUInt32(prop);-                    if (idx < p->u.array.count) {-                        /* we avoid duplicating the code */-                        return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);-                    } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                               p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                        goto typed_array_oob;-                    }-                } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                           p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                    int ret;-                    ret = JS_AtomIsNumericIndex(ctx, prop);-                    if (ret != 0) {-                        if (ret < 0)-                            return JS_EXCEPTION;-                    typed_array_oob:-                        if (typed_array_is_detached(ctx, p))-                            return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-                        return JS_UNDEFINED;-                    }-                }-            } else {-                const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-                if (em) {-                    if (em->get_property) {-                        JSValue obj1, retval;-                        /* XXX: should pass throw_ref_error */-                        /* Note: if 'p' is a prototype, it can be-                           freed in the called function */-                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-                        retval = em->get_property(ctx, obj1, prop, this_obj);-                        JS_FreeValue(ctx, obj1);-                        return retval;-                    }-                    if (em->get_own_property) {-                        JSPropertyDescriptor desc;-                        int ret;-                        JSValue obj1;--                        /* Note: if 'p' is a prototype, it can be-                           freed in the called function */-                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-                        ret = em->get_own_property(ctx, &desc, obj1, prop);-                        JS_FreeValue(ctx, obj1);-                        if (ret < 0)-                            return JS_EXCEPTION;-                        if (ret) {-                            if (desc.flags & JS_PROP_GETSET) {-                                JS_FreeValue(ctx, desc.setter);-                                return JS_CallFree(ctx, desc.getter, this_obj, 0, NULL);-                            } else {-                                return desc.value;-                            }-                        }-                    }-                }-            }-        }-        p = p->shape->proto;-        if (!p)-            break;-    }-    if (unlikely(throw_ref_error)) {-        return JS_ThrowReferenceErrorNotDefined(ctx, prop);-    } else {-        return JS_UNDEFINED;-    }-}--static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)-{-    return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist",-                                 atom);-}--/* Private fields can be added even on non extensible objects or-   Proxies */-static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,-                                 JSValueConst name, JSValue val)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSAtom prop;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        goto fail;-    }-    /* safety check */-    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) {-        JS_ThrowTypeErrorNotASymbol(ctx);-        goto fail;-    }-    prop = js_symbol_to_atom(ctx, (JSValue)name);-    p = JS_VALUE_GET_OBJ(obj);-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists",-                              prop);-        goto fail;-    }-    pr = add_property(ctx, p, prop, JS_PROP_C_W_E);-    if (unlikely(!pr)) {-    fail:-        JS_FreeValue(ctx, val);-        return -1;-    }-    pr->u.value = val;-    return 0;-}--static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,-                                  JSValueConst name)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSAtom prop;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    /* safety check */-    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL))-        return JS_ThrowTypeErrorNotASymbol(ctx);-    prop = js_symbol_to_atom(ctx, (JSValue)name);-    p = JS_VALUE_GET_OBJ(obj);-    prs = find_own_property(&pr, p, prop);-    if (!prs) {-        JS_ThrowTypeErrorPrivateNotFound(ctx, prop);-        return JS_EXCEPTION;-    }-    return JS_DupValue(ctx, pr->u.value);-}--static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,-                              JSValueConst name, JSValue val)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSAtom prop;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        goto fail;-    }-    /* safety check */-    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) {-        JS_ThrowTypeErrorNotASymbol(ctx);-        goto fail;-    }-    prop = js_symbol_to_atom(ctx, (JSValue)name);-    p = JS_VALUE_GET_OBJ(obj);-    prs = find_own_property(&pr, p, prop);-    if (!prs) {-        JS_ThrowTypeErrorPrivateNotFound(ctx, prop);-    fail:-        JS_FreeValue(ctx, val);-        return -1;-    }-    set_value(ctx, &pr->u.value, val);-    return 0;-}--static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)-{-    JSObject *p, *p1;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSValue brand;-    JSAtom brand_atom;-    -    if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    p = JS_VALUE_GET_OBJ(home_obj);-    prs = find_own_property(&pr, p, JS_ATOM_Private_brand);-    if (!prs) {-        brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE);-        if (JS_IsException(brand))-            return -1;-        /* if the brand is not present, add it */-        pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E);-        if (!pr) {-            JS_FreeValue(ctx, brand);-            return -1;-        }-        pr->u.value = JS_DupValue(ctx, brand);-    } else {-        brand = JS_DupValue(ctx, pr->u.value);-    }-    brand_atom = js_symbol_to_atom(ctx, brand);-    -    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        JS_FreeAtom(ctx, brand_atom);-        return -1;-    }-    p1 = JS_VALUE_GET_OBJ(obj);-    pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);-    JS_FreeAtom(ctx, brand_atom);-    if (!pr)-        return -1;-    pr->u.value = JS_UNDEFINED;-    return 0;-}--static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)-{-    JSObject *p, *p1, *home_obj;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSValueConst brand;-    -    /* get the home object of 'func' */-    if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) {-    not_obj:-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    p1 = JS_VALUE_GET_OBJ(func);-    if (!js_class_has_bytecode(p1->class_id))-        goto not_obj;-    home_obj = p1->u.func.home_object;-    if (!home_obj)-        goto not_obj;-    prs = find_own_property(&pr, home_obj, JS_ATOM_Private_brand);-    if (!prs) {-        JS_ThrowTypeError(ctx, "expecting <brand> private field");-        return -1;-    }-    brand = pr->u.value;-    /* safety check */-    if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL))-        goto not_obj;-    -    /* get the brand array of 'obj' */-    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))-        goto not_obj;-    p = JS_VALUE_GET_OBJ(obj);-    prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));-    if (!prs) {-        JS_ThrowTypeError(ctx, "invalid brand on object");-        return -1;-    }-    return 0;-}--static int num_keys_cmp(const void *p1, const void *p2, void *opaque)-{-    JSContext *ctx = opaque;-    JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom;-    JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom;-    uint32_t v1, v2;-    BOOL atom1_is_integer, atom2_is_integer;--    atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1);-    atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2);-    assert(atom1_is_integer && atom2_is_integer);-    if (v1 < v2)-        return -1;-    else if (v1 == v2)-        return 0;-    else-        return 1;-}--static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)-{-    uint32_t i;-    if (tab) {-        for(i = 0; i < len; i++)-            JS_FreeAtom(ctx, tab[i].atom);-        js_free(ctx, tab);-    }-}--/* return < 0 in case if exception, 0 if OK. ptab and its atoms must-   be freed by the user. */-static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,-                                                      JSPropertyEnum **ptab,-                                                      uint32_t *plen,-                                                      JSObject *p, int flags)-{-    int i, j;-    JSShape *sh;-    JSShapeProperty *prs;-    JSPropertyEnum *tab_atom, *tab_exotic;-    JSAtom atom;-    uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count;-    uint32_t num_index, str_index, sym_index, exotic_count;-    BOOL is_enumerable, num_sorted;-    uint32_t num_key;-    JSAtomKindEnum kind;-    -    /* clear pointer for consistency in case of failure */-    *ptab = NULL;-    *plen = 0;--    /* compute the number of returned properties */-    num_keys_count = 0;-    str_keys_count = 0;-    sym_keys_count = 0;-    exotic_count = 0;-    tab_exotic = NULL;-    sh = p->shape;-    for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {-        atom = prs->atom;-        if (atom != JS_ATOM_NULL) {-            is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0);-            kind = JS_AtomGetKind(ctx, atom);-            if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&-                ((flags >> kind) & 1) != 0) {-                /* need to raise an exception in case of the module-                   name space (implicit GetOwnProperty) */-                if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) &&-                    (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY))) {-                    JSVarRef *var_ref = p->prop[i].u.var_ref;-                    if (unlikely(JS_IsUninitialized(*var_ref->pvalue))) {-                        JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-                        return -1;-                    }-                }-                if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {-                    num_keys_count++;-                } else if (kind == JS_ATOM_KIND_STRING) {-                    str_keys_count++;-                } else {-                    sym_keys_count++;-                }-            }-        }-    }--    if (p->is_exotic) {-        if (p->fast_array) {-            /* the implicit GetOwnProperty raises an exception if the-               typed array is detached */-            if ((flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) &&-                 (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                  p->class_id <= JS_CLASS_FLOAT64_ARRAY) &&-                 typed_array_is_detached(ctx, p) &&-                typed_array_get_length(ctx, p) != 0) {-                JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-                return -1;-            }-            if (flags & JS_GPN_STRING_MASK) {-                num_keys_count += p->u.array.count;-            }-        } else {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em && em->get_own_property_names) {-                if (em->get_own_property_names(ctx, &tab_exotic, &exotic_count,-                                               JS_MKPTR(JS_TAG_OBJECT, p)))-                    return -1;-                for(i = 0; i < exotic_count; i++) {-                    atom = tab_exotic[i].atom;-                    kind = JS_AtomGetKind(ctx, atom);-                    if (((flags >> kind) & 1) != 0) {-                        is_enumerable = FALSE;-                        if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) {-                            JSPropertyDescriptor desc;-                            int res;-                            /* set the "is_enumerable" field if necessary */-                            res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);-                            if (res < 0) {-                                js_free_prop_enum(ctx, tab_exotic, exotic_count);-                                return -1;-                            }-                            if (res) {-                                is_enumerable =-                                    ((desc.flags & JS_PROP_ENUMERABLE) != 0);-                                js_free_desc(ctx, &desc);-                            }-                            tab_exotic[i].is_enumerable = is_enumerable;-                        }-                        if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) {-                            if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {-                                num_keys_count++;-                            } else if (kind == JS_ATOM_KIND_STRING) {-                                str_keys_count++;-                            } else {-                                sym_keys_count++;-                            }-                        }-                    }-                }-            }-        }-    }--    /* fill them */--    atom_count = num_keys_count + str_keys_count + sym_keys_count;-    /* avoid allocating 0 bytes */-    tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1));-    if (!tab_atom) {-        js_free_prop_enum(ctx, tab_exotic, exotic_count);-        return -1;-    }--    num_index = 0;-    str_index = num_keys_count;-    sym_index = str_index + str_keys_count;--    num_sorted = TRUE;-    sh = p->shape;-    for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {-        atom = prs->atom;-        if (atom != JS_ATOM_NULL) {-            is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0);-            kind = JS_AtomGetKind(ctx, atom);-            if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&-                ((flags >> kind) & 1) != 0) {-                if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {-                    j = num_index++;-                    num_sorted = FALSE;-                } else if (kind == JS_ATOM_KIND_STRING) {-                    j = str_index++;-                } else {-                    j = sym_index++;-                }-                tab_atom[j].atom = JS_DupAtom(ctx, atom);-                tab_atom[j].is_enumerable = is_enumerable;-            }-        }-    }--    if (p->is_exotic) {-        if (p->fast_array) {-            if (flags & JS_GPN_STRING_MASK) {-                for(i = 0; i < p->u.array.count; i++) {-                    tab_atom[num_index].atom = __JS_AtomFromUInt32(i);-                    if (tab_atom[num_index].atom == JS_ATOM_NULL) {-                        js_free_prop_enum(ctx, tab_exotic, exotic_count);-                        js_free_prop_enum(ctx, tab_atom, num_index);-                        return -1;-                    }-                    tab_atom[num_index].is_enumerable = TRUE;-                    num_index++;-                }-            }-        }-        if (exotic_count > 0) {-            for(i = 0; i < exotic_count; i++) {-                atom = tab_exotic[i].atom;-                is_enumerable = tab_exotic[i].is_enumerable;-                kind = JS_AtomGetKind(ctx, atom);-                if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&-                    ((flags >> kind) & 1) != 0) {-                    if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {-                        j = num_index++;-                        num_sorted = FALSE;-                    } else if (kind == JS_ATOM_KIND_STRING) {-                        j = str_index++;-                    } else {-                        j = sym_index++;-                    }-                    tab_atom[j].atom = atom;-                    tab_atom[j].is_enumerable = is_enumerable;-                } else {-                    JS_FreeAtom(ctx, atom);-                }-            }-        }-        js_free(ctx, tab_exotic);-    }--    assert(num_index == num_keys_count);-    assert(str_index == num_keys_count + str_keys_count);-    assert(sym_index == atom_count);--    if (num_keys_count != 0 && !num_sorted) {-        rqsort(tab_atom, num_keys_count, sizeof(tab_atom[0]), num_keys_cmp,-               ctx);-    }-    *ptab = tab_atom;-    *plen = atom_count;-    return 0;-}--int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,-                           uint32_t *plen, JSValueConst obj, int flags)-{-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen,-                                          JS_VALUE_GET_OBJ(obj), flags);-}--/* Return -1 if exception,-   FALSE if the property does not exist, TRUE if it exists. If TRUE is-   returned, the property descriptor 'desc' is filled present. */-static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,-                                     JSObject *p, JSAtom prop)-{-    JSShapeProperty *prs;-    JSProperty *pr;--retry:-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        if (desc) {-            desc->flags = prs->flags & JS_PROP_C_W_E;-            desc->getter = JS_UNDEFINED;-            desc->setter = JS_UNDEFINED;-            desc->value = JS_UNDEFINED;-            if (unlikely(prs->flags & JS_PROP_TMASK)) {-                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                    desc->flags |= JS_PROP_GETSET;-                    if (pr->u.getset.getter)-                        desc->getter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));-                    if (pr->u.getset.setter)-                        desc->setter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                    JSValue val = *pr->u.var_ref->pvalue;-                    if (unlikely(JS_IsUninitialized(val))) {-                        JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-                        return -1;-                    }-                    desc->value = JS_DupValue(ctx, val);-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                    /* Instantiate property and retry */-                    if (JS_AutoInitProperty(ctx, p, prop, pr))-                        return -1;-                    goto retry;-                }-            } else {-                desc->value = JS_DupValue(ctx, pr->u.value);-            }-        } else {-            /* for consistency, send the exception even if desc is NULL */-            if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF)) {-                if (unlikely(JS_IsUninitialized(*pr->u.var_ref->pvalue))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-                    return -1;-                }-            } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                /* nothing to do: delay instantiation until actual value and/or attributes are read */-            }-        }-        return TRUE;-    }-    if (p->is_exotic) {-        if (p->fast_array) {-            /* specific case for fast arrays */-            if (__JS_AtomIsTaggedInt(prop)) {-                uint32_t idx;-                idx = __JS_AtomToUInt32(prop);-                if (idx < p->u.array.count) {-                    if (desc) {-                        desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE;-                        if (p->class_id == JS_CLASS_ARRAY ||-                            p->class_id == JS_CLASS_ARGUMENTS)-                            desc->flags |= JS_PROP_CONFIGURABLE;-                        desc->getter = JS_UNDEFINED;-                        desc->setter = JS_UNDEFINED;-                        desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);-                    }-                    return TRUE;-                }-            }-            if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                int ret;-                ret = JS_AtomIsNumericIndex(ctx, prop);-                if (ret != 0) {-                    if (ret < 0)-                        return -1;-                    if (typed_array_is_detached(ctx, p)) {-                        JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-                        return -1;-                    }-                }-            }-        } else {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em && em->get_own_property) {-                return em->get_own_property(ctx, desc,-                                            JS_MKPTR(JS_TAG_OBJECT, p), prop);-            }-        }-    }-    return FALSE;-}--int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,-                      JSValueConst obj, JSAtom prop)-{-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop);-}--/* return -1 if exception (Proxy object only) or TRUE/FALSE */-int JS_IsExtensible(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    if (unlikely(p->class_id == JS_CLASS_PROXY))-        return js_proxy_isExtensible(ctx, obj);-    else-        return p->extensible;-}--/* return -1 if exception (Proxy object only) or TRUE/FALSE */-int JS_PreventExtensions(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    if (unlikely(p->class_id == JS_CLASS_PROXY))-        return js_proxy_preventExtensions(ctx, obj);-    p->extensible = FALSE;-    return TRUE;-}--/* return -1 if exception otherwise TRUE or FALSE */-int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)-{-    JSObject *p;-    int ret;-    JSValue obj1;--    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    for(;;) {-        if (p->is_exotic) {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em && em->has_property) {-                /* has_property can free the prototype */-                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-                ret = em->has_property(ctx, obj1, prop);-                JS_FreeValue(ctx, obj1);-                return ret;-            }-        }-        /* JS_GetOwnPropertyInternal can free the prototype */-        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-        ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);-        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-        if (ret != 0)-            return ret;-        if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-            p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-            ret = JS_AtomIsNumericIndex(ctx, prop);-            if (ret != 0) {-                if (ret < 0)-                    return -1;-                /* the detached array test was done in-                   JS_GetOwnPropertyInternal() */-                return FALSE;-            }-        }-        p = p->shape->proto;-        if (!p)-            break;-    }-    return FALSE;-}--/* val must be a symbol */-static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val)-{-    JSAtomStruct *p = JS_VALUE_GET_PTR(val);-    return js_get_atom_index(ctx->rt, p);-}--/* return JS_ATOM_NULL in case of exception */-JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)-{-    JSAtom atom;-    uint32_t tag;-    tag = JS_VALUE_GET_TAG(val);-    if (tag == JS_TAG_INT &&-        (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {-        /* fast path for integer values */-        atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));-    } else if (tag == JS_TAG_SYMBOL) {-        JSAtomStruct *p = JS_VALUE_GET_PTR(val);-        atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));-    } else {-        JSValue str;-        str = JS_ToPropertyKey(ctx, val);-        if (JS_IsException(str))-            return JS_ATOM_NULL;-        if (JS_VALUE_GET_TAG(str) == JS_TAG_SYMBOL) {-            atom = js_symbol_to_atom(ctx, str);-        } else {-            atom = JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(str));-        }-    }-    return atom;-}--static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,-                                   JSValue prop)-{-    JSAtom atom;-    JSValue ret;--    if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&-               JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {-        JSObject *p;-        uint32_t idx, len;-        /* fast path for array access */-        p = JS_VALUE_GET_OBJ(this_obj);-        idx = JS_VALUE_GET_INT(prop);-        len = (uint32_t)p->u.array.count;-        if (unlikely(idx >= len))-            goto slow_path;-        switch(p->class_id) {-        case JS_CLASS_ARRAY:-        case JS_CLASS_ARGUMENTS:-            return JS_DupValue(ctx, p->u.array.u.values[idx]);-        case JS_CLASS_INT8_ARRAY:-            return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]);-        case JS_CLASS_UINT8C_ARRAY:-        case JS_CLASS_UINT8_ARRAY:-            return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]);-        case JS_CLASS_INT16_ARRAY:-            return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]);-        case JS_CLASS_UINT16_ARRAY:-            return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]);-        case JS_CLASS_INT32_ARRAY:-            return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]);-        case JS_CLASS_UINT32_ARRAY:-            return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]);-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT64_ARRAY:-            return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);-        case JS_CLASS_BIG_UINT64_ARRAY:-            return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);-#endif-        case JS_CLASS_FLOAT32_ARRAY:-            return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);-        case JS_CLASS_FLOAT64_ARRAY:-            return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);-        default:-            goto slow_path;-        }-    } else {-    slow_path:-        atom = JS_ValueToAtom(ctx, prop);-        JS_FreeValue(ctx, prop);-        if (unlikely(atom == JS_ATOM_NULL))-            return JS_EXCEPTION;-        ret = JS_GetProperty(ctx, this_obj, atom);-        JS_FreeAtom(ctx, atom);-        return ret;-    }-}--JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,-                             uint32_t idx)-{-    return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx));-}--/* Check if an object has a generalized numeric property. Return value:-   -1 for exception,-   TRUE if property exists, stored into *pval,-   FALSE if proprty does not exist.- */-static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval)-{-    JSValue val = JS_UNDEFINED;-    JSAtom prop;-    int present;--    if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {-        /* fast path */-        present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));-        if (present > 0) {-            val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));-            if (unlikely(JS_IsException(val)))-                present = -1;-        }-    } else {-        prop = JS_NewAtomInt64(ctx, idx);-        present = -1;-        if (likely(prop != JS_ATOM_NULL)) {-            present = JS_HasProperty(ctx, obj, prop);-            if (present > 0) {-                val = JS_GetProperty(ctx, obj, prop);-                if (unlikely(JS_IsException(val)))-                    present = -1;-            }-            JS_FreeAtom(ctx, prop);-        }-    }-    *pval = val;-    return present;-}--static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx)-{-    JSAtom prop;-    JSValue val;--    if ((uint64_t)idx <= INT32_MAX) {-        /* fast path for fast arrays */-        return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));-    }-    prop = JS_NewAtomInt64(ctx, idx);-    if (prop == JS_ATOM_NULL)-        return JS_EXCEPTION;--    val = JS_GetProperty(ctx, obj, prop);-    JS_FreeAtom(ctx, prop);-    return val;-}--JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,-                          const char *prop)-{-    JSAtom atom;-    JSValue ret;-    atom = JS_NewAtom(ctx, prop);-    ret = JS_GetProperty(ctx, this_obj, atom);-    JS_FreeAtom(ctx, atom);-    return ret;-}--/* Note: the property value is not initialized. Return NULL if memory-   error. */-static JSProperty *add_property(JSContext *ctx,-                                JSObject *p, JSAtom prop, int prop_flags)-{-    JSShape *sh, *new_sh;--    sh = p->shape;-    if (sh->is_hashed) {-        /* try to find an existing shape */-        new_sh = find_hashed_shape_prop(ctx->rt, sh, prop, prop_flags);-        if (new_sh) {-            /* matching shape found: use it */-            /*  the property array may need to be resized */-            if (new_sh->prop_size != sh->prop_size) {-                JSProperty *new_prop;-                new_prop = js_realloc(ctx, p->prop, sizeof(p->prop[0]) *-                                      new_sh->prop_size);-                if (!new_prop)-                    return NULL;-                p->prop = new_prop;-            }-            p->shape = js_dup_shape(new_sh);-            js_free_shape(ctx->rt, sh);-            return &p->prop[new_sh->prop_count - 1];-        } else if (sh->header.ref_count != 1) {-            /* if the shape is shared, clone it */-            new_sh = js_clone_shape(ctx, sh);-            if (!new_sh)-                return NULL;-            /* hash the cloned shape */-            new_sh->is_hashed = TRUE;-            js_shape_hash_link(ctx->rt, new_sh);-            js_free_shape(ctx->rt, p->shape);-            p->shape = new_sh;-        }-    }-    assert(p->shape->header.ref_count == 1);-    if (add_shape_property(ctx, &p->shape, p, prop, prop_flags))-        return NULL;-    return &p->prop[p->shape->prop_count - 1];-}--/* can be called on Array or Arguments objects. return < 0 if-   memory alloc error. */-static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,-                                                             JSObject *p)-{-    JSProperty *pr;-    JSShape *sh;-    JSValue *tab;-    uint32_t i, len, new_count;--    if (js_shape_prepare_update(ctx, p, NULL))-        return -1;-    len = p->u.array.count;-    /* resize the properties once to simplify the error handling */-    sh = p->shape;-    new_count = sh->prop_count + len;-    if (new_count > sh->prop_size) {-        if (resize_properties(ctx, &p->shape, p, new_count))-            return -1;-    }--    tab = p->u.array.u.values;-    for(i = 0; i < len; i++) {-        /* add_property cannot fail here but-           __JS_AtomFromUInt32(i) fails for i > INT32_MAX */-        pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);-        pr->u.value = *tab++;-    }-    js_free(ctx, p->u.array.u.values);-    p->u.array.count = 0;-    p->u.array.u.values = NULL; /* fail safe */-    p->u.array.u1.size = 0;-    p->fast_array = 0;-    return 0;-}--static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)-{-    JSShape *sh;-    JSShapeProperty *pr, *lpr, *prop;-    JSProperty *pr1;-    uint32_t lpr_idx;-    intptr_t h, h1;-- redo:-    sh = p->shape;-    h1 = atom & sh->prop_hash_mask;-    h = prop_hash_end(sh)[-h1 - 1];-    prop = get_shape_prop(sh);-    lpr = NULL;-    lpr_idx = 0;   /* prevent warning */-    while (h != 0) {-        pr = &prop[h - 1];-        if (likely(pr->atom == atom)) {-            /* found ! */-            if (!(pr->flags & JS_PROP_CONFIGURABLE))-                return FALSE;-            /* realloc the shape if needed */-            if (lpr)-                lpr_idx = lpr - get_shape_prop(sh);-            if (js_shape_prepare_update(ctx, p, &pr))-                return -1;-            sh = p->shape;-            /* remove property */-            if (lpr) {-                lpr = get_shape_prop(sh) + lpr_idx;-                lpr->hash_next = pr->hash_next;-            } else {-                prop_hash_end(sh)[-h1 - 1] = pr->hash_next;-            }-            sh->deleted_prop_count++;-            /* free the entry */-            pr1 = &p->prop[h - 1];-            free_property(ctx->rt, pr1, pr->flags);-            JS_FreeAtom(ctx, pr->atom);-            /* put default values */-            pr->flags = 0;-            pr->atom = JS_ATOM_NULL;-            pr1->u.value = JS_UNDEFINED;--            /* compact the properties if too many deleted properties */-            if (sh->deleted_prop_count >= 8 &&-                sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) {-                compact_properties(ctx, p);-            }-            return TRUE;-        }-        lpr = pr;-        h = pr->hash_next;-    }--    if (p->is_exotic) {-        if (p->fast_array) {-            uint32_t idx;-            if (JS_AtomIsArrayIndex(ctx, &idx, atom) &&-                idx < p->u.array.count) {-                if (p->class_id == JS_CLASS_ARRAY ||-                    p->class_id == JS_CLASS_ARGUMENTS) {-                    /* Special case deleting the last element of a fast Array */-                    if (idx == p->u.array.count - 1) {-                        JS_FreeValue(ctx, p->u.array.u.values[idx]);-                        p->u.array.count = idx;-                        return TRUE;-                    }-                    if (convert_fast_array_to_array(ctx, p))-                        return -1;-                    goto redo;-                } else {-                    return FALSE; /* not configurable */-                }-            }-        } else {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em && em->delete_property) {-                return em->delete_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), atom);-            }-        }-    }-    /* not found */-    return TRUE;-}--static int call_setter(JSContext *ctx, JSObject *setter,-                       JSValueConst this_obj, JSValue val, int flags)-{-    JSValue ret, func;-    if (likely(setter)) {-        func = JS_MKPTR(JS_TAG_OBJECT, setter);-        /* Note: the field could be removed in the setter */-        func = JS_DupValue(ctx, func);-        ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);-        JS_FreeValue(ctx, val);-        if (JS_IsException(ret))-            return -1;-        JS_FreeValue(ctx, ret);-        return TRUE;-    } else {-        JS_FreeValue(ctx, val);-        if ((flags & JS_PROP_THROW) ||-            ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {-            JS_ThrowTypeError(ctx, "no setter for property");-            return -1;-        }-        return FALSE;-    }-}--/* set the array length and remove the array elements if necessary. */-static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, int flags)-{-    uint32_t len, idx, cur_len;-    int i, ret;--    /* Note: this call can reallocate the properties of 'p' */-    ret = JS_ToArrayLengthFree(ctx, &len, val);-    if (ret)-        return -1;--    if (likely(p->fast_array)) {-        uint32_t old_len = p->u.array.count;-        if (len < old_len) {-            for(i = len; i < old_len; i++) {-                JS_FreeValue(ctx, p->u.array.u.values[i]);-            }-            p->u.array.count = len;-        }-        p->prop[0].u.value = JS_NewUint32(ctx, len);-    } else {-        /* Note: length is always a uint32 because the object is an-           array */-        JS_ToUint32(ctx, &cur_len, p->prop[0].u.value);-        if (len < cur_len) {-            uint32_t d;-            JSShape *sh;-            JSShapeProperty *pr;--            d = cur_len - len;-            sh = p->shape;-            if (d <= sh->prop_count) {-                JSAtom atom;--                /* faster to iterate */-                while (cur_len > len) {-                    atom = JS_NewAtomUInt32(ctx, cur_len - 1);-                    ret = delete_property(ctx, p, atom);-                    JS_FreeAtom(ctx, atom);-                    if (unlikely(!ret)) {-                        /* unlikely case: property is not-                           configurable */-                        break;-                    }-                    cur_len--;-                }-            } else {-                /* faster to iterate thru all the properties. Need two-                   passes in case one of the property is not-                   configurable */-                cur_len = len;-                for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count;-                    i++, pr++) {-                    if (pr->atom != JS_ATOM_NULL &&-                        JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) {-                        if (idx >= cur_len &&-                            !(pr->flags & JS_PROP_CONFIGURABLE)) {-                            cur_len = idx + 1;-                        }-                    }-                }--                for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count;-                    i++, pr++) {-                    if (pr->atom != JS_ATOM_NULL &&-                        JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) {-                        if (idx >= cur_len) {-                            /* remove the property */-                            delete_property(ctx, p, pr->atom);-                            /* WARNING: the shape may have been modified */-                            sh = p->shape;-                            pr = get_shape_prop(sh) + i;-                        }-                    }-                }-            }-        } else {-            cur_len = len;-        }-        set_value(ctx, &p->prop[0].u.value, JS_NewUint32(ctx, cur_len));-        if (unlikely(cur_len > len)) {-            return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable");-        }-    }-    return TRUE;-}--/* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array =-   TRUE and p->extensible = TRUE */-static int add_fast_array_element(JSContext *ctx, JSObject *p,-                                  JSValue val, int flags)-{-    uint32_t new_len, array_len;-    /* extend the array by one */-    /* XXX: convert to slow array if new_len > 2^31-1 elements */-    new_len = p->u.array.count + 1;-    /* update the length if necessary. We assume that if the length is-       not an integer, then if it >= 2^31.  */-    if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) {-        array_len = JS_VALUE_GET_INT(p->prop[0].u.value);-        if (new_len > array_len) {-            if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) {-                JS_FreeValue(ctx, val);-                return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);-            }-            p->prop[0].u.value = JS_NewInt32(ctx, new_len);-        }-    }-    if (unlikely(new_len > p->u.array.u1.size)) {-        uint32_t new_size;-        size_t slack;-        JSValue *new_array_prop;-        /* XXX: potential arithmetic overflow */-        new_size = max_int(new_len, p->u.array.u1.size * 3 / 2);-        new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack);-        if (!new_array_prop) {-            JS_FreeValue(ctx, val);-            return -1;-        }-        new_size += slack / sizeof(*new_array_prop);-        p->u.array.u.values = new_array_prop;-        p->u.array.u1.size = new_size;-    }-    p->u.array.u.values[new_len - 1] = val;-    p->u.array.count = new_len;-    return TRUE;-}--static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)-{-    JS_FreeValue(ctx, desc->getter);-    JS_FreeValue(ctx, desc->setter);-    JS_FreeValue(ctx, desc->value);-}--/* generic (and slower) version of JS_SetProperty() for Reflect.set() */-static int JS_SetPropertyGeneric(JSContext *ctx,-                                 JSObject *p, JSAtom prop,-                                 JSValue val, JSValueConst this_obj,-                                 int flags)-{-    int ret;-    JSPropertyDescriptor desc;--    while (p != NULL) {-        if (p->is_exotic) {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em && em->set_property) {-                JSValue obj1;-                /* set_property can free the prototype */-                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-                ret = em->set_property(ctx, obj1, prop,-                                       val, this_obj, flags);-                JS_FreeValue(ctx, obj1);-                JS_FreeValue(ctx, val);-                return ret;-            }-        }--        ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);-        if (ret < 0)-            return ret;-        if (ret) {-            if (desc.flags & JS_PROP_GETSET) {-                JSObject *setter;-                if (JS_IsUndefined(desc.setter))-                    setter = NULL;-                else-                    setter = JS_VALUE_GET_OBJ(desc.setter);-                ret = call_setter(ctx, setter, this_obj, val, flags);-                JS_FreeValue(ctx, desc.getter);-                JS_FreeValue(ctx, desc.setter);-                return ret;-            } else {-                JS_FreeValue(ctx, desc.value);-                if (!(desc.flags & JS_PROP_WRITABLE)) {-                    goto read_only_error;-                }-            }-            break;-        }-        p = p->shape->proto;-    }--    if (!JS_IsObject(this_obj))-        return JS_ThrowTypeErrorOrFalse(ctx, flags, "receiver is not an object");--    p = JS_VALUE_GET_OBJ(this_obj);--    /* modify the property in this_obj if it already exists */-    ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);-    if (ret < 0)-        return ret;-    if (ret) {-        if (desc.flags & JS_PROP_GETSET) {-            JS_FreeValue(ctx, desc.getter);-            JS_FreeValue(ctx, desc.setter);-            JS_FreeValue(ctx, val);-            return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");-        } else {-            JS_FreeValue(ctx, desc.value);-            if (!(desc.flags & JS_PROP_WRITABLE) ||-                p->class_id == JS_CLASS_MODULE_NS) {-            read_only_error:-                JS_FreeValue(ctx, val);-                return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);-            }-        }-        ret = JS_DefineProperty(ctx, this_obj, prop, val,-                                JS_UNDEFINED, JS_UNDEFINED,-                                JS_PROP_HAS_VALUE);-        JS_FreeValue(ctx, val);-        return ret;-    }--    ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,-                            flags |-                            JS_PROP_HAS_VALUE |-                            JS_PROP_HAS_ENUMERABLE |-                            JS_PROP_HAS_WRITABLE |-                            JS_PROP_HAS_CONFIGURABLE |-                            JS_PROP_C_W_E);-    JS_FreeValue(ctx, val);-    return ret;-}--/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is-   freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD,-   JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set,-   the new property is not added and an error is raised. */-int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,-                           JSAtom prop, JSValue val, int flags)-{-    JSObject *p, *p1;-    JSShapeProperty *prs;-    JSProperty *pr;-    uint32_t tag;-    JSPropertyDescriptor desc;-    int ret;-#if 0-    printf("JS_SetPropertyInternal: "); print_atom(ctx, prop); printf("\n");-#endif-    tag = JS_VALUE_GET_TAG(this_obj);-    if (unlikely(tag != JS_TAG_OBJECT)) {-        switch(tag) {-        case JS_TAG_NULL:-            JS_FreeValue(ctx, val);-            JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);-            return -1;-        case JS_TAG_UNDEFINED:-            JS_FreeValue(ctx, val);-            JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);-            return -1;-        default:-            /* even on a primitive type we can have setters on the prototype */-            p = NULL;-            p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj));-            goto prototype_lookup;-        }-    }-    p = JS_VALUE_GET_OBJ(this_obj);-retry:-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |-                                  JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {-            /* fast case */-            set_value(ctx, &pr->u.value, val);-            return TRUE;-        } else if ((prs->flags & (JS_PROP_LENGTH | JS_PROP_WRITABLE)) ==-                   (JS_PROP_LENGTH | JS_PROP_WRITABLE)) {-            assert(p->class_id == JS_CLASS_ARRAY);-            assert(prop == JS_ATOM_length);-            return set_array_length(ctx, p, val, flags);-        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-            return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);-        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-            /* JS_PROP_WRITABLE is always true for variable-               references, but they are write protected in module name-               spaces. */-            if (p->class_id == JS_CLASS_MODULE_NS)-                goto read_only_prop;-            set_value(ctx, pr->u.var_ref->pvalue, val);-            return TRUE;-        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-            /* Instantiate property and retry (potentially useless) */-            if (JS_AutoInitProperty(ctx, p, prop, pr)) {-                JS_FreeValue(ctx, val);-                return -1;-            }-            goto retry;-        } else {-            goto read_only_prop;-        }-    }--    p1 = p;-    for(;;) {-        if (p1->is_exotic) {-            if (p1->fast_array) {-                if (__JS_AtomIsTaggedInt(prop)) {-                    uint32_t idx = __JS_AtomToUInt32(prop);-                    if (idx < p1->u.array.count) {-                        if (unlikely(p == p1))-                            return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);-                        else-                            break;-                    } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&-                               p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                        goto typed_array_oob;-                    }-                } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&-                           p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                    ret = JS_AtomIsNumericIndex(ctx, prop);-                    if (ret != 0) {-                        if (ret < 0) {-                            JS_FreeValue(ctx, val);-                            return -1;-                        }-                    typed_array_oob:-                        val = JS_ToNumberFree(ctx, val);-                        JS_FreeValue(ctx, val);-                        if (JS_IsException(val))-                            return -1;-                        if (typed_array_is_detached(ctx, p1)) {-                            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-                            return -1;-                        }-                        return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");-                    }-                }-            } else {-                const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic;-                if (em) {-                    JSValue obj1;-                    if (em->set_property) {-                        /* set_property can free the prototype */-                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));-                        ret = em->set_property(ctx, obj1, prop,-                                               val, this_obj, flags);-                        JS_FreeValue(ctx, obj1);-                        JS_FreeValue(ctx, val);-                        return ret;-                    }-                    if (em->get_own_property) {-                        /* get_own_property can free the prototype */-                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));-                        ret = em->get_own_property(ctx, &desc,-                                                   obj1, prop);-                        JS_FreeValue(ctx, obj1);-                        if (ret < 0) {-                            JS_FreeValue(ctx, val);-                            return ret;-                        }-                        if (ret) {-                            if (desc.flags & JS_PROP_GETSET) {-                                JSObject *setter;-                                if (JS_IsUndefined(desc.setter))-                                    setter = NULL;-                                else-                                    setter = JS_VALUE_GET_OBJ(desc.setter);-                                ret = call_setter(ctx, setter, this_obj, val, flags);-                                JS_FreeValue(ctx, desc.getter);-                                JS_FreeValue(ctx, desc.setter);-                                return ret;-                            } else {-                                JS_FreeValue(ctx, desc.value);-                                if (!(desc.flags & JS_PROP_WRITABLE))-                                    goto read_only_prop;-                                if (likely(p == p1)) {-                                    ret = JS_DefineProperty(ctx, this_obj, prop, val,-                                                            JS_UNDEFINED, JS_UNDEFINED,-                                                            JS_PROP_HAS_VALUE);-                                    JS_FreeValue(ctx, val);-                                    return ret;-                                } else {-                                    break;-                                }-                            }-                        }-                    }-                }-            }-        }-        p1 = p1->shape->proto;-    prototype_lookup:-        if (!p1)-            break;--    retry2:-        prs = find_own_property(&pr, p1, prop);-        if (prs) {-            if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);-            } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                /* Instantiate property and retry (potentially useless) */-                if (JS_AutoInitProperty(ctx, p1, prop, pr))-                    return -1;-                goto retry2;-            } else if (!(prs->flags & JS_PROP_WRITABLE)) {-            read_only_prop:-                JS_FreeValue(ctx, val);-                return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);-            }-        }-    }--    if (unlikely(flags & JS_PROP_NO_ADD)) {-        JS_FreeValue(ctx, val);-        JS_ThrowReferenceErrorNotDefined(ctx, prop);-        return -1;-    }--    if (unlikely(!p)) {-        JS_FreeValue(ctx, val);-        return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object");-    }--    if (unlikely(!p->extensible)) {-        JS_FreeValue(ctx, val);-        return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");-    }--    if (p->is_exotic) {-        if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&-            __JS_AtomIsTaggedInt(prop)) {-            uint32_t idx = __JS_AtomToUInt32(prop);-            if (idx == p->u.array.count) {-                /* fast case */-                return add_fast_array_element(ctx, p, val, flags);-            } else {-                goto generic_create_prop;-            }-        } else {-        generic_create_prop:-            ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,-                                    flags |-                                    JS_PROP_HAS_VALUE |-                                    JS_PROP_HAS_ENUMERABLE |-                                    JS_PROP_HAS_WRITABLE |-                                    JS_PROP_HAS_CONFIGURABLE |-                                    JS_PROP_C_W_E);-            JS_FreeValue(ctx, val);-            return ret;-        }-    }--    pr = add_property(ctx, p, prop, JS_PROP_C_W_E);-    if (unlikely(!pr)) {-        JS_FreeValue(ctx, val);-        return -1;-    }-    pr->u.value = val;-    return TRUE;-}--/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */-static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,-                               JSValue prop, JSValue val, int flags)-{-    if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&-               JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {-        JSObject *p;-        uint32_t idx;-        double d;-        int32_t v;--        /* fast path for array access */-        p = JS_VALUE_GET_OBJ(this_obj);-        idx = JS_VALUE_GET_INT(prop);-        switch(p->class_id) {-        case JS_CLASS_ARRAY:-            if (unlikely(idx >= (uint32_t)p->u.array.count)) {-                JSObject *p1;-                JSShape *sh1;--                /* fast path to add an element to the array */-                if (idx != (uint32_t)p->u.array.count ||-                    !p->fast_array || !p->extensible)-                    goto slow_path;-                /* check if prototype chain has a numeric property */-                p1 = p->shape->proto;-                while (p1 != NULL) {-                    sh1 = p1->shape;-                    if (p1->class_id == JS_CLASS_ARRAY) {-                        if (unlikely(!p1->fast_array))-                            goto slow_path;-                    } else if (p1->class_id == JS_CLASS_OBJECT) {-                        if (unlikely(sh1->has_small_array_index))-                            goto slow_path;-                    } else {-                        goto slow_path;-                    }-                    p1 = sh1->proto;-                }-                /* add element */-                return add_fast_array_element(ctx, p, val, flags);-            }-            set_value(ctx, &p->u.array.u.values[idx], val);-            break;-        case JS_CLASS_ARGUMENTS:-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto slow_path;-            set_value(ctx, &p->u.array.u.values[idx], val);-            break;-        case JS_CLASS_UINT8C_ARRAY:-            if (JS_ToUint8ClampFree(ctx, &v, val))-                return -1;-            /* Note: the conversion can detach the typed array, so the-               array bound check must be done after */-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto ta_out_of_bound;-            p->u.array.u.uint8_ptr[idx] = v;-            break;-        case JS_CLASS_INT8_ARRAY:-        case JS_CLASS_UINT8_ARRAY:-            if (JS_ToInt32Free(ctx, &v, val))-                return -1;-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto ta_out_of_bound;-            p->u.array.u.uint8_ptr[idx] = v;-            break;-        case JS_CLASS_INT16_ARRAY:-        case JS_CLASS_UINT16_ARRAY:-            if (JS_ToInt32Free(ctx, &v, val))-                return -1;-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto ta_out_of_bound;-            p->u.array.u.uint16_ptr[idx] = v;-            break;-        case JS_CLASS_INT32_ARRAY:-        case JS_CLASS_UINT32_ARRAY:-            if (JS_ToInt32Free(ctx, &v, val))-                return -1;-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto ta_out_of_bound;-            p->u.array.u.uint32_ptr[idx] = v;-            break;-#ifdef CONFIG_BIGNUM-        case JS_CLASS_BIG_INT64_ARRAY:-        case JS_CLASS_BIG_UINT64_ARRAY:-            /* XXX: need specific conversion function */-            {-                int64_t v;-                if (JS_ToBigInt64Free(ctx, &v, val))-                    return -1;-                if (unlikely(idx >= (uint32_t)p->u.array.count))-                    goto ta_out_of_bound;-                p->u.array.u.uint64_ptr[idx] = v;-            }-            break;-#endif-        case JS_CLASS_FLOAT32_ARRAY:-            if (JS_ToFloat64Free(ctx, &d, val))-                return -1;-            if (unlikely(idx >= (uint32_t)p->u.array.count))-                goto ta_out_of_bound;-            p->u.array.u.float_ptr[idx] = d;-            break;-        case JS_CLASS_FLOAT64_ARRAY:-            if (JS_ToFloat64Free(ctx, &d, val))-                return -1;-            if (unlikely(idx >= (uint32_t)p->u.array.count)) {-            ta_out_of_bound:-                if (typed_array_is_detached(ctx, p)) {-                    JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-                    return -1;-                } else {-                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");-                }-            }-            p->u.array.u.double_ptr[idx] = d;-            break;-        default:-            goto slow_path;-        }-        return TRUE;-    } else {-        JSAtom atom;-        int ret;-    slow_path:-        atom = JS_ValueToAtom(ctx, prop);-        JS_FreeValue(ctx, prop);-        if (unlikely(atom == JS_ATOM_NULL)) {-            JS_FreeValue(ctx, val);-            return -1;-        }-        ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags);-        JS_FreeAtom(ctx, atom);-        return ret;-    }-}--int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,-                         uint32_t idx, JSValue val)-{-    return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val,-                               JS_PROP_THROW);-}--int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,-                        int64_t idx, JSValue val)-{-    JSAtom prop;-    int res;--    if ((uint64_t)idx <= INT32_MAX) {-        /* fast path for fast arrays */-        return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val,-                                   JS_PROP_THROW);-    }-    prop = JS_NewAtomInt64(ctx, idx);-    if (prop == JS_ATOM_NULL) {-        JS_FreeValue(ctx, val);-        return -1;-    }-    res = JS_SetProperty(ctx, this_obj, prop, val);-    JS_FreeAtom(ctx, prop);-    return res;-}--int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,-                      const char *prop, JSValue val)-{-    JSAtom atom;-    int ret;-    atom = JS_NewAtom(ctx, prop);-    ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW);-    JS_FreeAtom(ctx, atom);-    return ret;-}--/* compute the property flags. For each flag: (JS_PROP_HAS_x forces-   it, otherwise def_flags is used)-   Note: makes assumption about the bit pattern of the flags-*/-static int get_prop_flags(int flags, int def_flags)-{-    int mask;-    mask = (flags >> JS_PROP_HAS_SHIFT) & JS_PROP_C_W_E;-    return (flags & mask) | (def_flags & ~mask);-}--static int JS_CreateProperty(JSContext *ctx, JSObject *p,-                             JSAtom prop, JSValueConst val,-                             JSValueConst getter, JSValueConst setter,-                             int flags)-{-    JSProperty *pr;-    int ret, prop_flags;--    /* add a new property or modify an existing exotic one */-    if (p->is_exotic) {-        if (p->class_id == JS_CLASS_ARRAY) {-            uint32_t idx, len;--            if (p->fast_array) {-                if (__JS_AtomIsTaggedInt(prop)) {-                    idx = __JS_AtomToUInt32(prop);-                    if (idx == p->u.array.count) {-                        if (!p->extensible)-                            goto not_extensible;-                        if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET))-                            goto convert_to_array;-                        prop_flags = get_prop_flags(flags, 0);-                        if (prop_flags != JS_PROP_C_W_E)-                            goto convert_to_array;-                        return add_fast_array_element(ctx, p,-                                                      JS_DupValue(ctx, val), flags);-                    } else {-                        goto convert_to_array;-                    }-                } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) {-                    /* convert the fast array to normal array */-                convert_to_array:-                    if (convert_fast_array_to_array(ctx, p))-                        return -1;-                    goto generic_array;-                }-            } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) {-                JSProperty *plen;-                JSShapeProperty *pslen;-            generic_array:-                /* update the length field */-                plen = &p->prop[0];-                JS_ToUint32(ctx, &len, plen->u.value);-                if ((idx + 1) > len) {-                    pslen = get_shape_prop(p->shape);-                    if (unlikely(!(pslen->flags & JS_PROP_WRITABLE)))-                        return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);-                    /* XXX: should update the length after defining-                       the property */-                    len = idx + 1;-                    set_value(ctx, &plen->u.value, JS_NewUint32(ctx, len));-                }-            }-        } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                   p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-            ret = JS_AtomIsNumericIndex(ctx, prop);-            if (ret != 0) {-                if (ret < 0)-                    return -1;-                return JS_ThrowTypeErrorOrFalse(ctx, flags, "cannot create numeric index in typed array");-            }-        } else if (!(flags & JS_PROP_NO_EXOTIC)) {-            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;-            if (em) {-                if (em->define_own_property) {-                    return em->define_own_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p),-                                                   prop, val, getter, setter, flags);-                }-                ret = JS_IsExtensible(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-                if (ret < 0)-                    return -1;-                if (!ret)-                    goto not_extensible;-            }-        }-    }--    if (!p->extensible) {-    not_extensible:-        return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");-    }--    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-        prop_flags = (flags & (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) |-            JS_PROP_GETSET;-    } else {-        prop_flags = flags & JS_PROP_C_W_E;-    }-    pr = add_property(ctx, p, prop, prop_flags);-    if (unlikely(!pr))-        return -1;-    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-        pr->u.getset.getter = NULL;-        if ((flags & JS_PROP_HAS_GET) && JS_IsFunction(ctx, getter)) {-            pr->u.getset.getter =-                JS_VALUE_GET_OBJ(JS_DupValue(ctx, getter));-        }-        pr->u.getset.setter = NULL;-        if ((flags & JS_PROP_HAS_SET) && JS_IsFunction(ctx, setter)) {-            pr->u.getset.setter =-                JS_VALUE_GET_OBJ(JS_DupValue(ctx, setter));-        }-    } else {-        if (flags & JS_PROP_HAS_VALUE) {-            pr->u.value = JS_DupValue(ctx, val);-        } else {-            pr->u.value = JS_UNDEFINED;-        }-    }-    return TRUE;-}--/* return FALSE if not OK */-static BOOL check_define_prop_flags(int prop_flags, int flags)-{-    BOOL has_accessor, is_getset;--    if (!(prop_flags & JS_PROP_CONFIGURABLE)) {-        if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) ==-            (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) {-            return FALSE;-        }-        if ((flags & JS_PROP_HAS_ENUMERABLE) &&-            (flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE))-            return FALSE;-    }-    if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |-                 JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-        if (!(prop_flags & JS_PROP_CONFIGURABLE)) {-            has_accessor = ((flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) != 0);-            is_getset = ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET);-            if (has_accessor != is_getset)-                return FALSE;-            if (!has_accessor && !is_getset && !(prop_flags & JS_PROP_WRITABLE)) {-                /* not writable: cannot set the writable bit */-                if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==-                    (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE))-                    return FALSE;-            }-        }-    }-    return TRUE;-}--/* ensure that the shape can be safely modified */-static int js_shape_prepare_update(JSContext *ctx, JSObject *p,-                                   JSShapeProperty **pprs)-{-    JSShape *sh;-    uint32_t idx = 0;    /* prevent warning */--    sh = p->shape;-    if (sh->is_hashed) {-        if (sh->header.ref_count != 1) {-            if (pprs)-                idx = *pprs - get_shape_prop(sh);-            /* clone the shape (the resulting one is no longer hashed) */-            sh = js_clone_shape(ctx, sh);-            if (!sh)-                return -1;-            js_free_shape(ctx->rt, p->shape);-            p->shape = sh;-            if (pprs)-                *pprs = get_shape_prop(sh) + idx;-        } else {-            js_shape_hash_unlink(ctx->rt, sh);-            sh->is_hashed = FALSE;-        }-    }-    return 0;-}--static int js_update_property_flags(JSContext *ctx, JSObject *p,-                                    JSShapeProperty **pprs, int flags)-{-    if (flags != (*pprs)->flags) {-        if (js_shape_prepare_update(ctx, p, pprs))-            return -1;-        (*pprs)->flags = flags;-    }-    return 0;-}--/* allowed flags:-   JS_PROP_CONFIGURABLE, JS_PROP_WRITABLE, JS_PROP_ENUMERABLE-   JS_PROP_HAS_GET, JS_PROP_HAS_SET, JS_PROP_HAS_VALUE,-   JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE,-   JS_PROP_THROW, JS_PROP_NO_EXOTIC.-   If JS_PROP_THROW is set, return an exception instead of FALSE.-   if JS_PROP_NO_EXOTIC is set, do not call the exotic-   define_own_property callback.-   return -1 (exception), FALSE or TRUE.-*/-int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,-                      JSAtom prop, JSValueConst val,-                      JSValueConst getter, JSValueConst setter, int flags)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    int mask, res;--    if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    p = JS_VALUE_GET_OBJ(this_obj);-- redo_prop_update:-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        /* property already exists */-        if (!check_define_prop_flags(prs->flags, flags)) {-        not_configurable:-            return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");-        }--    retry:-        if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |-                     JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-            if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-                JSObject *new_getter, *new_setter;--                if (JS_IsFunction(ctx, getter)) {-                    new_getter = JS_VALUE_GET_OBJ(getter);-                } else {-                    new_getter = NULL;-                }-                if (JS_IsFunction(ctx, setter)) {-                    new_setter = JS_VALUE_GET_OBJ(setter);-                } else {-                    new_setter = NULL;-                }--                if ((prs->flags & JS_PROP_TMASK) != JS_PROP_GETSET) {-                    if (js_shape_prepare_update(ctx, p, &prs))-                        return -1;-                    /* convert to getset */-                    if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                        free_var_ref(ctx->rt, pr->u.var_ref);-                    } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                        /* clear property and update */-                        if (js_shape_prepare_update(ctx, p, &prs))-                            return -1;-                        js_autoinit_free(ctx->rt, pr);-                        prs->flags &= ~JS_PROP_TMASK;-                        pr->u.value = JS_UNDEFINED;-                        goto retry;-                    } else {-                        JS_FreeValue(ctx, pr->u.value);-                    }-                    prs->flags = (prs->flags &-                                  (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) |-                        JS_PROP_GETSET;-                    pr->u.getset.getter = NULL;-                    pr->u.getset.setter = NULL;-                } else {-                    if (!(prs->flags & JS_PROP_CONFIGURABLE)) {-                        if ((flags & JS_PROP_HAS_GET) &&-                            new_getter != pr->u.getset.getter) {-                            goto not_configurable;-                        }-                        if ((flags & JS_PROP_HAS_SET) &&-                            new_setter != pr->u.getset.setter) {-                            goto not_configurable;-                        }-                    }-                }-                if (flags & JS_PROP_HAS_GET) {-                    if (pr->u.getset.getter)-                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));-                    if (new_getter)-                        JS_DupValue(ctx, getter);-                    pr->u.getset.getter = new_getter;-                }-                if (flags & JS_PROP_HAS_SET) {-                    if (pr->u.getset.setter)-                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));-                    if (new_setter)-                        JS_DupValue(ctx, setter);-                    pr->u.getset.setter = new_setter;-                }-            } else {-                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                    /* convert to data descriptor */-                    if (js_shape_prepare_update(ctx, p, &prs))-                        return -1;-                    if (pr->u.getset.getter)-                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));-                    if (pr->u.getset.setter)-                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));-                    prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);-                    pr->u.value = JS_UNDEFINED;-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                    /* Note: JS_PROP_VARREF is always writable */-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                    /* clear property and update */-                    if (js_shape_prepare_update(ctx, p, &prs))-                        return -1;-                    js_autoinit_free(ctx->rt, pr);-                    prs->flags &= ~JS_PROP_TMASK;-                    pr->u.value = JS_UNDEFINED;-                } else {-                    if ((prs->flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 &&-                        (flags & JS_PROP_HAS_VALUE) &&-                        !js_same_value(ctx, val, pr->u.value)) {-                        goto not_configurable;-                    }-                }-                if (prs->flags & JS_PROP_LENGTH) {-                    if (flags & JS_PROP_HAS_VALUE) {-                        res = set_array_length(ctx, p, JS_DupValue(ctx, val),-                                               flags);-                    } else {-                        res = TRUE;-                    }-                    /* still need to reset the writable flag if needed.-                       The JS_PROP_LENGTH is reset to have the correct-                       read-only behavior in JS_SetProperty(). */-                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==-                        JS_PROP_HAS_WRITABLE) {-                        prs = get_shape_prop(p->shape);-                        if (js_update_property_flags(ctx, p, &prs,-                                                     prs->flags & ~(JS_PROP_WRITABLE | JS_PROP_LENGTH)))-                            return -1;-                    }-                    return res;-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                    if (flags & JS_PROP_HAS_VALUE) {-                        if (p->class_id == JS_CLASS_MODULE_NS) {-                            /* JS_PROP_WRITABLE is always true for variable-                               references, but they are write protected in module name-                               spaces. */-                            if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue))-                                goto not_configurable;-                        }-                        /* update the reference */-                        set_value(ctx, pr->u.var_ref->pvalue,-                                  JS_DupValue(ctx, val));-                    }-                    /* if writable is set to false, no longer a-                       reference (for mapped arguments) */-                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) {-                        JSValue val1;-                        if (js_shape_prepare_update(ctx, p, &prs))-                            return -1;-                        val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue);-                        free_var_ref(ctx->rt, pr->u.var_ref);-                        pr->u.value = val1;-                        prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);-                    }-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                    /* XXX: should never happen, type was reset above */-                    abort();-                } else {-                    if (flags & JS_PROP_HAS_VALUE) {-                        JS_FreeValue(ctx, pr->u.value);-                        pr->u.value = JS_DupValue(ctx, val);-                    }-                    if (flags & JS_PROP_HAS_WRITABLE) {-                        if (js_update_property_flags(ctx, p, &prs,-                                                     (prs->flags & ~JS_PROP_WRITABLE) |-                                                     (flags & JS_PROP_WRITABLE)))-                            return -1;-                    }-                }-            }-        }-        mask = 0;-        if (flags & JS_PROP_HAS_CONFIGURABLE)-            mask |= JS_PROP_CONFIGURABLE;-        if (flags & JS_PROP_HAS_ENUMERABLE)-            mask |= JS_PROP_ENUMERABLE;-        if (js_update_property_flags(ctx, p, &prs,-                                     (prs->flags & ~mask) | (flags & mask)))-            return -1;-        return TRUE;-    }--    /* handle modification of fast array elements */-    if (p->fast_array) {-        uint32_t idx;-        uint32_t prop_flags;-        if (p->class_id == JS_CLASS_ARRAY) {-            if (__JS_AtomIsTaggedInt(prop)) {-                idx = __JS_AtomToUInt32(prop);-                if (idx < p->u.array.count) {-                    prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);-                    if (prop_flags != JS_PROP_C_W_E)-                        goto convert_to_slow_array;-                    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-                    convert_to_slow_array:-                        if (convert_fast_array_to_array(ctx, p))-                            return -1;-                        else-                            goto redo_prop_update;-                    }-                    if (flags & JS_PROP_HAS_VALUE) {-                        set_value(ctx, &p->u.array.u.values[idx], JS_DupValue(ctx, val));-                    }-                    return TRUE;-                }-            }-        } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                   p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-            JSValue num;-            int ret;--            if (!__JS_AtomIsTaggedInt(prop)) {-                /* slow path with to handle all numeric indexes */-                num = JS_AtomIsNumericIndex1(ctx, prop);-                if (JS_IsUndefined(num))-                    goto typed_array_done;-                if (JS_IsException(num))-                    return -1;-                ret = JS_NumberIsInteger(ctx, num);-                if (ret < 0) {-                    JS_FreeValue(ctx, num);-                    return -1;-                }-                if (!ret) {-                    JS_FreeValue(ctx, num);-                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "non integer index in typed array");-                }-                ret = JS_NumberIsNegativeOrMinusZero(ctx, num);-                JS_FreeValue(ctx, num);-                if (ret) {-                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");-                }-                if (!__JS_AtomIsTaggedInt(prop))-                    goto typed_array_oob;-            }-            idx = __JS_AtomToUInt32(prop);-            /* if the typed array is detached, p->u.array.count = 0 */-            if (idx >= typed_array_get_length(ctx, p)) {-            typed_array_oob:-                return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");-            }-            prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE);-            if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET) ||-                prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE)) {-                return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags");-            }-            if (flags & JS_PROP_HAS_VALUE) {-                return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags);-            }-            return TRUE;-        typed_array_done: ;-        }-    }--    return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags);-}--static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,-                                     JSAtom prop, JSAutoInitIDEnum id,-                                     void *opaque, int flags)-{-    JSObject *p;-    JSProperty *pr;--    if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT)-        return FALSE;--    p = JS_VALUE_GET_OBJ(this_obj);--    if (find_own_property(&pr, p, prop)) {-        /* property already exists */-        abort();-        return FALSE;-    }--    /* Specialized CreateProperty */-    pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);-    if (unlikely(!pr))-        return -1;-    pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx);-    assert((pr->u.init.realm_and_id & 3) == 0);-    assert(id <= 3);-    pr->u.init.realm_and_id |= id;-    pr->u.init.opaque = opaque;-    return TRUE;-}--/* shortcut to add or redefine a new property value */-int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,-                           JSAtom prop, JSValue val, int flags)-{-    int ret;-    ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED,-                            flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE);-    JS_FreeValue(ctx, val);-    return ret;-}--int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj,-                                JSValue prop, JSValue val, int flags)-{-    JSAtom atom;-    int ret;-    atom = JS_ValueToAtom(ctx, prop);-    JS_FreeValue(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL)) {-        JS_FreeValue(ctx, val);-        return -1;-    }-    ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);-    JS_FreeAtom(ctx, atom);-    return ret;-}--int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,-                                 uint32_t idx, JSValue val, int flags)-{-    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx),-                                       val, flags);-}--int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj,-                                int64_t idx, JSValue val, int flags)-{-    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),-                                       val, flags);-}--int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,-                              const char *prop, JSValue val, int flags)-{-    JSAtom atom;-    int ret;-    atom = JS_NewAtom(ctx, prop);-    ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);-    JS_FreeAtom(ctx, atom);-    return ret;-}--/* shortcut to add getter & setter */-int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,-                            JSAtom prop, JSValue getter, JSValue setter,-                            int flags)-{-    int ret;-    ret = JS_DefineProperty(ctx, this_obj, prop, JS_UNDEFINED, getter, setter,-                            flags | JS_PROP_HAS_GET | JS_PROP_HAS_SET |-                            JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE);-    JS_FreeValue(ctx, getter);-    JS_FreeValue(ctx, setter);-    return ret;-}--static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj,-                                       int64_t idx, JSValue val, int flags)-{-    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),-                                       val, flags | JS_PROP_CONFIGURABLE |-                                       JS_PROP_ENUMERABLE | JS_PROP_WRITABLE);-}---/* return TRUE if 'obj' has a non empty 'name' string */-static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj)-{-    JSProperty *pr;-    JSShapeProperty *prs;-    JSValueConst val;-    JSString *p;-    -    prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name);-    if (!prs)-        return FALSE;-    if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)-        return TRUE;-    val = pr->u.value;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)-        return TRUE;-    p = JS_VALUE_GET_STRING(val);-    return (p->len != 0);-}--static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj,-                               JSAtom name, int flags)-{-    if (name != JS_ATOM_NULL-    &&  JS_IsObject(obj)-    &&  !js_object_has_name(ctx, obj)-    &&  JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name), flags) < 0) {-        return -1;-    }-    return 0;-}--static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj,-                                       JSValueConst str, int flags)-{-    if (JS_IsObject(obj) &&-        !js_object_has_name(ctx, obj)) {-        JSAtom prop;-        JSValue name_str;-        prop = JS_ValueToAtom(ctx, str);-        if (prop == JS_ATOM_NULL)-            return -1;-        name_str = js_get_function_name(ctx, prop);-        JS_FreeAtom(ctx, prop);-        if (JS_IsException(name_str))-            return -1;-        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, name_str, flags) < 0)-            return -1;-    }-    return 0;-}--#define DEFINE_GLOBAL_LEX_VAR (1 << 7)-#define DEFINE_GLOBAL_FUNC_VAR (1 << 6)--static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop)-{-    return JS_ThrowSyntaxErrorAtom(ctx, "redeclaration of '%s'", prop);-}--/* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */-/* XXX: could support exotic global object. */-static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags)-{-    JSObject *p;-    JSShapeProperty *prs;--    p = JS_VALUE_GET_OBJ(ctx->global_obj);-    prs = find_own_property1(p, prop);-    /* XXX: should handle JS_PROP_AUTOINIT */-    if (flags & DEFINE_GLOBAL_LEX_VAR) {-        if (prs && !(prs->flags & JS_PROP_CONFIGURABLE))-            goto fail_redeclaration;-    } else {-        if (!prs && !p->extensible)-            goto define_error;-        if (flags & DEFINE_GLOBAL_FUNC_VAR) {-            if (prs) {-                if (!(prs->flags & JS_PROP_CONFIGURABLE) &&-                    ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET ||-                     ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) !=-                      (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) {-                define_error:-                    JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'",-                                          prop);-                    return -1;-                }-            }-        }-    }-    /* check if there already is a lexical declaration */-    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-    prs = find_own_property1(p, prop);-    if (prs) {-    fail_redeclaration:-        JS_ThrowSyntaxErrorVarRedeclaration(ctx, prop);-        return -1;-    }-    return 0;-}--/* def_flags is (0, DEFINE_GLOBAL_LEX_VAR) |-   JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE */-/* XXX: could support exotic global object. */-static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    JSValue val;-    int flags;--    if (def_flags & DEFINE_GLOBAL_LEX_VAR) {-        p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-        flags = JS_PROP_ENUMERABLE | (def_flags & JS_PROP_WRITABLE) |-            JS_PROP_CONFIGURABLE;-        val = JS_UNINITIALIZED;-    } else {-        p = JS_VALUE_GET_OBJ(ctx->global_obj);-        flags = JS_PROP_ENUMERABLE | JS_PROP_WRITABLE |-            (def_flags & JS_PROP_CONFIGURABLE);-        val = JS_UNDEFINED;-    }-    prs = find_own_property1(p, prop);-    if (prs)-        return 0;-    if (!p->extensible)-        return 0;-    pr = add_property(ctx, p, prop, flags);-    if (unlikely(!pr))-        return -1;-    pr->u.value = val;-    return 0;-}--/* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */-/* XXX: could support exotic global object. */-static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop,-                                   JSValueConst func, int def_flags)-{--    JSObject *p;-    JSShapeProperty *prs;-    int flags;--    p = JS_VALUE_GET_OBJ(ctx->global_obj);-    prs = find_own_property1(p, prop);-    flags = JS_PROP_HAS_VALUE | JS_PROP_THROW;-    if (!prs || (prs->flags & JS_PROP_CONFIGURABLE)) {-        flags |= JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | def_flags |-            JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE;-    }-    if (JS_DefineProperty(ctx, ctx->global_obj, prop, func,-                          JS_UNDEFINED, JS_UNDEFINED, flags) < 0)-        return -1;-    return 0;-}--static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,-                               BOOL throw_ref_error)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;--    /* no exotic behavior is possible in global_var_obj */-    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        /* XXX: should handle JS_PROP_TMASK properties */-        if (unlikely(JS_IsUninitialized(pr->u.value)))-            return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-        return JS_DupValue(ctx, pr->u.value);-    }-    return JS_GetPropertyInternal(ctx, ctx->global_obj, prop,-                                 ctx->global_obj, throw_ref_error);-}--/* construct a reference to a global variable */-static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;--    /* no exotic behavior is possible in global_var_obj */-    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        /* XXX: should handle JS_PROP_AUTOINIT properties? */-        /* XXX: conformance: do these tests in-           OP_put_var_ref/OP_get_var_ref ? */-        if (unlikely(JS_IsUninitialized(pr->u.value))) {-            JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-            return -1;-        }-        if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) {-            return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop);-        }-        sp[0] = JS_DupValue(ctx, ctx->global_var_obj);-    } else {-        int ret;-        ret = JS_HasProperty(ctx, ctx->global_obj, prop);-        if (ret < 0)-            return -1;-        if (ret) {-            sp[0] = JS_DupValue(ctx, ctx->global_obj);-        } else {-            sp[0] = JS_UNDEFINED;-        }-    }-    sp[1] = JS_AtomToValue(ctx, prop);-    return 0;-}--/* use for strict variable access: test if the variable exists */-static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop)-{-    JSObject *p;-    JSShapeProperty *prs;-    int ret;--    /* no exotic behavior is possible in global_var_obj */-    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-    prs = find_own_property1(p, prop);-    if (prs) {-        ret = TRUE;-    } else {-        ret = JS_HasProperty(ctx, ctx->global_obj, prop);-        if (ret < 0)-            return -1;-    }-    return ret;-}--/* flag = 0: normal variable write-   flag = 1: initialize lexical variable-   flag = 2: normal variable write, strict check was done before-*/-static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,-                           int flag)-{-    JSObject *p;-    JSShapeProperty *prs;-    JSProperty *pr;-    int flags;--    /* no exotic behavior is possible in global_var_obj */-    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);-    prs = find_own_property(&pr, p, prop);-    if (prs) {-        /* XXX: should handle JS_PROP_AUTOINIT properties? */-        if (flag != 1) {-            if (unlikely(JS_IsUninitialized(pr->u.value))) {-                JS_FreeValue(ctx, val);-                JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);-                return -1;-            }-            if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) {-                JS_FreeValue(ctx, val);-                return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop);-            }-        }-        set_value(ctx, &pr->u.value, val);-        return 0;-    }--    flags = JS_PROP_THROW_STRICT;-    if (flag != 2 && is_strict_mode(ctx))-        flags |= JS_PROP_NO_ADD;-    return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);-}--/* return -1, FALSE or TRUE. return FALSE if not configurable or-   invalid object. return -1 in case of exception.-   flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */-int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)-{-    JSValue obj1;-    JSObject *p;-    int res;-    -    obj1 = JS_ToObject(ctx, obj);-    if (JS_IsException(obj1))-        return -1;-    p = JS_VALUE_GET_OBJ(obj1);-    res = delete_property(ctx, p, prop);-    JS_FreeValue(ctx, obj1);-    if (res != FALSE)-        return res;-    if ((flags & JS_PROP_THROW) ||-        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {-        JS_ThrowTypeError(ctx, "could not delete property");-        return -1;-    }-    return FALSE;-}--int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags)-{-    JSAtom prop;-    int res;--    if ((uint64_t)idx <= JS_ATOM_MAX_INT) {-        /* fast path for fast arrays */-        return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);-    }-    prop = JS_NewAtomInt64(ctx, idx);-    if (prop == JS_ATOM_NULL)-        return -1;-    res = JS_DeleteProperty(ctx, obj, prop, flags);-    JS_FreeAtom(ctx, prop);-    return res;-}--BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(val);-    switch(p->class_id) {-    case JS_CLASS_BYTECODE_FUNCTION:-        return TRUE;-    case JS_CLASS_PROXY:-        return p->u.proxy_data->is_func;-    default:-        return (ctx->rt->class_array[p->class_id].call != NULL);-    }-}--BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(val);-    if (p->class_id == JS_CLASS_C_FUNCTION)-        return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic);-    else-        return FALSE;-}--BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(val);-    return p->is_constructor;-}--BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(func_obj);-    p->is_constructor = val;-    return TRUE;-}--BOOL JS_IsError(JSContext *ctx, JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(val);-    return (p->class_id == JS_CLASS_ERROR);-}--/* used to avoid catching interrupt exceptions */-BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(val);-    return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error;-}--void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return;-    p = JS_VALUE_GET_OBJ(val);-    if (p->class_id == JS_CLASS_ERROR)-        p->is_uncatchable_error = flag;-}--void JS_ResetUncatchableError(JSContext *ctx)-{-    JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE);-}--void JS_SetOpaque(JSValue obj, void *opaque)-{-   JSObject *p;-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(obj);-        p->u.opaque = opaque;-    }-}--/* return NULL if not an object of class class_id */-void *JS_GetOpaque(JSValueConst obj, JSClassID class_id)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return NULL;-    p = JS_VALUE_GET_OBJ(obj);-    if (p->class_id != class_id)-        return NULL;-    return p->u.opaque;-}--void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)-{-    void *p = JS_GetOpaque(obj, class_id);-    if (unlikely(!p)) {-        JS_ThrowTypeErrorInvalidClass(ctx, class_id);-    }-    return p;-}--#define HINT_STRING  0-#define HINT_NUMBER  1-#define HINT_NONE    2-/* don't try Symbol.toPrimitive */-#define HINT_FORCE_ORDINARY (1 << 4)--static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)-{-    int i;-    BOOL force_ordinary;--    JSAtom method_name;-    JSValue method, ret;-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)-        return val;-    force_ordinary = hint & HINT_FORCE_ORDINARY;-    hint &= ~HINT_FORCE_ORDINARY;-    if (!force_ordinary) {-        method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_toPrimitive);-        if (JS_IsException(method))-            goto exception;-        /* ECMA says *If exoticToPrim is not undefined* but tests in-           test262 use null as a non callable converter */-        if (!JS_IsUndefined(method) && !JS_IsNull(method)) {-            JSAtom atom;-            JSValue arg;-            switch(hint) {-            case HINT_STRING:-                atom = JS_ATOM_string;-                break;-            case HINT_NUMBER:-                atom = JS_ATOM_number;-                break;-            default:-            case HINT_NONE:-                atom = JS_ATOM_default;-                break;-            }-            arg = JS_AtomToString(ctx, atom);-            ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);-            JS_FreeValue(ctx, arg);-            if (JS_IsException(ret))-                goto exception;-            JS_FreeValue(ctx, val);-            if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT)-                return ret;-            JS_FreeValue(ctx, ret);-            return JS_ThrowTypeError(ctx, "toPrimitive");-        }-    }-    if (hint != HINT_STRING)-        hint = HINT_NUMBER;-    for(i = 0; i < 2; i++) {-        if ((i ^ hint) == 0) {-            method_name = JS_ATOM_toString;-        } else {-            method_name = JS_ATOM_valueOf;-        }-        method = JS_GetProperty(ctx, val, method_name);-        if (JS_IsException(method))-            goto exception;-        if (JS_IsFunction(ctx, method)) {-            ret = JS_CallFree(ctx, method, val, 0, NULL);-            if (JS_IsException(ret))-                goto exception;-            if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {-                JS_FreeValue(ctx, val);-                return ret;-            }-            JS_FreeValue(ctx, ret);-        } else {-            JS_FreeValue(ctx, method);-        }-    }-    JS_ThrowTypeError(ctx, "toPrimitive");-exception:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint)-{-    return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);-}--void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return;-    p = JS_VALUE_GET_OBJ(obj);-    p->is_HTMLDDA = TRUE;-}--static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return FALSE;-    p = JS_VALUE_GET_OBJ(obj);-    return p->is_HTMLDDA;-}-                         -static int JS_ToBoolFree(JSContext *ctx, JSValue val)-{-    uint32_t tag = JS_VALUE_GET_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-        return JS_VALUE_GET_INT(val) != 0;-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        return JS_VALUE_GET_INT(val);-    case JS_TAG_EXCEPTION:-        return -1;-    case JS_TAG_STRING:-        {-            BOOL ret = JS_VALUE_GET_STRING(val)->len != 0;-            JS_FreeValue(ctx, val);-            return ret;-        }-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            BOOL ret;-            ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;-            JS_FreeValue(ctx, val);-            return ret;-        }-    case JS_TAG_BIG_DECIMAL:-        {-            JSBigDecimal *p = JS_VALUE_GET_PTR(val);-            BOOL ret;-            ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;-            JS_FreeValue(ctx, val);-            return ret;-        }-#endif-    case JS_TAG_OBJECT:-        {-            JSObject *p = JS_VALUE_GET_OBJ(val);-            BOOL ret;-            ret = !p->is_HTMLDDA;-            JS_FreeValue(ctx, val);-            return ret;-        }-        break;-    default:-        if (JS_TAG_IS_FLOAT64(tag)) {-            double d = JS_VALUE_GET_FLOAT64(val);-            return !isnan(d) && d != 0;-        } else {-            JS_FreeValue(ctx, val);-            return TRUE;-        }-    }-}--int JS_ToBool(JSContext *ctx, JSValueConst val)-{-    return JS_ToBoolFree(ctx, JS_DupValue(ctx, val));-}--static int skip_spaces(const char *pc)-{-    const uint8_t *p, *p_next, *p_start;-    uint32_t c;--    p = p_start = (const uint8_t *)pc;-    for (;;) {-        c = *p;-        if (c < 128) {-            if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20)))-                break;-            p++;-        } else {-            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);-            if (!lre_is_space(c))-                break;-            p = p_next;-        }-    }-    return p - p_start;-}--static inline int to_digit(int c)-{-    if (c >= '0' && c <= '9')-        return c - '0';-    else if (c >= 'A' && c <= 'Z')-        return c - 'A' + 10;-    else if (c >= 'a' && c <= 'z')-        return c - 'a' + 10;-    else-        return 36;-}--/* XXX: remove */-static double js_strtod(const char *p, int radix, BOOL is_float)-{-    double d;-    int c;-    -    if (!is_float || radix != 10) {-        uint64_t n_max, n;-        int int_exp, is_neg;-        -        is_neg = 0;-        if (*p == '-') {-            is_neg = 1;-            p++;-        }--        /* skip leading zeros */-        while (*p == '0')-            p++;-        n = 0;-        if (radix == 10)-            n_max = ((uint64_t)-1 - 9) / 10; /* most common case */-        else-            n_max = ((uint64_t)-1 - (radix - 1)) / radix;-        /* XXX: could be more precise */-        int_exp = 0;-        while (*p != '\0') {-            c = to_digit((uint8_t)*p);-            if (c >= radix)-                break;-            if (n <= n_max) {-                n = n * radix + c;-            } else {-                int_exp++;-            }-            p++;-        }-        d = n;-        if (int_exp != 0) {-            d *= pow(radix, int_exp);-        }-        if (is_neg)-            d = -d;-    } else {-        d = strtod(p, NULL);-    }-    return d;-}--#define ATOD_INT_ONLY        (1 << 0)-/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */-#define ATOD_ACCEPT_BIN_OCT  (1 << 2)-/* accept O prefix as octal if radix == 0 and properly formed (Annex B) */-#define ATOD_ACCEPT_LEGACY_OCTAL  (1 << 4)-/* accept _ between digits as a digit separator */-#define ATOD_ACCEPT_UNDERSCORES  (1 << 5)-/* allow a suffix to override the type */-#define ATOD_ACCEPT_SUFFIX    (1 << 6) -/* default type */-#define ATOD_TYPE_MASK        (3 << 7)-#define ATOD_TYPE_FLOAT64     (0 << 7)-#define ATOD_TYPE_BIG_INT     (1 << 7)-#define ATOD_TYPE_BIG_FLOAT   (2 << 7)-#define ATOD_TYPE_BIG_DECIMAL (3 << 7)-/* assume bigint mode: floats are parsed as integers if no decimal-   point nor exponent */-#define ATOD_MODE_BIGINT      (1 << 9) -/* accept -0x1 */-#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)--#ifdef CONFIG_BIGNUM-static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,-                                   int radix, int flags, slimb_t *pexponent)-{-    bf_t a_s, *a = &a_s;-    int ret;-    JSValue val;-    val = JS_NewBigInt(ctx);-    if (JS_IsException(val))-        return val;-    a = JS_GetBigInt(val);-    ret = bf_atof(a, buf, NULL, radix, BF_PREC_INF, BF_RNDZ);-    if (ret & BF_ST_MEM_ERROR) {-        JS_FreeValue(ctx, val);-        return JS_ThrowOutOfMemory(ctx);-    }-    val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);-    return val;-}--static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf,-                                     int radix, int flags, slimb_t *pexponent)-{-    bf_t *a;-    int ret;-    JSValue val;-    -    val = JS_NewBigFloat(ctx);-    if (JS_IsException(val))-        return val;-    a = JS_GetBigFloat(val);-    if (flags & ATOD_ACCEPT_SUFFIX) {-        /* return the exponent to get infinite precision */-        ret = bf_atof2(a, pexponent, buf, NULL, radix, BF_PREC_INF,-                       BF_RNDZ | BF_ATOF_EXPONENT);-    } else {-        ret = bf_atof(a, buf, NULL, radix, ctx->fp_env.prec,-                      ctx->fp_env.flags);-    }-    if (ret & BF_ST_MEM_ERROR) {-        JS_FreeValue(ctx, val);-        return JS_ThrowOutOfMemory(ctx);-    }-    return val;-}--static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf,-                                       int radix, int flags, slimb_t *pexponent)-{-    bfdec_t *a;-    int ret;-    JSValue val;-    -    val = JS_NewBigDecimal(ctx);-    if (JS_IsException(val))-        return val;-    a = JS_GetBigDecimal(val);-    ret = bfdec_atof(a, buf, NULL, BF_PREC_INF,-                     BF_RNDZ | BF_ATOF_NO_NAN_INF);-    if (ret & BF_ST_MEM_ERROR) {-        JS_FreeValue(ctx, val);-        return JS_ThrowOutOfMemory(ctx);-    }-    return val;-}--#endif--/* return an exception in case of memory error. Return JS_NAN if-   invalid syntax */-#ifdef CONFIG_BIGNUM-static JSValue js_atof2(JSContext *ctx, const char *str, const char **pp,-                        int radix, int flags, slimb_t *pexponent)-#else-static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,-                       int radix, int flags)-#endif-{-    const char *p, *p_start;-    int sep, is_neg;-    BOOL is_float, has_legacy_octal;-    int atod_type = flags & ATOD_TYPE_MASK;-    char buf1[64], *buf;-    int i, j, len;-    BOOL buf_allocated = FALSE;-    JSValue val;-    -    /* optional separator between digits */-    sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;-    has_legacy_octal = FALSE;-    -    p = str;-    p_start = p;-    is_neg = 0;-    if (p[0] == '+') {-        p++;-        p_start++;-        if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))-            goto no_radix_prefix;-    } else if (p[0] == '-') {-        p++;-        p_start++;-        is_neg = 1;-        if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))-            goto no_radix_prefix;-    }-    if (p[0] == '0') {-        if ((p[1] == 'x' || p[1] == 'X') &&-            (radix == 0 || radix == 16)) {-            p += 2;-            radix = 16;-        } else if ((p[1] == 'o' || p[1] == 'O') &&-                   radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {-            p += 2;-            radix = 8;-        } else if ((p[1] == 'b' || p[1] == 'B') &&-                   radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {-            p += 2;-            radix = 2;-        } else if ((p[1] >= '0' && p[1] <= '9') &&-                   radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) {-            int i;-            has_legacy_octal = TRUE;-            sep = 256;-            for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++)-                continue;-            if (p[i] == '8' || p[i] == '9')-                goto no_prefix;-            p += 1;-            radix = 8;-        } else {-            goto no_prefix;-        }-        /* there must be a digit after the prefix */-        if (to_digit((uint8_t)*p) >= radix)-            goto fail;-    no_prefix: ;-    } else {- no_radix_prefix:-        if (!(flags & ATOD_INT_ONLY) &&-            (atod_type == ATOD_TYPE_FLOAT64 ||-             atod_type == ATOD_TYPE_BIG_FLOAT) &&-            strstart(p, "Infinity", &p)) {-#ifdef CONFIG_BIGNUM-            if (atod_type == ATOD_TYPE_BIG_FLOAT) {-                bf_t *a;-                val = JS_NewBigFloat(ctx);-                if (JS_IsException(val))-                    goto done;-                a = JS_GetBigFloat(val);-                bf_set_inf(a, is_neg);-            } else-#endif-            {-                double d = 1.0 / 0.0;-                if (is_neg)-                    d = -d;-                val = JS_NewFloat64(ctx, d);-            }-            goto done;-        }-    }-    if (radix == 0)-        radix = 10;-    is_float = FALSE;-    p_start = p;-    while (to_digit((uint8_t)*p) < radix-           ||  (*p == sep && (radix != 10 ||-                              p != p_start + 1 || p[-1] != '0') &&-                to_digit((uint8_t)p[1]) < radix)) {-        p++;-    }-    if (!(flags & ATOD_INT_ONLY)) {-        if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) {-            is_float = TRUE;-            p++;-            if (*p == sep)-                goto fail;-            while (to_digit((uint8_t)*p) < radix ||-                   (*p == sep && to_digit((uint8_t)p[1]) < radix))-                p++;-        }-        if (p > p_start &&-            (((*p == 'e' || *p == 'E') && radix == 10) ||-             ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {-            const char *p1 = p + 1;-            is_float = TRUE;-            if (*p1 == '+') {-                p1++;-            } else if (*p1 == '-') {-                p1++;-            }-            if (is_digit((uint8_t)*p1)) {-                p = p1 + 1;-                while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))-                    p++;-            }-        }-    }-    if (p == p_start)-        goto fail;--    buf = buf1;-    buf_allocated = FALSE;-    len = p - p_start;-    if (unlikely((len + 2) > sizeof(buf1))) {-        buf = js_malloc_rt(ctx->rt, len + 2); /* no exception raised */-        if (!buf)-            goto mem_error;-        buf_allocated = TRUE;-    }-    /* remove the separators and the radix prefixes */-    j = 0;-    if (is_neg)-        buf[j++] = '-';-    for (i = 0; i < len; i++) {-        if (p_start[i] != '_')-            buf[j++] = p_start[i];-    }-    buf[j] = '\0';--#ifdef CONFIG_BIGNUM-    if (flags & ATOD_ACCEPT_SUFFIX) {-        if (*p == 'n') {-            p++;-            atod_type = ATOD_TYPE_BIG_INT;-        } else if (*p == 'l') {-            p++;-            atod_type = ATOD_TYPE_BIG_FLOAT;-        } else if (*p == 'm') {-            p++;-            atod_type = ATOD_TYPE_BIG_DECIMAL;-        } else {-            if (flags & ATOD_MODE_BIGINT) {-                if (!is_float)-                    atod_type = ATOD_TYPE_BIG_INT;-                if (has_legacy_octal)-                    goto fail;-            } else {-                if (is_float && radix != 10)-                    goto fail;-            }-        }-    } else {-        if (atod_type == ATOD_TYPE_FLOAT64) {-            if (flags & ATOD_MODE_BIGINT) {-                if (!is_float)-                    atod_type = ATOD_TYPE_BIG_INT;-                if (has_legacy_octal)-                    goto fail;-            } else {-                if (is_float && radix != 10)-                    goto fail;-            }-        }-    }--    switch(atod_type) {-    case ATOD_TYPE_FLOAT64:-        {-            double d;-            d = js_strtod(buf, radix, is_float);-            /* return int or float64 */-            val = JS_NewFloat64(ctx, d);-        }-        break;-    case ATOD_TYPE_BIG_INT:-        if (has_legacy_octal || is_float)-            goto fail;-        val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL);-        break;-    case ATOD_TYPE_BIG_FLOAT:-        if (has_legacy_octal)-            goto fail;-        val = ctx->rt->bigfloat_ops.from_string(ctx, buf, radix, flags,-                                                pexponent);-        break;-    case ATOD_TYPE_BIG_DECIMAL:-        if (radix != 10)-            goto fail;-        val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);-        break;-    default:-        abort();-    }-#else-    {-        double d;-        (void)has_legacy_octal;-        if (is_float && radix != 10)-            goto fail;-        d = js_strtod(buf, radix, is_float);-        val = JS_NewFloat64(ctx, d);-    }-#endif-    -done:-    if (buf_allocated)-        js_free_rt(ctx->rt, buf);-    if (pp)-        *pp = p;-    return val;- fail:-    val = JS_NAN;-    goto done;- mem_error:-    val = JS_ThrowOutOfMemory(ctx);-    goto done;-}--#ifdef CONFIG_BIGNUM-static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,-                       int radix, int flags)-{-    return js_atof2(ctx, str, pp, radix, flags, NULL);-}-#endif--typedef enum JSToNumberHintEnum {-    TON_FLAG_NUMBER,-    TON_FLAG_NUMERIC,-} JSToNumberHintEnum;--static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,-                                   JSToNumberHintEnum flag)-{-    uint32_t tag;-    JSValue ret;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_DECIMAL:-        if (flag != TON_FLAG_NUMERIC) {-            JS_FreeValue(ctx, val);-            return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");-        }-        ret = val;-        break;-    case JS_TAG_BIG_INT:-        if (flag != TON_FLAG_NUMERIC) {-            JS_FreeValue(ctx, val);-            return JS_ThrowTypeError(ctx, "cannot convert bigint to number");-        }-        ret = val;-        break;-    case JS_TAG_BIG_FLOAT:-        if (flag != TON_FLAG_NUMERIC) {-            JS_FreeValue(ctx, val);-            return JS_ThrowTypeError(ctx, "cannot convert bigfloat to number");-        }-        ret = val;-        break;-#endif-    case JS_TAG_FLOAT64:-    case JS_TAG_INT:-    case JS_TAG_EXCEPTION:-        ret = val;-        break;-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-        ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));-        break;-    case JS_TAG_UNDEFINED:-        ret = JS_NAN;-        break;-    case JS_TAG_OBJECT:-        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);-        if (JS_IsException(val))-            return JS_EXCEPTION;-        goto redo;-    case JS_TAG_STRING:-        {-            const char *str;-            const char *p;-            size_t len;-            -            str = JS_ToCStringLen(ctx, &len, val);-            JS_FreeValue(ctx, val);-            if (!str)-                return JS_EXCEPTION;-            p = str;-            p += skip_spaces(p);-            if ((p - str) == len) {-                ret = JS_NewInt32(ctx, 0);-            } else {-                int flags = ATOD_ACCEPT_BIN_OCT;-                ret = js_atof(ctx, p, &p, 0, flags);-                if (!JS_IsException(ret)) {-                    p += skip_spaces(p);-                    if ((p - str) != len) {-                        JS_FreeValue(ctx, ret);-                        ret = JS_NAN;-                    }-                }-            }-            JS_FreeCString(ctx, str);-        }-        break;-    case JS_TAG_SYMBOL:-        JS_FreeValue(ctx, val);-        return JS_ThrowTypeError(ctx, "cannot convert symbol to number");-    default:-        JS_FreeValue(ctx, val);-        ret = JS_NAN;-        break;-    }-    return ret;-}--static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val)-{-    return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMBER);-}--static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val)-{-    return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMERIC);-}--static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)-{-    return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));-}--static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,-                                          JSValue val)-{-    double d;-    uint32_t tag;--    val = JS_ToNumberFree(ctx, val);-    if (JS_IsException(val)) {-        *pres = JS_FLOAT64_NAN;-        return -1;-    }-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-        d = JS_VALUE_GET_INT(val);-        break;-    case JS_TAG_FLOAT64:-        d = JS_VALUE_GET_FLOAT64(val);-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            /* XXX: there can be a double rounding issue with some-               primitives (such as JS_ToUint8ClampFree()), but it is-               not critical to fix it. */-            bf_get_float64(&p->num, &d, BF_RNDN);-            JS_FreeValue(ctx, val);-        }-        break;-#endif-    default:-        abort();-    }-    *pres = d;-    return 0;-}--static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)-{-    uint32_t tag;--    tag = JS_VALUE_GET_TAG(val);-    if (tag <= JS_TAG_NULL) {-        *pres = JS_VALUE_GET_INT(val);-        return 0;-    } else if (JS_TAG_IS_FLOAT64(tag)) {-        *pres = JS_VALUE_GET_FLOAT64(val);-        return 0;-    } else {-        return __JS_ToFloat64Free(ctx, pres, val);-    }-}--int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val)-{-    return JS_ToFloat64Free(ctx, pres, JS_DupValue(ctx, val));-}--static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)-{-    return JS_ToNumberFree(ctx, JS_DupValue(ctx, val));-}--/* same as JS_ToNumber() but return 0 in case of NaN/Undefined */-static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)-{-    uint32_t tag;-    JSValue ret;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));-        break;-    case JS_TAG_FLOAT64:-        {-            double d = JS_VALUE_GET_FLOAT64(val);-            if (isnan(d)) {-                ret = JS_NewInt32(ctx, 0);-            } else {-                /* convert -0 to +0 */-                d = trunc(d) + 0.0;-                ret = JS_NewFloat64(ctx, d);-            }-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            bf_t a_s, *a, r_s, *r = &r_s;-            BOOL is_nan;--            a = JS_ToBigFloat(ctx, &a_s, val);-            if (!bf_is_finite(a)) {-                is_nan = bf_is_nan(a);-                if (is_nan)-                    ret = JS_NewInt32(ctx, 0);-                else-                    ret = JS_DupValue(ctx, val);-            } else {-                ret = JS_NewBigInt(ctx);-                if (!JS_IsException(ret)) {-                    r = JS_GetBigInt(ret);-                    bf_set(r, a);-                    bf_rint(r, BF_RNDZ);-                    ret = JS_CompactBigInt(ctx, ret);-                }-            }-            if (a == &a_s)-                bf_delete(a);-            JS_FreeValue(ctx, val);-        }-        break;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val))-            return val;-        goto redo;-    }-    return ret;-}--/* Note: the integer value is satured to 32 bits */-static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val)-{-    uint32_t tag;-    int ret;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        ret = JS_VALUE_GET_INT(val);-        break;-    case JS_TAG_EXCEPTION:-        *pres = 0;-        return -1;-    case JS_TAG_FLOAT64:-        {-            double d = JS_VALUE_GET_FLOAT64(val);-            if (isnan(d)) {-                ret = 0;-            } else {-                if (d < INT32_MIN)-                    ret = INT32_MIN;-                else if (d > INT32_MAX)-                    ret = INT32_MAX;-                else-                    ret = (int)d;-            }-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_get_int32(&ret, &p->num, 0);-            JS_FreeValue(ctx, val);-        }-        break;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val)) {-            *pres = 0;-            return -1;-        }-        goto redo;-    }-    *pres = ret;-    return 0;-}--int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val)-{-    return JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));-}--int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val,-                    int min, int max, int min_offset)-{-    int res = JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));-    if (res == 0) {-        if (*pres < min) {-            *pres += min_offset;-            if (*pres < min)-                *pres = min;-        } else {-            if (*pres > max)-                *pres = max;-        }-    }-    return res;-}--static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)-{-    uint32_t tag;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        *pres = JS_VALUE_GET_INT(val);-        return 0;-    case JS_TAG_EXCEPTION:-        *pres = 0;-        return -1;-    case JS_TAG_FLOAT64:-        {-            double d = JS_VALUE_GET_FLOAT64(val);-            if (isnan(d)) {-                *pres = 0;-            } else {-                if (d < INT64_MIN)-                    *pres = INT64_MIN;-                else if (d > INT64_MAX)-                    *pres = INT64_MAX;-                else-                    *pres = (int64_t)d;-            }-        }-        return 0;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_get_int64(pres, &p->num, 0);-            JS_FreeValue(ctx, val);-        }-        return 0;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val)) {-            *pres = 0;-            return -1;-        }-        goto redo;-    }-}--int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val)-{-    return JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));-}--int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val,-                    int64_t min, int64_t max, int64_t neg_offset)-{-    int res = JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));-    if (res == 0) {-        if (*pres < 0)-            *pres += neg_offset;-        if (*pres < min)-            *pres = min;-        else if (*pres > max)-            *pres = max;-    }-    return res;-}--/* Same as JS_ToInt32Free() but with a 64 bit result. Return (<0, 0)-   in case of exception */-static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val)-{-    uint32_t tag;-    int64_t ret;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        ret = JS_VALUE_GET_INT(val);-        break;-    case JS_TAG_FLOAT64:-        {-            JSFloat64Union u;-            double d;-            int e;-            d = JS_VALUE_GET_FLOAT64(val);-            u.d = d;-            /* we avoid doing fmod(x, 2^64) */-            e = (u.u64 >> 52) & 0x7ff;-            if (likely(e <= (1023 + 62))) {-                /* fast case */-                ret = (int64_t)d;-            } else if (e <= (1023 + 62 + 53)) {-                uint64_t v;-                /* remainder modulo 2^64 */-                v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52);-                ret = v << ((e - 1023) - 52);-                /* take the sign into account */-                if (u.u64 >> 63)-                    ret = -ret;-            } else {-                ret = 0; /* also handles NaN and +inf */-            }-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_get_int64(&ret, &p->num, BF_GET_INT_MOD);-            JS_FreeValue(ctx, val);-        }-        break;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val)) {-            *pres = 0;-            return -1;-        }-        goto redo;-    }-    *pres = ret;-    return 0;-}--int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val)-{-    return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val));-}--int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val)-{-    if (JS_IsBigInt(ctx, val))-        return JS_ToBigInt64(ctx, pres, val);-    else-        return JS_ToInt64(ctx, pres, val);-}--/* return (<0, 0) in case of exception */-static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val)-{-    uint32_t tag;-    int32_t ret;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        ret = JS_VALUE_GET_INT(val);-        break;-    case JS_TAG_FLOAT64:-        {-            JSFloat64Union u;-            double d;-            int e;-            d = JS_VALUE_GET_FLOAT64(val);-            u.d = d;-            /* we avoid doing fmod(x, 2^32) */-            e = (u.u64 >> 52) & 0x7ff;-            if (likely(e <= (1023 + 30))) {-                /* fast case */-                ret = (int32_t)d;-            } else if (e <= (1023 + 30 + 53)) {-                uint64_t v;-                /* remainder modulo 2^32 */-                v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52);-                v = v << ((e - 1023) - 52 + 32);-                ret = v >> 32;-                /* take the sign into account */-                if (u.u64 >> 63)-                    ret = -ret;-            } else {-                ret = 0; /* also handles NaN and +inf */-            }-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_get_int32(&ret, &p->num, BF_GET_INT_MOD);-            JS_FreeValue(ctx, val);-        }-        break;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val)) {-            *pres = 0;-            return -1;-        }-        goto redo;-    }-    *pres = ret;-    return 0;-}--int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val)-{-    return JS_ToInt32Free(ctx, pres, JS_DupValue(ctx, val));-}--static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val)-{-    return JS_ToInt32Free(ctx, (int32_t *)pres, val);-}--static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)-{-    uint32_t tag;-    int res;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        res = JS_VALUE_GET_INT(val);-#ifdef CONFIG_BIGNUM-    int_clamp:-#endif-        res = max_int(0, min_int(255, res));-        break;-    case JS_TAG_FLOAT64:-        {-            double d = JS_VALUE_GET_FLOAT64(val);-            if (isnan(d)) {-                res = 0;-            } else {-                if (d < 0)-                    res = 0;-                else if (d > 255)-                    res = 255;-                else-                    res = lrint(d);-            }-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_t r_s, *r = &r_s;-            bf_init(ctx->bf_ctx, r);-            bf_set(r, &p->num);-            bf_rint(r, BF_RNDN);-            bf_get_int32(&res, r, 0);-            bf_delete(r);-            JS_FreeValue(ctx, val);-        }-        goto int_clamp;-#endif-    default:-        val = JS_ToNumberFree(ctx, val);-        if (JS_IsException(val)) {-            *pres = 0;-            return -1;-        }-        goto redo;-    }-    *pres = res;-    return 0;-}--static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,-                                            JSValue val)-{-    uint32_t tag, len;-- redo:-    tag = JS_VALUE_GET_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-        {-            int v;-            v = JS_VALUE_GET_INT(val);-            if (v < 0)-                goto fail;-            len = v;-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            bf_t a;-            BOOL res;-            bf_get_int32((int32_t *)&len, &p->num, BF_GET_INT_MOD);-            bf_init(ctx->bf_ctx, &a);-            bf_set_ui(&a, len);-            res = bf_cmp_eq(&a, &p->num);-            bf_delete(&a);-            JS_FreeValue(ctx, val);-            if (!res)-                goto fail;-        }-        break;-#endif-    default:-        if (JS_TAG_IS_FLOAT64(tag)) {-            double d;-            d = JS_VALUE_GET_FLOAT64(val);-            len = (uint32_t)d;-            if (len != d) {-            fail:-                JS_ThrowRangeError(ctx, "invalid array length");-                return -1;-            }-        } else {-            val = JS_ToNumberFree(ctx, val);-            if (JS_IsException(val))-                return -1;-            goto redo;-        }-        break;-    }-    *plen = len;-    return 0;-}--#define MAX_SAFE_INTEGER (((int64_t)1 << 53) - 1)--static BOOL is_safe_integer(double d)-{-    return isfinite(d) && floor(d) == d &&-        fabs(d) <= (double)MAX_SAFE_INTEGER;-}--int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)-{-    int64_t v;-    if (JS_ToInt64Sat(ctx, &v, val))-        return -1;-    if (v < 0 || v > MAX_SAFE_INTEGER) {-        JS_ThrowRangeError(ctx, "invalid array index");-        *plen = 0;-        return -1;-    }-    *plen = v;-    return 0;-}--/* convert a value to a length between 0 and MAX_SAFE_INTEGER.-   return -1 for exception */-static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,-                                       JSValue val)-{-    int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);-    JS_FreeValue(ctx, val);-    return res;-}--/* Note: can return an exception */-static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val)-{-    double d;-    if (!JS_IsNumber(val))-        return FALSE;-    if (unlikely(JS_ToFloat64(ctx, &d, val)))-        return -1;-    return isfinite(d) && floor(d) == d;-}--static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)-{-    uint32_t tag;--    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-        {-            int v;-            v = JS_VALUE_GET_INT(val);-            return (v < 0);-        }-    case JS_TAG_FLOAT64:-        {-            JSFloat64Union u;-            u.d = JS_VALUE_GET_FLOAT64(val);-            return (u.u64 >> 63);-        }-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            /* Note: integer zeros are not necessarily positive */-            return p->num.sign && !bf_is_zero(&p->num);-        }-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            return p->num.sign;-        }-        break;-    case JS_TAG_BIG_DECIMAL:-        {-            JSBigDecimal *p = JS_VALUE_GET_PTR(val);-            return p->num.sign;-        }-        break;-#endif-    default:-        return FALSE;-    }-}--#ifdef CONFIG_BIGNUM--static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)-{-    JSValue ret;-    bf_t a_s, *a;-    char *str;-    int saved_sign;--    a = JS_ToBigInt(ctx, &a_s, val);-    if (!a)-        return JS_EXCEPTION;-    saved_sign = a->sign;-    if (a->expn == BF_EXP_ZERO)-        a->sign = 0;-    str = bf_ftoa(NULL, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |-                  BF_FTOA_JS_QUIRKS);-    a->sign = saved_sign;-    JS_FreeBigInt(ctx, a, &a_s);-    if (!str)-        return JS_ThrowOutOfMemory(ctx);-    ret = JS_NewString(ctx, str);-    bf_free(ctx->bf_ctx, str);-    return ret;-}--static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val)-{-    return js_bigint_to_string1(ctx, val, 10);-}--static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,-                       limb_t prec, bf_flags_t flags)-{-    JSValue val, ret;-    bf_t a_s, *a;-    char *str;-    int saved_sign;--    val = JS_ToNumeric(ctx, val1);-    if (JS_IsException(val))-        return val;-    a = JS_ToBigFloat(ctx, &a_s, val);-    saved_sign = a->sign;-    if (a->expn == BF_EXP_ZERO)-        a->sign = 0;-    flags |= BF_FTOA_JS_QUIRKS;-    if ((flags & BF_FTOA_FORMAT_MASK) == BF_FTOA_FORMAT_FREE_MIN) {-        /* Note: for floating point numbers with a radix which is not-           a power of two, the current precision is used to compute-           the number of digits. */-        if ((radix & (radix - 1)) != 0) {-            bf_t r_s, *r = &r_s;-            int prec, flags1;-            /* must round first */-            if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {-                prec = ctx->fp_env.prec;-                flags1 = ctx->fp_env.flags &-                    (BF_FLAG_SUBNORMAL | (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT));-            } else {-                prec = 53;-                flags1 = bf_set_exp_bits(11) | BF_FLAG_SUBNORMAL;-            }-            bf_init(ctx->bf_ctx, r);-            bf_set(r, a);-            bf_round(r, prec, flags1 | BF_RNDN);-            str = bf_ftoa(NULL, r, radix, prec, flags1 | flags);-            bf_delete(r);-        } else {-            str = bf_ftoa(NULL, a, radix, BF_PREC_INF, flags);-        }-    } else {-        str = bf_ftoa(NULL, a, radix, prec, flags);-    }-    a->sign = saved_sign;-    if (a == &a_s)-        bf_delete(a);-    JS_FreeValue(ctx, val);-    if (!str)-        return JS_ThrowOutOfMemory(ctx);-    ret = JS_NewString(ctx, str);-    bf_free(ctx->bf_ctx, str);-    return ret;-}--static JSValue js_bigfloat_to_string(JSContext *ctx, JSValueConst val)-{-    return js_ftoa(ctx, val, 10, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);-}--static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val,-                                        limb_t prec, int flags)-{-    JSValue ret;-    bfdec_t *a;-    char *str;-    int saved_sign;--    a = JS_ToBigDecimal(ctx, val);-    saved_sign = a->sign;-    if (a->expn == BF_EXP_ZERO)-        a->sign = 0;-    str = bfdec_ftoa(NULL, a, prec, flags | BF_FTOA_JS_QUIRKS);-    a->sign = saved_sign;-    if (!str)-        return JS_ThrowOutOfMemory(ctx);-    ret = JS_NewString(ctx, str);-    bf_free(ctx->bf_ctx, str);-    return ret;-}--static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val)-{-    return js_bigdecimal_to_string1(ctx, val, 0,-                                    BF_RNDZ | BF_FTOA_FORMAT_FREE);-}--#endif /* CONFIG_BIGNUM */--/* 2 <= base <= 36 */-static char *i64toa(char *buf_end, int64_t n, unsigned int base)-{-    char *q = buf_end;-    int digit, is_neg;--    is_neg = 0;-    if (n < 0) {-        is_neg = 1;-        n = -n;-    }-    *--q = '\0';-    do {-        digit = (uint64_t)n % base;-        n = (uint64_t)n / base;-        if (digit < 10)-            digit += '0';-        else-            digit += 'a' - 10;-        *--q = digit;-    } while (n != 0);-    if (is_neg)-        *--q = '-';-    return q;-}--/* buf1 contains the printf result */-static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf,-                     int rounding_mode, char *buf1, int buf1_size)-{-    if (rounding_mode != FE_TONEAREST)-        fesetround(rounding_mode);-    snprintf(buf1, buf1_size, "%+.*e", n_digits - 1, d);-    if (rounding_mode != FE_TONEAREST)-        fesetround(FE_TONEAREST);-    *sign = (buf1[0] == '-');-    /* mantissa */-    buf[0] = buf1[1];-    if (n_digits > 1)-        memcpy(buf + 1, buf1 + 3, n_digits - 1);-    buf[n_digits] = '\0';-    /* exponent */-    *decpt = atoi(buf1 + n_digits + 2 + (n_digits > 1)) + 1;-}--/* maximum buffer size for js_dtoa */-#define JS_DTOA_BUF_SIZE 128--/* needed because ecvt usually limits the number of digits to-   17. Return the number of digits. */-static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,-                   BOOL is_fixed)-{-    int rounding_mode;-    char buf_tmp[JS_DTOA_BUF_SIZE];--    if (!is_fixed) {-        unsigned int n_digits_min, n_digits_max;-        /* find the minimum amount of digits (XXX: inefficient but simple) */-        n_digits_min = 1;-        n_digits_max = 17;-        while (n_digits_min < n_digits_max) {-            n_digits = (n_digits_min + n_digits_max) / 2;-            js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST,-                     buf_tmp, sizeof(buf_tmp));-            if (strtod(buf_tmp, NULL) == d) {-                /* no need to keep the trailing zeros */-                while (n_digits >= 2 && buf[n_digits - 1] == '0')-                    n_digits--;-                n_digits_max = n_digits;-            } else {-                n_digits_min = n_digits + 1;-            }-        }-        n_digits = n_digits_max;-        rounding_mode = FE_TONEAREST;-    } else {-        rounding_mode = FE_TONEAREST;-#ifdef CONFIG_PRINTF_RNDN-        {-            char buf1[JS_DTOA_BUF_SIZE], buf2[JS_DTOA_BUF_SIZE];-            int decpt1, sign1, decpt2, sign2;-            /* The JS rounding is specified as round to nearest ties away-               from zero (RNDNA), but in printf the "ties" case is not-               specified (for example it is RNDN for glibc, RNDNA for-               Windows), so we must round manually. */-            js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_TONEAREST,-                     buf_tmp, sizeof(buf_tmp));-            /* XXX: could use 2 digits to reduce the average running time */-            if (buf1[n_digits] == '5') {-                js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_DOWNWARD,-                         buf_tmp, sizeof(buf_tmp));-                js_ecvt1(d, n_digits + 1, &decpt2, &sign2, buf2, FE_UPWARD,-                         buf_tmp, sizeof(buf_tmp));-                if (memcmp(buf1, buf2, n_digits + 1) == 0 && decpt1 == decpt2) {-                    /* exact result: round away from zero */-                    if (sign1)-                        rounding_mode = FE_DOWNWARD;-                    else-                        rounding_mode = FE_UPWARD;-                }-            }-        }-#endif /* CONFIG_PRINTF_RNDN */-    }-    js_ecvt1(d, n_digits, decpt, sign, buf, rounding_mode,-             buf_tmp, sizeof(buf_tmp));-    return n_digits;-}--static int js_fcvt1(char *buf, int buf_size, double d, int n_digits,-                    int rounding_mode)-{-    int n;-    if (rounding_mode != FE_TONEAREST)-        fesetround(rounding_mode);-    n = snprintf(buf, buf_size, "%.*f", n_digits, d);-    if (rounding_mode != FE_TONEAREST)-        fesetround(FE_TONEAREST);-    assert(n < buf_size);-    return n;-}--static void js_fcvt(char *buf, int buf_size, double d, int n_digits)-{-    int rounding_mode;-    rounding_mode = FE_TONEAREST;-#ifdef CONFIG_PRINTF_RNDN-    {-        int n1, n2;-        char buf1[JS_DTOA_BUF_SIZE];-        char buf2[JS_DTOA_BUF_SIZE];--        /* The JS rounding is specified as round to nearest ties away from-           zero (RNDNA), but in printf the "ties" case is not specified-           (for example it is RNDN for glibc, RNDNA for Windows), so we-           must round manually. */-        n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_TONEAREST);-        rounding_mode = FE_TONEAREST;-        /* XXX: could use 2 digits to reduce the average running time */-        if (buf1[n1 - 1] == '5') {-            n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_DOWNWARD);-            n2 = js_fcvt1(buf2, sizeof(buf2), d, n_digits + 1, FE_UPWARD);-            if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) {-                /* exact result: round away from zero */-                if (buf1[0] == '-')-                    rounding_mode = FE_DOWNWARD;-                else-                    rounding_mode = FE_UPWARD;-            }-        }-    }-#endif /* CONFIG_PRINTF_RNDN */-    js_fcvt1(buf, buf_size, d, n_digits, rounding_mode);-}--/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */-/* use as many digits as necessary */-#define JS_DTOA_VAR_FORMAT   (0 << 0)-/* use n_digits significant digits (1 <= n_digits <= 101) */-#define JS_DTOA_FIXED_FORMAT (1 << 0)-/* force fractional format: [-]dd.dd with n_digits fractional digits */-#define JS_DTOA_FRAC_FORMAT  (2 << 0)-/* force exponential notation either in fixed or variable format */-#define JS_DTOA_FORCE_EXP    (1 << 2)--/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough.-   XXX: radix != 10 is only supported for small integers-*/-static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)-{-    char *q;--    if (!isfinite(d)) {-        if (isnan(d)) {-            strcpy(buf, "NaN");-        } else {-            q = buf;-            if (d < 0)-                *q++ = '-';-            strcpy(q, "Infinity");-        }-    } else if (flags == JS_DTOA_VAR_FORMAT) {-        int64_t i64;-        char buf1[70], *ptr;-        i64 = (int64_t)d;-        if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER)-            goto generic_conv;-        /* fast path for integers */-        ptr = i64toa(buf1 + sizeof(buf1), i64, radix);-        strcpy(buf, ptr);-    } else {-        if (d == 0.0)-            d = 0.0; /* convert -0 to 0 */-        if (flags == JS_DTOA_FRAC_FORMAT) {-            js_fcvt(buf, JS_DTOA_BUF_SIZE, d, n_digits);-        } else {-            char buf1[JS_DTOA_BUF_SIZE];-            int sign, decpt, k, n, i, p, n_max;-            BOOL is_fixed;-        generic_conv:-            is_fixed = ((flags & 3) == JS_DTOA_FIXED_FORMAT);-            if (is_fixed) {-                n_max = n_digits;-            } else {-                n_max = 21;-            }-            /* the number has k digits (k >= 1) */-            k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed);-            n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */-            q = buf;-            if (sign)-                *q++ = '-';-            if (flags & JS_DTOA_FORCE_EXP)-                goto force_exp;-            if (n >= 1 && n <= n_max) {-                if (k <= n) {-                    memcpy(q, buf1, k);-                    q += k;-                    for(i = 0; i < (n - k); i++)-                        *q++ = '0';-                    *q = '\0';-                } else {-                    /* k > n */-                    memcpy(q, buf1, n);-                    q += n;-                    *q++ = '.';-                    for(i = 0; i < (k - n); i++)-                        *q++ = buf1[n + i];-                    *q = '\0';-                }-            } else if (n >= -5 && n <= 0) {-                *q++ = '0';-                *q++ = '.';-                for(i = 0; i < -n; i++)-                    *q++ = '0';-                memcpy(q, buf1, k);-                q += k;-                *q = '\0';-            } else {-            force_exp:-                /* exponential notation */-                *q++ = buf1[0];-                if (k > 1) {-                    *q++ = '.';-                    for(i = 1; i < k; i++)-                        *q++ = buf1[i];-                }-                *q++ = 'e';-                p = n - 1;-                if (p >= 0)-                    *q++ = '+';-                sprintf(q, "%d", p);-            }-        }-    }-}--static JSValue js_dtoa(JSContext *ctx,-                       double d, int radix, int n_digits, int flags)-{-    char buf[JS_DTOA_BUF_SIZE];-    js_dtoa1(buf, d, radix, n_digits, flags);-    return JS_NewString(ctx, buf);-}--JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey)-{-    uint32_t tag;-    const char *str;-    char buf[32];--    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_STRING:-        return JS_DupValue(ctx, val);-    case JS_TAG_INT:-        snprintf(buf, sizeof(buf), "%d", JS_VALUE_GET_INT(val));-        str = buf;-        goto new_string;-    case JS_TAG_BOOL:-        return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ?-                          JS_ATOM_true : JS_ATOM_false);-    case JS_TAG_NULL:-        return JS_AtomToString(ctx, JS_ATOM_null);-    case JS_TAG_UNDEFINED:-        return JS_AtomToString(ctx, JS_ATOM_undefined);-    case JS_TAG_EXCEPTION:-        return JS_EXCEPTION;-    case JS_TAG_OBJECT:-        {-            JSValue val1, ret;-            val1 = JS_ToPrimitive(ctx, val, HINT_STRING);-            if (JS_IsException(val1))-                return val1;-            ret = JS_ToStringInternal(ctx, val1, is_ToPropertyKey);-            JS_FreeValue(ctx, val1);-            return ret;-        }-        break;-    case JS_TAG_FUNCTION_BYTECODE:-        str = "[function bytecode]";-        goto new_string;-    case JS_TAG_SYMBOL:-        if (is_ToPropertyKey) {-            return JS_DupValue(ctx, val);-        } else {-            return JS_ThrowTypeError(ctx, "cannot convert symbol to string");-        }-    case JS_TAG_FLOAT64:-        return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0,-                       JS_DTOA_VAR_FORMAT);-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        return ctx->rt->bigint_ops.to_string(ctx, val);-    case JS_TAG_BIG_FLOAT:-        return ctx->rt->bigfloat_ops.to_string(ctx, val);-    case JS_TAG_BIG_DECIMAL:-        return ctx->rt->bigdecimal_ops.to_string(ctx, val);-#endif-    default:-        str = "[unsupported type]";-    new_string:-        return JS_NewString(ctx, str);-    }-}--JSValue JS_ToString(JSContext *ctx, JSValueConst val)-{-    return JS_ToStringInternal(ctx, val, FALSE);-}--static JSValue JS_ToStringFree(JSContext *ctx, JSValue val)-{-    JSValue ret;-    ret = JS_ToString(ctx, val);-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val)-{-    if (JS_IsUndefined(val) || JS_IsNull(val))-        return JS_ToStringFree(ctx, val);-    return JS_InvokeFree(ctx, val, JS_ATOM_toLocaleString, 0, NULL);-}--JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val)-{-    return JS_ToStringInternal(ctx, val, TRUE);-}--static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)-{-    uint32_t tag = JS_VALUE_GET_TAG(val);-    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)-        return JS_ThrowTypeError(ctx, "null or undefined are forbidden");-    return JS_ToString(ctx, val);-}--static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)-{-    JSValue val;-    JSString *p;-    int i;-    uint32_t c;-    StringBuffer b_s, *b = &b_s;-    char buf[16];--    val = JS_ToStringCheckObject(ctx, val1);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_STRING(val);--    if (string_buffer_init(ctx, b, p->len + 2))-        goto fail;--    if (string_buffer_putc8(b, '\"'))-        goto fail;-    for(i = 0; i < p->len; ) {-        c = string_getc(p, &i);-        switch(c) {-        case '\t':-            c = 't';-            goto quote;-        case '\r':-            c = 'r';-            goto quote;-        case '\n':-            c = 'n';-            goto quote;-        case '\b':-            c = 'b';-            goto quote;-        case '\f':-            c = 'f';-            goto quote;-        case '\"':-        case '\\':-        quote:-            if (string_buffer_putc8(b, '\\'))-                goto fail;-            if (string_buffer_putc8(b, c))-                goto fail;-            break;-        default:-            if (c < 32 || (c >= 0xd800 && c < 0xe000)) {-                snprintf(buf, sizeof(buf), "\\u%04x", c);-                if (string_buffer_puts8(b, buf))-                    goto fail;-            } else {-                if (string_buffer_putc(b, c))-                    goto fail;-            }-            break;-        }-    }-    if (string_buffer_putc8(b, '\"'))-        goto fail;-    JS_FreeValue(ctx, val);-    return string_buffer_end(b);- fail:-    JS_FreeValue(ctx, val);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)-{-    printf("%14s %4s %4s %14s %10s %s\n",-           "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");-}--/* for debug only: dump an object without side effect */-static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)-{-    uint32_t i;-    char atom_buf[ATOM_GET_STR_BUF_SIZE];-    JSShape *sh;-    JSShapeProperty *prs;-    JSProperty *pr;-    BOOL is_first = TRUE;--    /* XXX: should encode atoms with special characters */-    sh = p->shape; /* the shape can be NULL while freeing an object */-    printf("%14p %4d ",-           (void *)p,-           p->header.ref_count);-    if (sh) {-        printf("%3d%c %14p ",-               sh->header.ref_count,-               " *"[sh->is_hashed],-               (void *)sh->proto);-    } else {-        printf("%3s  %14s ", "-", "-");-    }-    printf("%10s ",-           JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name));-    if (p->is_exotic && p->fast_array) {-        printf("[ ");-        for(i = 0; i < p->u.array.count; i++) {-            if (i != 0)-                printf(", ");-            switch (p->class_id) {-            case JS_CLASS_ARRAY:-            case JS_CLASS_ARGUMENTS:-                JS_DumpValueShort(rt, p->u.array.u.values[i]);-                break;-            case JS_CLASS_UINT8C_ARRAY:-            case JS_CLASS_INT8_ARRAY:-            case JS_CLASS_UINT8_ARRAY:-            case JS_CLASS_INT16_ARRAY:-            case JS_CLASS_UINT16_ARRAY:-            case JS_CLASS_INT32_ARRAY:-            case JS_CLASS_UINT32_ARRAY:-#ifdef CONFIG_BIGNUM-            case JS_CLASS_BIG_INT64_ARRAY:-            case JS_CLASS_BIG_UINT64_ARRAY:-#endif-            case JS_CLASS_FLOAT32_ARRAY:-            case JS_CLASS_FLOAT64_ARRAY:-                {-                    int size = 1 << typed_array_size_log2(p->class_id);-                    const uint8_t *b = p->u.array.u.uint8_ptr + i * size;-                    while (size-- > 0)-                        printf("%02X", *b++);-                }-                break;-            }-        }-        printf(" ] ");-    }--    if (sh) {-        printf("{ ");-        for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {-            if (prs->atom != JS_ATOM_NULL) {-                pr = &p->prop[i];-                if (!is_first)-                    printf(", ");-                printf("%s: ",-                       JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom));-                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {-                    printf("[getset %p %p]", (void *)pr->u.getset.getter,-                           (void *)pr->u.getset.setter);-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {-                    printf("[varref %p]", (void *)pr->u.var_ref);-                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {-                    printf("[autoinit %p %d %p]",-                           (void *)js_autoinit_get_realm(pr),-                           js_autoinit_get_id(pr),-                           (void *)pr->u.init.opaque);-                } else {-                    JS_DumpValueShort(rt, pr->u.value);-                }-                is_first = FALSE;-            }-        }-        printf(" }");-    }-    -    if (js_class_has_bytecode(p->class_id)) {-        JSFunctionBytecode *b = p->u.func.function_bytecode;-        JSVarRef **var_refs;-        if (b->closure_var_count) {-            var_refs = p->u.func.var_refs;-            printf(" Closure:");-            for(i = 0; i < b->closure_var_count; i++) {-                printf(" ");-                JS_DumpValueShort(rt, var_refs[i]->value);-            }-            if (p->u.func.home_object) {-                printf(" HomeObject: ");-                JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));-            }-        }-    }-    printf("\n");-}--static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)-{-    if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {-        JS_DumpObject(rt, (JSObject *)p);-    } else {-        printf("%14p %4d ",-               (void *)p,-               p->ref_count);-        switch(p->gc_obj_type) {-        case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:-            printf("[function bytecode]");-            break;-        case JS_GC_OBJ_TYPE_SHAPE:-            printf("[shape]");-            break;-        case JS_GC_OBJ_TYPE_VAR_REF:-            printf("[var_ref]");-            break;-        case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:-            printf("[async_function]");-            break;-        case JS_GC_OBJ_TYPE_JS_CONTEXT:-            printf("[js_context]");-            break;-        default:-            printf("[unknown %d]", p->gc_obj_type);-            break;-        }-        printf("\n");-    }-}--static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,-                                                      JSValueConst val)-{-    uint32_t tag = JS_VALUE_GET_NORM_TAG(val);-    const char *str;--    switch(tag) {-    case JS_TAG_INT:-        printf("%d", JS_VALUE_GET_INT(val));-        break;-    case JS_TAG_BOOL:-        if (JS_VALUE_GET_BOOL(val))-            str = "true";-        else-            str = "false";-        goto print_str;-    case JS_TAG_NULL:-        str = "null";-        goto print_str;-    case JS_TAG_EXCEPTION:-        str = "exception";-        goto print_str;-    case JS_TAG_UNINITIALIZED:-        str = "uninitialized";-        goto print_str;-    case JS_TAG_UNDEFINED:-        str = "undefined";-    print_str:-        printf("%s", str);-        break;-    case JS_TAG_FLOAT64:-        printf("%.14g", JS_VALUE_GET_FLOAT64(val));-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            char *str;-            str = bf_ftoa(NULL, &p->num, 10, 0,-                          BF_RNDZ | BF_FTOA_FORMAT_FRAC);-            printf("%sn", str);-            bf_realloc(&rt->bf_ctx, str, 0);-        }-        break;-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            char *str;-            str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF,-                          BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX);-            printf("%sl", str);-            bf_free(&rt->bf_ctx, str);-        }-        break;-    case JS_TAG_BIG_DECIMAL:-        {-            JSBigDecimal *p = JS_VALUE_GET_PTR(val);-            char *str;-            str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF,-                             BF_RNDZ | BF_FTOA_FORMAT_FREE);-            printf("%sm", str);-            bf_free(&rt->bf_ctx, str);-        }-        break;-#endif-    case JS_TAG_STRING:-        {-            JSString *p;-            p = JS_VALUE_GET_STRING(val);-            JS_DumpString(rt, p);-        }-        break;-    case JS_TAG_FUNCTION_BYTECODE:-        {-            JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);-            char buf[ATOM_GET_STR_BUF_SIZE];-            printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));-        }-        break;-    case JS_TAG_OBJECT:-        {-            JSObject *p = JS_VALUE_GET_OBJ(val);-            JSAtom atom = rt->class_array[p->class_id].class_name;-            char atom_buf[ATOM_GET_STR_BUF_SIZE];-            printf("[%s %p]",-                   JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p);-        }-        break;-    case JS_TAG_SYMBOL:-        {-            JSAtomStruct *p = JS_VALUE_GET_PTR(val);-            char atom_buf[ATOM_GET_STR_BUF_SIZE];-            printf("Symbol(%s)",-                   JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p)));-        }-        break;-    case JS_TAG_MODULE:-        printf("[module]");-        break;-    default:-        printf("[unknown tag %d]", tag);-        break;-    }-}--static __maybe_unused void JS_DumpValue(JSContext *ctx,-                                                 JSValueConst val)-{-    JS_DumpValueShort(ctx->rt, val);-}--static __maybe_unused void JS_PrintValue(JSContext *ctx,-                                                  const char *str,-                                                  JSValueConst val)-{-    printf("%s=", str);-    JS_DumpValueShort(ctx->rt, val);-    printf("\n");-}--/* return -1 if exception (proxy case) or TRUE/FALSE */-int JS_IsArray(JSContext *ctx, JSValueConst val)-{-    JSObject *p;-    if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(val);-        if (unlikely(p->class_id == JS_CLASS_PROXY))-            return js_proxy_isArray(ctx, val);-        else-            return p->class_id == JS_CLASS_ARRAY;-    } else {-        return FALSE;-    }-}--static double js_pow(double a, double b)-{-    if (unlikely(!isfinite(b)) && fabs(a) == 1) {-        /* not compatible with IEEE 754 */-        return JS_FLOAT64_NAN;-    } else {-        return pow(a, b);-    }-}--#ifdef CONFIG_BIGNUM--JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)-{-    JSValue val;-    bf_t *a;-    val = JS_NewBigInt(ctx);-    if (JS_IsException(val))-        return val;-    a = JS_GetBigInt(val);-    if (bf_set_si(a, v)) {-        JS_FreeValue(ctx, val);-        return JS_ThrowOutOfMemory(ctx);-    }-    return val;-}--JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)-{-    if (is_math_mode(ctx) &&-        v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {-        return JS_NewInt64(ctx, v);-    } else {-        return JS_NewBigInt64_1(ctx, v);-    }-}--JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)-{-    JSValue val;-    if (is_math_mode(ctx) && v <= MAX_SAFE_INTEGER) {-        val = JS_NewInt64(ctx, v);-    } else {-        bf_t *a;-        val = JS_NewBigInt(ctx);-        if (JS_IsException(val))-            return val;-        a = JS_GetBigInt(val);-        if (bf_set_ui(a, v)) {-            JS_FreeValue(ctx, val);-            return JS_ThrowOutOfMemory(ctx);-        }-    }-    return val;-}--/* if the returned bigfloat is allocated it is equal to-   'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return-   NULL in case of error. */-static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)-{-    uint32_t tag;-    bf_t *r;-    JSBigFloat *p;--    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-        r = buf;-        bf_init(ctx->bf_ctx, r);-        if (bf_set_si(r, JS_VALUE_GET_INT(val)))-            goto fail;-        break;-    case JS_TAG_FLOAT64:-        r = buf;-        bf_init(ctx->bf_ctx, r);-        if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {-        fail:-            bf_delete(r);-            return NULL;-        }-        break;-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        p = JS_VALUE_GET_PTR(val);-        r = &p->num;-        break;-    case JS_TAG_UNDEFINED:-    default:-        r = buf;-        bf_init(ctx->bf_ctx, r);-        bf_set_nan(r);-        break;-    }-    return r;-}--/* return NULL if invalid type */-static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val)-{-    uint32_t tag;-    JSBigDecimal *p;-    bfdec_t *r;-    -    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_BIG_DECIMAL:-        p = JS_VALUE_GET_PTR(val);-        r = &p->num;-        break;-    default:-        JS_ThrowTypeError(ctx, "bigdecimal expected");-        r = NULL;-        break;-    }-    return r;-}--/* return NaN if bad bigint literal */-static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)-{-    const char *str, *p;-    size_t len;-    int flags;-    -    str = JS_ToCStringLen(ctx, &len, val);-    JS_FreeValue(ctx, val);-    if (!str)-        return JS_EXCEPTION;-    p = str;-    p += skip_spaces(p);-    if ((p - str) == len) {-        val = JS_NewBigInt64(ctx, 0);-    } else {-        flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;-        if (is_math_mode(ctx))-            flags |= ATOD_MODE_BIGINT;-        val = js_atof(ctx, p, &p, 0, flags);-        p += skip_spaces(p);-        if (!JS_IsException(val)) {-            if ((p - str) != len) {-                JS_FreeValue(ctx, val);-                val = JS_NAN;-            }-        }-    }-    JS_FreeCString(ctx, str);-    return val;-}--static JSValue JS_StringToBigIntErr(JSContext *ctx, JSValue val)-{-    val = JS_StringToBigInt(ctx, val);-    if (JS_VALUE_IS_NAN(val))-        return JS_ThrowSyntaxError(ctx, "invalid bigint literal");-    return val;-}--/* if the returned bigfloat is allocated it is equal to-   'buf'. Otherwise it is a pointer to the bigfloat in 'val'. */-static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)-{-    uint32_t tag;-    bf_t *r;-    JSBigFloat *p;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        if (!is_math_mode(ctx))-            goto fail;-        /* fall tru */-    case JS_TAG_BOOL:-        r = buf;-        bf_init(ctx->bf_ctx, r);-        bf_set_si(r, JS_VALUE_GET_INT(val));-        break;-    case JS_TAG_FLOAT64:-        {-            double d = JS_VALUE_GET_FLOAT64(val);-            if (!is_math_mode(ctx))-                goto fail;-            if (!isfinite(d))-                goto fail;-            r = buf;-            bf_init(ctx->bf_ctx, r);-            d = trunc(d);-            bf_set_float64(r, d);-        }-        break;-    case JS_TAG_BIG_INT:-        p = JS_VALUE_GET_PTR(val);-        r = &p->num;-        break;-    case JS_TAG_BIG_FLOAT:-        if (!is_math_mode(ctx))-            goto fail;-        p = JS_VALUE_GET_PTR(val);-        if (!bf_is_finite(&p->num))-            goto fail;-        r = buf;-        bf_init(ctx->bf_ctx, r);-        bf_set(r, &p->num);-        bf_rint(r, BF_RNDZ);-        JS_FreeValue(ctx, val);-        break;-    case JS_TAG_STRING:-        val = JS_StringToBigIntErr(ctx, val);-        if (JS_IsException(val))-            return NULL;-        goto redo;-    case JS_TAG_OBJECT:-        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);-        if (JS_IsException(val))-            return NULL;-        goto redo;-    default:-    fail:-        JS_FreeValue(ctx, val);-        JS_ThrowTypeError(ctx, "cannot convert to bigint");-        return NULL;-    }-    return r;-}--static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val)-{-    return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val));-}--static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val)-{-    if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) {-        return val;-    } else {-        bf_t a_s, *a, *r;-        int ret;-        JSValue res; --        res = JS_NewBigInt(ctx);-        if (JS_IsException(res))-            return JS_EXCEPTION;-        a = JS_ToBigIntFree(ctx, &a_s, val);-        if (!a) {-            JS_FreeValue(ctx, res);-            return JS_EXCEPTION;-        }-        r = JS_GetBigInt(res);-        ret = bf_set(r, a);-        JS_FreeBigInt(ctx, a, &a_s);-        if (ret) {-            JS_FreeValue(ctx, res);-            return JS_ThrowOutOfMemory(ctx);-        }-        return JS_CompactBigInt(ctx, res);-    }-}--/* free the bf_t allocated by JS_ToBigInt */-static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)-{-    if (a == buf) {-        bf_delete(a);-    } else {-        JSBigFloat *p = (JSBigFloat *)((uint8_t *)a --                                       offsetof(JSBigFloat, num));-        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_FLOAT, p));-    }-}--/* XXX: merge with JS_ToInt64Free with a specific flag */-static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val)-{-    bf_t a_s, *a;--    a = JS_ToBigIntFree(ctx, &a_s, val);-    if (!a) {-        *pres = 0;-        return -1;-    }-    bf_get_int64(pres, a, BF_GET_INT_MOD);-    JS_FreeBigInt(ctx, a, &a_s);-    return 0;-}--int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)-{-    return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val));-}--static JSBigFloat *js_new_bf(JSContext *ctx)-{-    JSBigFloat *p;-    p = js_malloc(ctx, sizeof(*p));-    if (!p)-        return NULL;-    p->header.ref_count = 1;-    bf_init(ctx->bf_ctx, &p->num);-    return p;-}--static JSValue JS_NewBigFloat(JSContext *ctx)-{-    JSBigFloat *p;-    p = js_malloc(ctx, sizeof(*p));-    if (!p)-        return JS_EXCEPTION;-    p->header.ref_count = 1;-    bf_init(ctx->bf_ctx, &p->num);-    return JS_MKPTR(JS_TAG_BIG_FLOAT, p);-}--static JSValue JS_NewBigDecimal(JSContext *ctx)-{-    JSBigDecimal *p;-    p = js_malloc(ctx, sizeof(*p));-    if (!p)-        return JS_EXCEPTION;-    p->header.ref_count = 1;-    bfdec_init(ctx->bf_ctx, &p->num);-    return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);-}--static JSValue JS_NewBigInt(JSContext *ctx)-{-    JSBigFloat *p;-    p = js_malloc(ctx, sizeof(*p));-    if (!p)-        return JS_EXCEPTION;-    p->header.ref_count = 1;-    bf_init(ctx->bf_ctx, &p->num);-    return JS_MKPTR(JS_TAG_BIG_INT, p);-}--static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,-                                 BOOL convert_to_safe_integer)-{-    int64_t v;-    bf_t *a;-    -    if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)-        return val; /* fail safe */-    a = JS_GetBigInt(val);-    if (convert_to_safe_integer && bf_get_int64(&v, a, 0) == 0 &&-        v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {-        JS_FreeValue(ctx, val);-        return JS_NewInt64(ctx, v);-    } else if (a->expn == BF_EXP_ZERO && a->sign) {-        JSBigFloat *p = JS_VALUE_GET_PTR(val);-        assert(p->header.ref_count == 1);-        a->sign = 0;-    }-    return val;-}--/* Convert the big int to a safe integer if in math mode. normalize-   the zero representation. Could also be used to convert the bigint-   to a short bigint value. The reference count of the value must be-   1. Cannot fail */-static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)-{-    return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));-}--/* must be kept in sync with JSOverloadableOperatorEnum */-/* XXX: use atoms ? */-static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {-    "+",-    "-",-    "*",-    "/",-    "%",-    "**",-    "|",-    "&",-    "^",-    "<<",-    ">>",-    ">>>",-    "==",-    "<",-    "pos",-    "neg",-    "++",-    "--",-    "~",-};--static int get_ovop_from_opcode(OPCodeEnum op)-{-    switch(op) {-    case OP_add:-        return JS_OVOP_ADD;-    case OP_sub:-        return JS_OVOP_SUB;-    case OP_mul:-        return JS_OVOP_MUL;-    case OP_div:-        return JS_OVOP_DIV;-    case OP_mod:-    case OP_math_mod:-        return JS_OVOP_MOD;-    case OP_pow:-        return JS_OVOP_POW;-    case OP_or:-        return JS_OVOP_OR;-    case OP_and:-        return JS_OVOP_AND;-    case OP_xor:-        return JS_OVOP_XOR;-    case OP_shl:-        return JS_OVOP_SHL;-    case OP_sar:-        return JS_OVOP_SAR;-    case OP_shr:-        return JS_OVOP_SHR;-    case OP_eq:-    case OP_neq:-        return JS_OVOP_EQ;-    case OP_lt:-    case OP_lte:-    case OP_gt:-    case OP_gte:-        return JS_OVOP_LESS;-    case OP_plus:-        return JS_OVOP_POS;-    case OP_neg:-        return JS_OVOP_NEG;-    case OP_inc:-        return JS_OVOP_INC;-    case OP_dec:-        return JS_OVOP_DEC;-    default:-        abort();-    }-}--/* return NULL if not present */-static JSObject *find_binary_op(JSBinaryOperatorDef *def,-                                uint32_t operator_index,-                                JSOverloadableOperatorEnum op)-{-    JSBinaryOperatorDefEntry *ent;-    int i;-    for(i = 0; i < def->count; i++) {-        ent = &def->tab[i];-        if (ent->operator_index == operator_index)-            return ent->ops[op];-    }-    return NULL;-}--/* return -1 if exception, 0 if no operator overloading, 1 if-   overloaded operator called */-static __exception int js_call_binary_op_fallback(JSContext *ctx,-                                                  JSValue *pret,-                                                  JSValueConst op1,-                                                  JSValueConst op2,-                                                  OPCodeEnum op,-                                                  BOOL is_numeric,-                                                  int hint)-{-    JSValue opset1_obj, opset2_obj, method, ret, new_op1, new_op2;-    JSOperatorSetData *opset1, *opset2;-    JSOverloadableOperatorEnum ovop;-    JSObject *p;-    JSValueConst args[2];-    -    if (!ctx->allow_operator_overloading)-        return 0;-    -    opset2_obj = JS_UNDEFINED;-    opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);-    if (JS_IsException(opset1_obj))-        goto exception;-    if (JS_IsUndefined(opset1_obj))-        return 0;-    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);-    if (!opset1)-        goto exception;--    opset2_obj = JS_GetProperty(ctx, op2, JS_ATOM_Symbol_operatorSet);-    if (JS_IsException(opset2_obj))-        goto exception;-    if (JS_IsUndefined(opset2_obj)) {-        JS_FreeValue(ctx, opset1_obj);-        return 0;-    }-    opset2 = JS_GetOpaque2(ctx, opset2_obj, JS_CLASS_OPERATOR_SET);-    if (!opset2)-        goto exception;--    if (opset1->is_primitive && opset2->is_primitive) {-        JS_FreeValue(ctx, opset1_obj);-        JS_FreeValue(ctx, opset2_obj);-        return 0;-    }--    ovop = get_ovop_from_opcode(op);-    -    if (opset1->operator_counter == opset2->operator_counter) {-        p = opset1->self_ops[ovop];-    } else if (opset1->operator_counter > opset2->operator_counter) {-        p = find_binary_op(&opset1->left, opset2->operator_counter, ovop);-    } else {-        p = find_binary_op(&opset2->right, opset1->operator_counter, ovop);-    }-    if (!p) {-        JS_ThrowTypeError(ctx, "operator %s: no function defined",-                          js_overloadable_operator_names[ovop]);-        goto exception;-    }--    if (opset1->is_primitive) {-        if (is_numeric) {-            new_op1 = JS_ToNumeric(ctx, op1);-        } else {-            new_op1 = JS_ToPrimitive(ctx, op1, hint);-        }-        if (JS_IsException(new_op1))-            goto exception;-    } else {-        new_op1 = JS_DupValue(ctx, op1);-    }-    -    if (opset2->is_primitive) {-        if (is_numeric) {-            new_op2 = JS_ToNumeric(ctx, op2);-        } else {-            new_op2 = JS_ToPrimitive(ctx, op2, hint);-        }-        if (JS_IsException(new_op2)) {-            JS_FreeValue(ctx, new_op1);-            goto exception;-        }-    } else {-        new_op2 = JS_DupValue(ctx, op2);-    }--    /* XXX: could apply JS_ToPrimitive() if primitive type so that the-       operator function does not get a value object */-    -    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-    if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) {-        args[0] = new_op2;-        args[1] = new_op1;-    } else {-        args[0] = new_op1;-        args[1] = new_op2;-    }-    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);-    JS_FreeValue(ctx, new_op1);-    JS_FreeValue(ctx, new_op2);-    if (JS_IsException(ret))-        goto exception;-    if (ovop == JS_OVOP_EQ) {-        BOOL res = JS_ToBoolFree(ctx, ret);-        if (op == OP_neq)-            res ^= 1;-        ret = JS_NewBool(ctx, res);-    } else if (ovop == JS_OVOP_LESS) {-        if (JS_IsUndefined(ret)) {-            ret = JS_FALSE;-        } else {-            BOOL res = JS_ToBoolFree(ctx, ret);-            if (op == OP_lte || op == OP_gte)-                res ^= 1;-            ret = JS_NewBool(ctx, res);-        }-    }-    JS_FreeValue(ctx, opset1_obj);-    JS_FreeValue(ctx, opset2_obj);-    *pret = ret;-    return 1;- exception:-    JS_FreeValue(ctx, opset1_obj);-    JS_FreeValue(ctx, opset2_obj);-    *pret = JS_UNDEFINED;-    return -1;-}--/* try to call the operation on the operatorSet field of 'obj'. Only-   used for "/" and "**" on the BigInt prototype in math mode */-static __exception int js_call_binary_op_simple(JSContext *ctx,-                                                JSValue *pret,-                                                JSValueConst obj,-                                                JSValueConst op1,-                                                JSValueConst op2,-                                                OPCodeEnum op)-{-    JSValue opset1_obj, method, ret, new_op1, new_op2;-    JSOperatorSetData *opset1;-    JSOverloadableOperatorEnum ovop;-    JSObject *p;-    JSValueConst args[2];--    opset1_obj = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);-    if (JS_IsException(opset1_obj))-        goto exception;-    if (JS_IsUndefined(opset1_obj))-        return 0;-    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);-    if (!opset1)-        goto exception;-    ovop = get_ovop_from_opcode(op);--    p = opset1->self_ops[ovop];-    if (!p) {-        JS_FreeValue(ctx, opset1_obj);-        return 0;-    }--    new_op1 = JS_ToNumeric(ctx, op1);-    if (JS_IsException(new_op1))-        goto exception;-    new_op2 = JS_ToNumeric(ctx, op2);-    if (JS_IsException(new_op2)) {-        JS_FreeValue(ctx, new_op1);-        goto exception;-    }--    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-    args[0] = new_op1;-    args[1] = new_op2;-    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);-    JS_FreeValue(ctx, new_op1);-    JS_FreeValue(ctx, new_op2);-    if (JS_IsException(ret))-        goto exception;-    JS_FreeValue(ctx, opset1_obj);-    *pret = ret;-    return 1;- exception:-    JS_FreeValue(ctx, opset1_obj);-    *pret = JS_UNDEFINED;-    return -1;-}--/* return -1 if exception, 0 if no operator overloading, 1 if-   overloaded operator called */-static __exception int js_call_unary_op_fallback(JSContext *ctx,-                                                 JSValue *pret,-                                                 JSValueConst op1,-                                                 OPCodeEnum op)-{-    JSValue opset1_obj, method, ret;-    JSOperatorSetData *opset1;-    JSOverloadableOperatorEnum ovop;-    JSObject *p;--    if (!ctx->allow_operator_overloading)-        return 0;-    -    opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);-    if (JS_IsException(opset1_obj))-        goto exception;-    if (JS_IsUndefined(opset1_obj))-        return 0;-    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);-    if (!opset1)-        goto exception;-    if (opset1->is_primitive) {-        JS_FreeValue(ctx, opset1_obj);-        return 0;-    }--    ovop = get_ovop_from_opcode(op);--    p = opset1->self_ops[ovop];-    if (!p) {-        JS_ThrowTypeError(ctx, "no overloaded operator %s",-                          js_overloadable_operator_names[ovop]);-        goto exception;-    }-    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));-    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 1, &op1);-    if (JS_IsException(ret))-        goto exception;-    JS_FreeValue(ctx, opset1_obj);-    *pret = ret;-    return 1;- exception:-    JS_FreeValue(ctx, opset1_obj);-    *pret = JS_UNDEFINED;-    return -1;-}--static JSValue throw_bf_exception(JSContext *ctx, int status)-{-    const char *str;-    if (status & BF_ST_MEM_ERROR)-        return JS_ThrowOutOfMemory(ctx);-    if (status & BF_ST_DIVIDE_ZERO) {-        str = "division by zero";-    } else if (status & BF_ST_INVALID_OP) {-        str = "invalid operation";-    } else {-        str = "integer overflow";-    }-    return JS_ThrowRangeError(ctx, "%s", str);-}--static int js_unary_arith_bigint(JSContext *ctx,-                                 JSValue *pres, OPCodeEnum op, JSValue op1)-{-    bf_t a_s, *r, *a;-    int ret, v;-    JSValue res;-    -    if (op == OP_plus && !is_math_mode(ctx)) {-        JS_ThrowTypeError(ctx, "bigint argument with unary +");-        JS_FreeValue(ctx, op1);-        return -1;-    }-    res = JS_NewBigInt(ctx);-    if (JS_IsException(res)) {-        JS_FreeValue(ctx, op1);-        return -1;-    }-    r = JS_GetBigInt(res);-    a = JS_ToBigInt(ctx, &a_s, op1);-    ret = 0;-    switch(op) {-    case OP_inc:-    case OP_dec:-        v = 2 * (op - OP_dec) - 1;-        ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_plus:-        ret = bf_set(r, a);-        break;-    case OP_neg:-        ret = bf_set(r, a);-        bf_neg(r);-        break;-    case OP_not:-        ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);-        bf_neg(r);-        break;-    default:-        abort();-    }-    JS_FreeBigInt(ctx, a, &a_s);-    JS_FreeValue(ctx, op1);-    if (unlikely(ret)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    res = JS_CompactBigInt(ctx, res);-    *pres = res;-    return 0;-}--static int js_unary_arith_bigfloat(JSContext *ctx,-                                   JSValue *pres, OPCodeEnum op, JSValue op1)-{-    bf_t a_s, *r, *a;-    int ret, v;-    JSValue res;-    -    if (op == OP_plus && !is_math_mode(ctx)) {-        JS_ThrowTypeError(ctx, "bigfloat argument with unary +");-        JS_FreeValue(ctx, op1);-        return -1;-    }--    res = JS_NewBigFloat(ctx);-    if (JS_IsException(res)) {-        JS_FreeValue(ctx, op1);-        return -1;-    }-    r = JS_GetBigFloat(res);-    a = JS_ToBigFloat(ctx, &a_s, op1);-    ret = 0;-    switch(op) {-    case OP_inc:-    case OP_dec:-        v = 2 * (op - OP_dec) - 1;-        ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case OP_plus:-        ret = bf_set(r, a);-        break;-    case OP_neg:-        ret = bf_set(r, a);-        bf_neg(r);-        break;-    default:-        abort();-    }-    if (a == &a_s)-        bf_delete(a);-    JS_FreeValue(ctx, op1);-    if (unlikely(ret & BF_ST_MEM_ERROR)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    *pres = res;-    return 0;-}--static int js_unary_arith_bigdecimal(JSContext *ctx,-                                     JSValue *pres, OPCodeEnum op, JSValue op1)-{-    bfdec_t *r, *a;-    int ret, v;-    JSValue res;-    -    if (op == OP_plus && !is_math_mode(ctx)) {-        JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");-        JS_FreeValue(ctx, op1);-        return -1;-    }--    res = JS_NewBigDecimal(ctx);-    if (JS_IsException(res)) {-        JS_FreeValue(ctx, op1);-        return -1;-    }-    r = JS_GetBigDecimal(res);-    a = JS_ToBigDecimal(ctx, op1);-    ret = 0;-    switch(op) {-    case OP_inc:-    case OP_dec:-        v = 2 * (op - OP_dec) - 1;-        ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_plus:-        ret = bfdec_set(r, a);-        break;-    case OP_neg:-        ret = bfdec_set(r, a);-        bfdec_neg(r);-        break;-    default:-        abort();-    }-    JS_FreeValue(ctx, op1);-    if (unlikely(ret)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    *pres = res;-    return 0;-}--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,-                                                     JSValue *sp,-                                                     OPCodeEnum op)-{-    JSValue op1, val;-    int v, ret;-    uint32_t tag;--    op1 = sp[-1];-    /* fast path for float64 */-    if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)))-        goto handle_float64;-    if (JS_IsObject(op1)) {-        ret = js_call_unary_op_fallback(ctx, &val, op1, op);-        if (ret < 0)-            return -1;-        if (ret) {-            JS_FreeValue(ctx, op1);-            sp[-1] = val;-            return 0;-        }-    }--    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1))-        goto exception;-    tag = JS_VALUE_GET_TAG(op1);-    switch(tag) {-    case JS_TAG_INT:-        {-            int64_t v64;-            v64 = JS_VALUE_GET_INT(op1);-            switch(op) {-            case OP_inc:-            case OP_dec:-                v = 2 * (op - OP_dec) - 1;-                v64 += v;-                break;-            case OP_plus:-                break;-            case OP_neg:-                if (v64 == 0) {-                    sp[-1] = __JS_NewFloat64(ctx, -0.0);-                    return 0;-                } else {-                    v64 = -v64;-                }-                break;-            default:-                abort();-            }-            sp[-1] = JS_NewInt64(ctx, v64);-        }-        break;-    case JS_TAG_BIG_INT:-    handle_bigint:-        if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))-            goto exception;-        break;-    case JS_TAG_BIG_FLOAT:-        if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1))-            goto exception;-        break;-    case JS_TAG_BIG_DECIMAL:-        if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))-            goto exception;-        break;-    default:-    handle_float64:-        {-            double d;-            if (is_math_mode(ctx))-                goto handle_bigint;-            d = JS_VALUE_GET_FLOAT64(op1);-            switch(op) {-            case OP_inc:-            case OP_dec:-                v = 2 * (op - OP_dec) - 1;-                d += v;-                break;-            case OP_plus:-                break;-            case OP_neg:-                d = -d;-                break;-            default:-                abort();-            }-            sp[-1] = __JS_NewFloat64(ctx, d);-        }-        break;-    }-    return 0;- exception:-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static __exception int js_post_inc_slow(JSContext *ctx,-                                        JSValue *sp, OPCodeEnum op)-{-    JSValue op1;--    /* XXX: allow custom operators */-    op1 = sp[-1];-    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1)) {-        sp[-1] = JS_UNDEFINED;-        return -1;-    }-    sp[-1] = op1;-    sp[0] = JS_DupValue(ctx, op1);-    return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec);-}--static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)-{-    JSValue op1, val;-    int ret;-    -    op1 = sp[-1];-    if (JS_IsObject(op1)) {-        ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);-        if (ret < 0)-            return -1;-        if (ret) {-            JS_FreeValue(ctx, op1);-            sp[-1] = val;-            return 0;-        }-    }--    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1))-        goto exception;-    if (is_math_mode(ctx) || JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {-        if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1))-            goto exception;-    } else {-        int32_t v1;-        if (unlikely(JS_ToInt32Free(ctx, &v1, op1)))-            goto exception;-        sp[-1] = JS_NewInt32(ctx, ~v1);-    }-    return 0;- exception:-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,-                                    JSValue *pres, JSValue op1, JSValue op2)-{-    bf_t a_s, b_s, *r, *a, *b;-    int ret;-    JSValue res;-    -    res = JS_NewBigFloat(ctx);-    if (JS_IsException(res)) {-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-        return -1;-    }-    r = JS_GetBigFloat(res);-    a = JS_ToBigFloat(ctx, &a_s, op1);-    b = JS_ToBigFloat(ctx, &b_s, op2);-    bf_init(ctx->bf_ctx, r);-    switch(op) {-    case OP_add:-        ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case OP_sub:-        ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case OP_mul:-        ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case OP_div:-        ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case OP_math_mod:-        /* Euclidian remainder */-        ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,-                     BF_DIVREM_EUCLIDIAN);-        break;-    case OP_mod:-        ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,-                     BF_RNDZ);-        break;-    case OP_pow:-        ret = bf_pow(r, a, b, ctx->fp_env.prec,-                     ctx->fp_env.flags | BF_POW_JS_QUIRKS);-        break;-    default:-        abort();-    }-    if (a == &a_s)-        bf_delete(a);-    if (b == &b_s)-        bf_delete(b);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    if (unlikely(ret & BF_ST_MEM_ERROR)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    *pres = res;-    return 0;-}--static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,-                                  JSValue *pres, JSValue op1, JSValue op2)-{-    bf_t a_s, b_s, *r, *a, *b;-    int ret;-    JSValue res;-    -    res = JS_NewBigInt(ctx);-    if (JS_IsException(res))-        goto fail;-    a = JS_ToBigInt(ctx, &a_s, op1);-    if (!a)-        goto fail;-    b = JS_ToBigInt(ctx, &b_s, op2);-    if (!b) {-        JS_FreeBigInt(ctx, a, &a_s);-        goto fail;-    }-    r = JS_GetBigInt(res);-    ret = 0;-    switch(op) {-    case OP_add:-        ret = bf_add(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_sub:-        ret = bf_sub(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_mul:-        ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_div:-        if (!is_math_mode(ctx)) {-            bf_t rem_s, *rem = &rem_s;-            bf_init(ctx->bf_ctx, rem);-            ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ,-                            BF_RNDZ);-            bf_delete(rem);-        } else {-            goto math_mode_div_pow;-        }-        break;-    case OP_math_mod:-        /* Euclidian remainder */-        ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,-                     BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;-        break;-    case OP_mod:-        ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,-                     BF_RNDZ) & BF_ST_INVALID_OP;-        break;-    case OP_pow:-        if (b->sign) {-            if (!is_math_mode(ctx)) {-                ret = BF_ST_INVALID_OP;-            } else {-            math_mode_div_pow:-                JS_FreeValue(ctx, res);-                ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);-                if (ret != 0) {-                    JS_FreeBigInt(ctx, a, &a_s);-                    JS_FreeBigInt(ctx, b, &b_s);-                    JS_FreeValue(ctx, op1);-                    JS_FreeValue(ctx, op2);-                    if (ret < 0) {-                        return -1;-                    } else {-                        *pres = res;-                        return 0;-                    }-                }-                /* if no BigInt power operator defined, return a-                   bigfloat */-                res = JS_NewBigFloat(ctx);-                if (JS_IsException(res)) {-                    JS_FreeBigInt(ctx, a, &a_s);-                    JS_FreeBigInt(ctx, b, &b_s);-                    goto fail;-                }-                r = JS_GetBigFloat(res);-                if (op == OP_div) {-                    ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags) & BF_ST_MEM_ERROR;-                } else {-                    ret = bf_pow(r, a, b, ctx->fp_env.prec,-                                 ctx->fp_env.flags | BF_POW_JS_QUIRKS) & BF_ST_MEM_ERROR;-                }-                JS_FreeBigInt(ctx, a, &a_s);-                JS_FreeBigInt(ctx, b, &b_s);-                JS_FreeValue(ctx, op1);-                JS_FreeValue(ctx, op2);-                if (unlikely(ret)) {-                    JS_FreeValue(ctx, res);-                    throw_bf_exception(ctx, ret);-                    return -1;-                }-                *pres = res;-                return 0;-            }-        } else {-            ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);-        }-        break;--        /* logical operations */-    case OP_shl:-    case OP_sar:-        {-            slimb_t v2;-#if LIMB_BITS == 32-            bf_get_int32(&v2, b, 0);-            if (v2 == INT32_MIN)-                v2 = INT32_MIN + 1;-#else-            bf_get_int64(&v2, b, 0);-            if (v2 == INT64_MIN)-                v2 = INT64_MIN + 1;-#endif-            if (op == OP_sar)-                v2 = -v2;-            ret = bf_set(r, a);-            ret |= bf_mul_2exp(r, v2, BF_PREC_INF, BF_RNDZ);-            if (v2 < 0) {-                ret |= bf_rint(r, BF_RNDD) & (BF_ST_OVERFLOW | BF_ST_MEM_ERROR);-            }-        }-        break;-    case OP_and:-        ret = bf_logic_and(r, a, b);-        break;-    case OP_or:-        ret = bf_logic_or(r, a, b);-        break;-    case OP_xor:-        ret = bf_logic_xor(r, a, b);-        break;-    default:-        abort();-    }-    JS_FreeBigInt(ctx, a, &a_s);-    JS_FreeBigInt(ctx, b, &b_s);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    if (unlikely(ret)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    *pres = JS_CompactBigInt(ctx, res);-    return 0;- fail:-    JS_FreeValue(ctx, res);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return -1;-}--/* b must be a positive integer */-static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b)-{-    bfdec_t b1;-    int32_t b2;-    int ret;--    bfdec_init(b->ctx, &b1);-    ret = bfdec_set(&b1, b);-    if (ret) {-        bfdec_delete(&b1);-        return ret;-    }-    ret = bfdec_rint(&b1, BF_RNDZ);-    if (ret) {-        bfdec_delete(&b1);-        return BF_ST_INVALID_OP; /* must be an integer */-    }-    ret = bfdec_get_int32(&b2, &b1);-    bfdec_delete(&b1);-    if (ret)-        return ret; /* overflow */-    if (b2 < 0)-        return BF_ST_INVALID_OP; /* must be positive */-    return bfdec_pow_ui(r, a, b2);-}--static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,-                                      JSValue *pres, JSValue op1, JSValue op2)-{-    bfdec_t *r, *a, *b;-    int ret;-    JSValue res;--    res = JS_NewBigDecimal(ctx);-    if (JS_IsException(res))-        goto fail;-    r = JS_GetBigDecimal(res);-    -    a = JS_ToBigDecimal(ctx, op1);-    if (!a)-        goto fail;-    b = JS_ToBigDecimal(ctx, op2);-    if (!b)-        goto fail;-    switch(op) {-    case OP_add:-        ret = bfdec_add(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_sub:-        ret = bfdec_sub(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_mul:-        ret = bfdec_mul(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_div:-        ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ);-        break;-    case OP_math_mod:-        /* Euclidian remainder */-        ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_DIVREM_EUCLIDIAN);-        break;-    case OP_mod:-        ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);-        break;-    case OP_pow:-        ret = js_bfdec_pow(r, a, b);-        break;-    default:-        abort();-    }-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    if (unlikely(ret)) {-        JS_FreeValue(ctx, res);-        throw_bf_exception(ctx, ret);-        return -1;-    }-    *pres = res;-    return 0;- fail:-    JS_FreeValue(ctx, res);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return -1;-}--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,-                                                      OPCodeEnum op)-{-    JSValue op1, op2, res;-    uint32_t tag1, tag2;-    int ret;-    double d1, d2;--    op1 = sp[-2];-    op2 = sp[-1];-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    /* fast path for float operations */-    if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) {-        d1 = JS_VALUE_GET_FLOAT64(op1);-        d2 = JS_VALUE_GET_FLOAT64(op2);-        goto handle_float64;-    }--    /* try to call an overloaded operator */-    if ((tag1 == JS_TAG_OBJECT &&-         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||-        (tag2 == JS_TAG_OBJECT &&-         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {-        ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);-        if (ret != 0) {-            JS_FreeValue(ctx, op1);-            JS_FreeValue(ctx, op2);-            if (ret < 0) {-                goto exception;-            } else {-                sp[-2] = res;-                return 0;-            }-        }-    }--    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToNumericFree(ctx, op2);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);--    if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {-        int32_t v1, v2;-        int64_t v;-        v1 = JS_VALUE_GET_INT(op1);-        v2 = JS_VALUE_GET_INT(op2);-        switch(op) {-        case OP_sub:-            v = (int64_t)v1 - (int64_t)v2;-            break;-        case OP_mul:-            v = (int64_t)v1 * (int64_t)v2;-            if (is_math_mode(ctx) &&-                (v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))-                goto handle_bigint;-            if (v == 0 && (v1 | v2) < 0) {-                sp[-2] = __JS_NewFloat64(ctx, -0.0);-                return 0;-            }-            break;-        case OP_div:-            if (is_math_mode(ctx))-                goto handle_bigint;-            sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);-            return 0;-        case OP_math_mod:-            if (unlikely(v2 == 0)) {-                throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);-                goto exception;-            }-            v = (int64_t)v1 % (int64_t)v2;-            if (v < 0) {-                if (v2 < 0)-                    v -= v2;-                else-                    v += v2;-            }-            break;-        case OP_mod:-            if (v1 < 0 || v2 <= 0) {-                sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));-                return 0;-            } else {-                v = (int64_t)v1 % (int64_t)v2;-            }-            break;-        case OP_pow:-            if (!is_math_mode(ctx)) {-                sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2));-                return 0;-            } else {-                goto handle_bigint;-            }-            break;-        default:-            abort();-        }-        sp[-2] = JS_NewInt64(ctx, v);-    } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {-        if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2))-            goto exception;-    } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {-        if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))-            goto exception;-    } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {-    handle_bigint:-        if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))-            goto exception;-    } else {-        double dr;-        /* float64 result */-        if (JS_ToFloat64Free(ctx, &d1, op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        if (JS_ToFloat64Free(ctx, &d2, op2))-            goto exception;-    handle_float64:-        if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))-            goto handle_bigint;-        switch(op) {-        case OP_sub:-            dr = d1 - d2;-            break;-        case OP_mul:-            dr = d1 * d2;-            break;-        case OP_div:-            dr = d1 / d2;-            break;-        case OP_mod:-            dr = fmod(d1, d2);-            break;-        case OP_math_mod:-            d2 = fabs(d2);-            dr = fmod(d1, d2);-            /* XXX: loss of accuracy if dr < 0 */-            if (dr < 0)-                dr += d2;-            break;-        case OP_pow:-            dr = js_pow(d1, d2);-            break;-        default:-            abort();-        }-        sp[-2] = __JS_NewFloat64(ctx, dr);-    }-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2, res;-    uint32_t tag1, tag2;-    int ret;--    op1 = sp[-2];-    op2 = sp[-1];--    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    /* fast path for float64 */-    if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) {-        double d1, d2;-        d1 = JS_VALUE_GET_FLOAT64(op1);-        d2 = JS_VALUE_GET_FLOAT64(op2);-        sp[-2] = __JS_NewFloat64(ctx, d1 + d2);-        return 0;-    }--    if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) {-        /* try to call an overloaded operator */-        if ((tag1 == JS_TAG_OBJECT &&-             (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED &&-              tag2 != JS_TAG_STRING)) ||-            (tag2 == JS_TAG_OBJECT &&-             (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED &&-              tag1 != JS_TAG_STRING))) {-            ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,-                                             FALSE, HINT_NONE);-            if (ret != 0) {-                JS_FreeValue(ctx, op1);-                JS_FreeValue(ctx, op2);-                if (ret < 0) {-                    goto exception;-                } else {-                    sp[-2] = res;-                    return 0;-                }-            }-        }--        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);-        if (JS_IsException(op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }--        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            goto exception;-        }-        tag1 = JS_VALUE_GET_NORM_TAG(op1);-        tag2 = JS_VALUE_GET_NORM_TAG(op2);-    }--    if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {-        sp[-2] = JS_ConcatString(ctx, op1, op2);-        if (JS_IsException(sp[-2]))-            goto exception;-        return 0;-    }--    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToNumericFree(ctx, op2);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);--    if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {-        int32_t v1, v2;-        int64_t v;-        v1 = JS_VALUE_GET_INT(op1);-        v2 = JS_VALUE_GET_INT(op2);-        v = (int64_t)v1 + (int64_t)v2;-        sp[-2] = JS_NewInt64(ctx, v);-    } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {-        if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))-            goto exception;-    } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {-        if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))-            goto exception;-    } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {-    handle_bigint:-        if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))-            goto exception;-    } else {-        double d1, d2;-        /* float64 result */-        if (JS_ToFloat64Free(ctx, &d1, op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        if (JS_ToFloat64Free(ctx, &d2, op2))-            goto exception;-        if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))-            goto handle_bigint;-        sp[-2] = __JS_NewFloat64(ctx, d1 + d2);-    }-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,-                                                      JSValue *sp,-                                                      OPCodeEnum op)-{-    JSValue op1, op2, res;-    int ret;-    uint32_t tag1, tag2;-    uint32_t v1, v2, r;--    op1 = sp[-2];-    op2 = sp[-1];-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);--    /* try to call an overloaded operator */-    if ((tag1 == JS_TAG_OBJECT &&-         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||-        (tag2 == JS_TAG_OBJECT &&-         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {-        ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);-        if (ret != 0) {-            JS_FreeValue(ctx, op1);-            JS_FreeValue(ctx, op2);-            if (ret < 0) {-                goto exception;-            } else {-                sp[-2] = res;-                return 0;-            }-        }-    }--    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToNumericFree(ctx, op2);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }--    if (is_math_mode(ctx))-        goto bigint_op;--    tag1 = JS_VALUE_GET_TAG(op1);-    tag2 = JS_VALUE_GET_TAG(op2);-    if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {-        if (tag1 != tag2) {-            JS_FreeValue(ctx, op1);-            JS_FreeValue(ctx, op2);-            JS_ThrowTypeError(ctx, "both operands must be bigint");-            goto exception;-        } else {-        bigint_op:-            if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))-                goto exception;-        }-    } else {-        if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))-            goto exception;-        switch(op) {-        case OP_shl:-            r = v1 << (v2 & 0x1f);-            break;-        case OP_sar:-            r = (int)v1 >> (v2 & 0x1f);-            break;-        case OP_and:-            r = v1 & v2;-            break;-        case OP_or:-            r = v1 | v2;-            break;-        case OP_xor:-            r = v1 ^ v2;-            break;-        default:-            abort();-        }-        sp[-2] = JS_NewInt32(ctx, r);-    }-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--/* Note: also used for bigint */-static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,-                               JSValue op1, JSValue op2)-{-    bf_t a_s, b_s, *a, *b;-    int res;-    -    a = JS_ToBigFloat(ctx, &a_s, op1);-    if (!a) {-        JS_FreeValue(ctx, op2);-        return -1;-    }-    b = JS_ToBigFloat(ctx, &b_s, op2);-    if (!b) {-        if (a == &a_s)-            bf_delete(a);-        JS_FreeValue(ctx, op1);-        return -1;-    }-    switch(op) {-    case OP_lt:-        res = bf_cmp_lt(a, b); /* if NaN return false */-        break;-    case OP_lte:-        res = bf_cmp_le(a, b); /* if NaN return false */-        break;-    case OP_gt:-        res = bf_cmp_lt(b, a); /* if NaN return false */-        break;-    case OP_gte:-        res = bf_cmp_le(b, a); /* if NaN return false */-        break;-    case OP_eq:-        res = bf_cmp_eq(a, b); /* if NaN return false */-        break;-    default:-        abort();-    }-    if (a == &a_s)-        bf_delete(a);-    if (b == &b_s)-        bf_delete(b);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return res;-}--static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,-                                 JSValue op1, JSValue op2)-{-    bfdec_t *a, *b;-    int res;--    /* Note: binary floats are converted to bigdecimal with-       toString(). It is not mathematically correct but is consistent-       with the BigDecimal() constructor behavior */-    op1 = JS_ToBigDecimalFree(ctx, op1, TRUE);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        return -1;-    }-    op2 = JS_ToBigDecimalFree(ctx, op2, TRUE);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        return -1;-    }-    a = JS_ToBigDecimal(ctx, op1);-    b = JS_ToBigDecimal(ctx, op2);-    -    switch(op) {-    case OP_lt:-        res = bfdec_cmp_lt(a, b); /* if NaN return false */-        break;-    case OP_lte:-        res = bfdec_cmp_le(a, b); /* if NaN return false */-        break;-    case OP_gt:-        res = bfdec_cmp_lt(b, a); /* if NaN return false */-        break;-    case OP_gte:-        res = bfdec_cmp_le(b, a); /* if NaN return false */-        break;-    case OP_eq:-        res = bfdec_cmp_eq(a, b); /* if NaN return false */-        break;-    default:-        abort();-    }-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return res;-}--static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,-                                        OPCodeEnum op)-{-    JSValue op1, op2, ret;-    int res;-    uint32_t tag1, tag2;--    op1 = sp[-2];-    op2 = sp[-1];-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    /* try to call an overloaded operator */-    if ((tag1 == JS_TAG_OBJECT &&-         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||-        (tag2 == JS_TAG_OBJECT &&-         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {-        res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op,-                                         FALSE, HINT_NUMBER);-        if (res != 0) {-            JS_FreeValue(ctx, op1);-            JS_FreeValue(ctx, op2);-            if (res < 0) {-                goto exception;-            } else {-                sp[-2] = ret;-                return 0;-            }-        }-    }-    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);--    if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) {-        JSString *p1, *p2;-        p1 = JS_VALUE_GET_STRING(op1);-        p2 = JS_VALUE_GET_STRING(op2);-        res = js_string_compare(ctx, p1, p2);-        switch(op) {-        case OP_lt:-            res = (res < 0);-            break;-        case OP_lte:-            res = (res <= 0);-            break;-        case OP_gt:-            res = (res > 0);-            break;-        default:-        case OP_gte:-            res = (res >= 0);-            break;-        }-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-    } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) &&-               (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) {-        /* fast path for float64/int */-        goto float64_compare;-    } else {-        if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||-             (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&-            !is_math_mode(ctx)) {-            if (tag1 == JS_TAG_STRING) {-                op1 = JS_StringToBigInt(ctx, op1);-                if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)-                    goto invalid_bigint_string;-            }-            if (tag2 == JS_TAG_STRING) {-                op2 = JS_StringToBigInt(ctx, op2);-                if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT) {-                invalid_bigint_string:-                    JS_FreeValue(ctx, op1);-                    JS_FreeValue(ctx, op2);-                    res = FALSE;-                    goto done;-                }-            }-        } else {-            op1 = JS_ToNumericFree(ctx, op1);-            if (JS_IsException(op1)) {-                JS_FreeValue(ctx, op2);-                goto exception;-            }-            op2 = JS_ToNumericFree(ctx, op2);-            if (JS_IsException(op2)) {-                JS_FreeValue(ctx, op1);-                goto exception;-            }-        }--        tag1 = JS_VALUE_GET_NORM_TAG(op1);-        tag2 = JS_VALUE_GET_NORM_TAG(op2);--        if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {-            res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);-            if (res < 0)-                goto exception;-        } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {-            res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);-            if (res < 0)-                goto exception;-        } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {-            res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);-            if (res < 0)-                goto exception;-        } else {-            double d1, d2;--        float64_compare:-            /* can use floating point comparison */-            if (tag1 == JS_TAG_FLOAT64) {-                d1 = JS_VALUE_GET_FLOAT64(op1);-            } else {-                d1 = JS_VALUE_GET_INT(op1);-            }-            if (tag2 == JS_TAG_FLOAT64) {-                d2 = JS_VALUE_GET_FLOAT64(op2);-            } else {-                d2 = JS_VALUE_GET_INT(op2);-            }-            switch(op) {-            case OP_lt:-                res = (d1 < d2); /* if NaN return false */-                break;-            case OP_lte:-                res = (d1 <= d2); /* if NaN return false */-                break;-            case OP_gt:-                res = (d1 > d2); /* if NaN return false */-                break;-            default:-            case OP_gte:-                res = (d1 >= d2); /* if NaN return false */-                break;-            }-        }-    }- done:-    sp[-2] = JS_NewBool(ctx, res);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static BOOL tag_is_number(uint32_t tag)-{-    return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||-            tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_FLOAT ||-            tag == JS_TAG_BIG_DECIMAL);-}--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,-                                            BOOL is_neq)-{-    JSValue op1, op2, ret;-    int res;-    uint32_t tag1, tag2;--    op1 = sp[-2];-    op2 = sp[-1];- redo:-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    if (tag_is_number(tag1) && tag_is_number(tag2)) {-        if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {-            res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);-        } else if ((tag1 == JS_TAG_FLOAT64 &&-                    (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64)) ||-                   (tag2 == JS_TAG_FLOAT64 &&-                    (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64))) {-            double d1, d2;-            if (tag1 == JS_TAG_FLOAT64) {-                d1 = JS_VALUE_GET_FLOAT64(op1);-            } else {-                d1 = JS_VALUE_GET_INT(op1);-            }-            if (tag2 == JS_TAG_FLOAT64) {-                d2 = JS_VALUE_GET_FLOAT64(op2);-            } else {-                d2 = JS_VALUE_GET_INT(op2);-            }-            res = (d1 == d2);-        } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {-            res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);-            if (res < 0)-                goto exception;-        } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {-            res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);-            if (res < 0)-                goto exception;-        } else {-            res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);-            if (res < 0)-                goto exception;-        }-    } else if (tag1 == tag2) {-        if (tag1 == JS_TAG_OBJECT) {-            /* try the fallback operator */-            res = js_call_binary_op_fallback(ctx, &ret, op1, op2,-                                             is_neq ? OP_neq : OP_eq,-                                             FALSE, HINT_NONE);-            if (res != 0) {-                JS_FreeValue(ctx, op1);-                JS_FreeValue(ctx, op2);-                if (res < 0) {-                    goto exception;-                } else {-                    sp[-2] = ret;-                    return 0;-                }-            }-        }-        res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);-    } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||-               (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {-        res = TRUE;-    } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||-               (tag2 == JS_TAG_STRING && tag_is_number(tag1))) {--        if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) &&-            !is_math_mode(ctx)) {-            if (tag1 == JS_TAG_STRING) {-                op1 = JS_StringToBigInt(ctx, op1);-                if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)-                    goto invalid_bigint_string;-            }-            if (tag2 == JS_TAG_STRING) {-                op2 = JS_StringToBigInt(ctx, op2);-                if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT) {-                invalid_bigint_string:-                    JS_FreeValue(ctx, op1);-                    JS_FreeValue(ctx, op2);-                    res = FALSE;-                    goto done;-                }-            }-        } else {-            op1 = JS_ToNumericFree(ctx, op1);-            if (JS_IsException(op1)) {-                JS_FreeValue(ctx, op2);-                goto exception;-            }-            op2 = JS_ToNumericFree(ctx, op2);-            if (JS_IsException(op2)) {-                JS_FreeValue(ctx, op1);-                goto exception;-            }-        }-        res = js_strict_eq(ctx, op1, op2);-    } else if (tag1 == JS_TAG_BOOL) {-        op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));-        goto redo;-    } else if (tag2 == JS_TAG_BOOL) {-        op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));-        goto redo;-    } else if ((tag1 == JS_TAG_OBJECT &&-                (tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||-               (tag2 == JS_TAG_OBJECT &&-                (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {--        /* try the fallback operator */-        res = js_call_binary_op_fallback(ctx, &ret, op1, op2,-                                         is_neq ? OP_neq : OP_eq,-                                         FALSE, HINT_NONE);-        if (res != 0) {-            JS_FreeValue(ctx, op1);-            JS_FreeValue(ctx, op2);-            if (res < 0) {-                goto exception;-            } else {-                sp[-2] = ret;-                return 0;-            }-        }--        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);-        if (JS_IsException(op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            goto exception;-        }-        goto redo;-    } else {-        /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */-        if ((JS_IsHTMLDDA(ctx, op1) &&-             (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||-            (JS_IsHTMLDDA(ctx, op2) &&-             (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {-            res = TRUE;-        } else {-            res = FALSE;-        }-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-    }- done:-    sp[-2] = JS_NewBool(ctx, res ^ is_neq);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    uint32_t v1, v2, r;--    op1 = sp[-2];-    op2 = sp[-1];-    op1 = JS_ToNumericFree(ctx, op1);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToNumericFree(ctx, op2);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }-    /* XXX: could forbid >>> in bignum mode */-    if (!is_math_mode(ctx) &&-        (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||-         JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT)) {-        JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>");-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    /* cannot give an exception */-    JS_ToUint32Free(ctx, &v1, op1);-    JS_ToUint32Free(ctx, &v2, op2);-    r = v1 >> (v2 & 0x1f);-    sp[-2] = JS_NewUint32(ctx, r);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,-                                       int64_t exponent)-{-    bf_t r_s, *r = &r_s;-    double d;-    int ret;-    -    /* always convert to Float64 */-    bf_init(ctx->bf_ctx, r);-    ret = bf_mul_pow_radix(r, a, 10, exponent,-                           53, bf_set_exp_bits(11) | BF_RNDN |-                           BF_FLAG_SUBNORMAL);-    bf_get_float64(r, &d, BF_RNDN);-    bf_delete(r);-    if (ret & BF_ST_MEM_ERROR)-        return JS_ThrowOutOfMemory(ctx);-    else-        return __JS_NewFloat64(ctx, d);-}--static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)-{-    bf_t a_s, *a, *r;-    JSValue op1, op2, res;-    int64_t e;-    int ret;--    res = JS_NewBigFloat(ctx);-    if (JS_IsException(res))-        return -1;-    r = JS_GetBigFloat(res);-    op1 = sp[-2];-    op2 = sp[-1];-    a = JS_ToBigFloat(ctx, &a_s, op1);-    if (!a)-        return -1;-    if (JS_IsBigInt(ctx, op2)) {-        ret = JS_ToBigInt64(ctx, &e, op2);-    } else {-        ret = JS_ToInt64(ctx, &e, op2);-    }-    if (ret) {-        if (a == &a_s)-            bf_delete(a);-        JS_FreeValue(ctx, res);-        return -1;-    }--    bf_mul_pow_radix(r, a, 10, e, ctx->fp_env.prec, ctx->fp_env.flags);-    if (a == &a_s)-        bf_delete(a);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    sp[-2] = res;-    return 0;-}--#else /* !CONFIG_BIGNUM */--static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "bigint is not supported");-}--JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)-{-    return JS_ThrowUnsupportedBigint(ctx);-}--JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)-{-    return JS_ThrowUnsupportedBigint(ctx);-}--int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)-{-    JS_ThrowUnsupportedBigint(ctx);-    *pres = 0;-    return -1;-}--static no_inline __exception int js_unary_arith_slow(JSContext *ctx,-                                                     JSValue *sp,-                                                     OPCodeEnum op)-{-    JSValue op1;-    double d;--    op1 = sp[-1];-    if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {-        sp[-1] = JS_UNDEFINED;-        return -1;-    }-    switch(op) {-    case OP_inc:-        d++;-        break;-    case OP_dec:-        d--;-        break;-    case OP_plus:-        break;-    case OP_neg:-        d = -d;-        break;-    default:-        abort();-    }-    sp[-1] = JS_NewFloat64(ctx, d);-    return 0;-}--/* specific case necessary for correct return value semantics */-static __exception int js_post_inc_slow(JSContext *ctx,-                                        JSValue *sp, OPCodeEnum op)-{-    JSValue op1;-    double d, r;--    op1 = sp[-1];-    if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {-        sp[-1] = JS_UNDEFINED;-        return -1;-    }-    r = d + 2 * (op - OP_post_dec) - 1;-    sp[0] = JS_NewFloat64(ctx, r);-    sp[-1] = JS_NewFloat64(ctx, d);-    return 0;-}--static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,-                                                      OPCodeEnum op)-{-    JSValue op1, op2;-    double d1, d2, r;--    op1 = sp[-2];-    op2 = sp[-1];-    if (unlikely(JS_ToFloat64Free(ctx, &d1, op1))) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    if (unlikely(JS_ToFloat64Free(ctx, &d2, op2))) {-        goto exception;-    }-    switch(op) {-    case OP_sub:-        r = d1 - d2;-        break;-    case OP_mul:-        r = d1 * d2;-        break;-    case OP_div:-        r = d1 / d2;-        break;-    case OP_mod:-        r = fmod(d1, d2);-        break;-    case OP_pow:-        r = js_pow(d1, d2);-        break;-    default:-        abort();-    }-    sp[-2] = JS_NewFloat64(ctx, r);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    uint32_t tag1, tag2;--    op1 = sp[-2];-    op2 = sp[-1];-    tag1 = JS_VALUE_GET_TAG(op1);-    tag2 = JS_VALUE_GET_TAG(op2);-    if ((tag1 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag1)) &&-        (tag2 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag2))) {-        goto add_numbers;-    } else {-        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);-        if (JS_IsException(op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            goto exception;-        }-        tag1 = JS_VALUE_GET_TAG(op1);-        tag2 = JS_VALUE_GET_TAG(op2);-        if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {-            sp[-2] = JS_ConcatString(ctx, op1, op2);-            if (JS_IsException(sp[-2]))-                goto exception;-        } else {-            double d1, d2;-        add_numbers:-            if (JS_ToFloat64Free(ctx, &d1, op1)) {-                JS_FreeValue(ctx, op2);-                goto exception;-            }-            if (JS_ToFloat64Free(ctx, &d2, op2))-                goto exception;-            sp[-2] = JS_NewFloat64(ctx, d1 + d2);-        }-    }-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline __exception int js_binary_logic_slow(JSContext *ctx,-                                                      JSValue *sp,-                                                      OPCodeEnum op)-{-    JSValue op1, op2;-    uint32_t v1, v2, r;--    op1 = sp[-2];-    op2 = sp[-1];-    if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))-        goto exception;-    switch(op) {-    case OP_shl:-        r = v1 << (v2 & 0x1f);-        break;-    case OP_sar:-        r = (int)v1 >> (v2 & 0x1f);-        break;-    case OP_and:-        r = v1 & v2;-        break;-    case OP_or:-        r = v1 | v2;-        break;-    case OP_xor:-        r = v1 ^ v2;-        break;-    default:-        abort();-    }-    sp[-2] = JS_NewInt32(ctx, r);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)-{-    int32_t v1;--    if (unlikely(JS_ToInt32Free(ctx, &v1, sp[-1]))) {-        sp[-1] = JS_UNDEFINED;-        return -1;-    }-    sp[-1] = JS_NewInt32(ctx, ~v1);-    return 0;-}--static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,-                                        OPCodeEnum op)-{-    JSValue op1, op2;-    int res;--    op1 = sp[-2];-    op2 = sp[-1];-    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);-    if (JS_IsException(op1)) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        goto exception;-    }-    if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING &&-        JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {-        JSString *p1, *p2;-        p1 = JS_VALUE_GET_STRING(op1);-        p2 = JS_VALUE_GET_STRING(op2);-        res = js_string_compare(ctx, p1, p2);-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-        switch(op) {-        case OP_lt:-            res = (res < 0);-            break;-        case OP_lte:-            res = (res <= 0);-            break;-        case OP_gt:-            res = (res > 0);-            break;-        default:-        case OP_gte:-            res = (res >= 0);-            break;-        }-    } else {-        double d1, d2;-        if (JS_ToFloat64Free(ctx, &d1, op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        if (JS_ToFloat64Free(ctx, &d2, op2))-            goto exception;-        switch(op) {-        case OP_lt:-            res = (d1 < d2); /* if NaN return false */-            break;-        case OP_lte:-            res = (d1 <= d2); /* if NaN return false */-            break;-        case OP_gt:-            res = (d1 > d2); /* if NaN return false */-            break;-        default:-        case OP_gte:-            res = (d1 >= d2); /* if NaN return false */-            break;-        }-    }-    sp[-2] = JS_NewBool(ctx, res);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,-                                            BOOL is_neq)-{-    JSValue op1, op2;-    int tag1, tag2;-    BOOL res;--    op1 = sp[-2];-    op2 = sp[-1];- redo:-    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    if (tag1 == tag2 ||-        (tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||-        (tag2 == JS_TAG_INT && tag1 == JS_TAG_FLOAT64)) {-        res = js_strict_eq(ctx, op1, op2);-    } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||-               (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {-        res = TRUE;-    } else if ((tag1 == JS_TAG_STRING && (tag2 == JS_TAG_INT ||-                                   tag2 == JS_TAG_FLOAT64)) ||-        (tag2 == JS_TAG_STRING && (tag1 == JS_TAG_INT ||-                                   tag1 == JS_TAG_FLOAT64))) {-        double d1;-        double d2;-        if (JS_ToFloat64Free(ctx, &d1, op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        if (JS_ToFloat64Free(ctx, &d2, op2))-            goto exception;-        res = (d1 == d2);-    } else if (tag1 == JS_TAG_BOOL) {-        op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));-        goto redo;-    } else if (tag2 == JS_TAG_BOOL) {-        op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));-        goto redo;-    } else if (tag1 == JS_TAG_OBJECT &&-               (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64 || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) {-        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);-        if (JS_IsException(op1)) {-            JS_FreeValue(ctx, op2);-            goto exception;-        }-        goto redo;-    } else if (tag2 == JS_TAG_OBJECT &&-               (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64 || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL)) {-        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            goto exception;-        }-        goto redo;-    } else {-        /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */-        if ((JS_IsHTMLDDA(ctx, op1) &&-             (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||-            (JS_IsHTMLDDA(ctx, op2) &&-             (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {-            res = TRUE;-        } else {-            res = FALSE;-        }-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-    }-    sp[-2] = JS_NewBool(ctx, res ^ is_neq);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    uint32_t v1, v2, r;--    op1 = sp[-2];-    op2 = sp[-1];-    if (unlikely(JS_ToUint32Free(ctx, &v1, op1))) {-        JS_FreeValue(ctx, op2);-        goto exception;-    }-    if (unlikely(JS_ToUint32Free(ctx, &v2, op2)))-        goto exception;-    r = v1 >> (v2 & 0x1f);-    sp[-2] = JS_NewUint32(ctx, r);-    return 0;- exception:-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--#endif /* !CONFIG_BIGNUM */--/* XXX: Should take JSValueConst arguments */-static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,-                          JSStrictEqModeEnum eq_mode)-{-    BOOL res;-    int tag1, tag2;-    double d1, d2;--    tag1 = JS_VALUE_GET_NORM_TAG(op1);-    tag2 = JS_VALUE_GET_NORM_TAG(op2);-    switch(tag1) {-    case JS_TAG_BOOL:-        if (tag1 != tag2) {-            res = FALSE;-        } else {-            res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);-            goto done_no_free;-        }-        break;-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        res = (tag1 == tag2);-        break;-    case JS_TAG_STRING:-        {-            JSString *p1, *p2;-            if (tag1 != tag2) {-                res = FALSE;-            } else {-                p1 = JS_VALUE_GET_STRING(op1);-                p2 = JS_VALUE_GET_STRING(op2);-                res = (js_string_compare(ctx, p1, p2) == 0);-            }-        }-        break;-    case JS_TAG_SYMBOL:-        {-            JSAtomStruct *p1, *p2;-            if (tag1 != tag2) {-                res = FALSE;-            } else {-                p1 = JS_VALUE_GET_PTR(op1);-                p2 = JS_VALUE_GET_PTR(op2);-                res = (p1 == p2);-            }-        }-        break;-    case JS_TAG_OBJECT:-        if (tag1 != tag2)-            res = FALSE;-        else-            res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2);-        break;-    case JS_TAG_INT:-        d1 = JS_VALUE_GET_INT(op1);-        if (tag2 == JS_TAG_INT) {-            d2 = JS_VALUE_GET_INT(op2);-            goto number_test;-        } else if (tag2 == JS_TAG_FLOAT64) {-            d2 = JS_VALUE_GET_FLOAT64(op2);-            goto number_test;-        } else {-            res = FALSE;-        }-        break;-    case JS_TAG_FLOAT64:-        d1 = JS_VALUE_GET_FLOAT64(op1);-        if (tag2 == JS_TAG_FLOAT64) {-            d2 = JS_VALUE_GET_FLOAT64(op2);-        } else if (tag2 == JS_TAG_INT) {-            d2 = JS_VALUE_GET_INT(op2);-        } else {-            res = FALSE;-            break;-        }-    number_test:-        if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) {-            JSFloat64Union u1, u2;-            /* NaN is not always normalized, so this test is necessary */-            if (isnan(d1) || isnan(d2)) {-                res = isnan(d1) == isnan(d2);-            } else if (eq_mode == JS_EQ_SAME_VALUE_ZERO) {-                res = (d1 == d2); /* +0 == -0 */-            } else {-                u1.d = d1;-                u2.d = d2;-                res = (u1.u64 == u2.u64); /* +0 != -0 */-            }-        } else {-            res = (d1 == d2); /* if NaN return false and +0 == -0 */-        }-        goto done_no_free;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        {-            bf_t a_s, *a, b_s, *b;-            if (tag1 != tag2) {-                res = FALSE;-                break;-            }-            a = JS_ToBigFloat(ctx, &a_s, op1);-            b = JS_ToBigFloat(ctx, &b_s, op2);-            res = bf_cmp_eq(a, b);-            if (a == &a_s)-                bf_delete(a);-            if (b == &b_s)-                bf_delete(b);-        }-        break;-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p1, *p2;-            const bf_t *a, *b;-            if (tag1 != tag2) {-                res = FALSE;-                break;-            }-            p1 = JS_VALUE_GET_PTR(op1);-            p2 = JS_VALUE_GET_PTR(op2);-            a = &p1->num;-            b = &p2->num;-            if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) {-                if (eq_mode == JS_EQ_SAME_VALUE_ZERO &&-                           a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO) {-                    res = TRUE;-                } else {-                    res = (bf_cmp_full(a, b) == 0);-                }-            } else {-                res = bf_cmp_eq(a, b);-            }-        }-        break;-    case JS_TAG_BIG_DECIMAL:-        {-            JSBigDecimal *p1, *p2;-            const bfdec_t *a, *b;-            if (tag1 != tag2) {-                res = FALSE;-                break;-            }-            p1 = JS_VALUE_GET_PTR(op1);-            p2 = JS_VALUE_GET_PTR(op2);-            a = &p1->num;-            b = &p2->num;-            res = bfdec_cmp_eq(a, b);-        }-        break;-#endif-    default:-        res = FALSE;-        break;-    }-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);- done_no_free:-    return res;-}--static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)-{-    return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);-}--static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)-{-    return js_strict_eq2(ctx,-                         JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),-                         JS_EQ_SAME_VALUE);-}--static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)-{-    return js_strict_eq2(ctx,-                         JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),-                         JS_EQ_SAME_VALUE_ZERO);-}--static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,-                                       BOOL is_neq)-{-    BOOL res;-    res = js_strict_eq(ctx, sp[-2], sp[-1]);-    sp[-2] = JS_NewBool(ctx, res ^ is_neq);-    return 0;-}--static __exception int js_operator_in(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    JSAtom atom;-    int ret;--    op1 = sp[-2];-    op2 = sp[-1];--    if (JS_VALUE_GET_TAG(op2) != JS_TAG_OBJECT) {-        JS_ThrowTypeError(ctx, "invalid 'in' operand");-        return -1;-    }-    atom = JS_ValueToAtom(ctx, op1);-    if (unlikely(atom == JS_ATOM_NULL))-        return -1;-    ret = JS_HasProperty(ctx, op2, atom);-    JS_FreeAtom(ctx, atom);-    if (ret < 0)-        return -1;-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    sp[-2] = JS_NewBool(ctx, ret);-    return 0;-}--static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,-                                         JSAtom atom)-{-    JSValue arr, val;-    int ret;--    arr = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_unscopables);-    if (JS_IsException(arr))-        return -1;-    ret = 0;-    if (JS_IsObject(arr)) {-        val = JS_GetProperty(ctx, arr, atom);-        ret = JS_ToBoolFree(ctx, val);-    }-    JS_FreeValue(ctx, arr);-    return ret;-}--static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    BOOL ret;--    op1 = sp[-2];-    op2 = sp[-1];-    ret = JS_IsInstanceOf(ctx, op1, op2);-    if (ret < 0)-        return ret;-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    sp[-2] = JS_NewBool(ctx, ret);-    return 0;-}--static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)-{-    JSAtom atom;-    uint32_t tag;--    tag = JS_VALUE_GET_NORM_TAG(op1);-    switch(tag) {-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        atom = JS_ATOM_bigint;-        break;-    case JS_TAG_BIG_FLOAT:-        atom = JS_ATOM_bigfloat;-        break;-    case JS_TAG_BIG_DECIMAL:-        atom = JS_ATOM_bigdecimal;-        break;-#endif-    case JS_TAG_INT:-    case JS_TAG_FLOAT64:-        atom = JS_ATOM_number;-        break;-    case JS_TAG_UNDEFINED:-        atom = JS_ATOM_undefined;-        break;-    case JS_TAG_BOOL:-        atom = JS_ATOM_boolean;-        break;-    case JS_TAG_STRING:-        atom = JS_ATOM_string;-        break;-    case JS_TAG_OBJECT:-        {-            JSObject *p;-            p = JS_VALUE_GET_OBJ(op1);-            if (unlikely(p->is_HTMLDDA)) -                atom = JS_ATOM_undefined;-            else if (JS_IsFunction(ctx, op1))-                atom = JS_ATOM_function;-            else-                goto obj_type;-        }-        break;-    case JS_TAG_NULL:-    obj_type:-        atom = JS_ATOM_object;-        break;-    case JS_TAG_SYMBOL:-        atom = JS_ATOM_symbol;-        break;-    default:-        atom = JS_ATOM_unknown;-        break;-    }-    return atom;-}--static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)-{-    JSValue op1, op2;-    JSAtom atom;-    int ret;--    op1 = sp[-2];-    op2 = sp[-1];-    atom = JS_ValueToAtom(ctx, op2);-    if (unlikely(atom == JS_ATOM_NULL))-        return -1;-    ret = JS_DeleteProperty(ctx, op1, atom, JS_PROP_THROW_STRICT);-    JS_FreeAtom(ctx, atom);-    if (unlikely(ret < 0))-        return -1;-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    sp[-2] = JS_NewBool(ctx, ret);-    return 0;-}--static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    return JS_ThrowTypeError(ctx, "invalid property access");-}--/* XXX: not 100% compatible, but mozilla seems to use a similar-   implementation to ensure that caller in non strict mode does not-   throw (ES5 compatibility) */-static JSValue js_function_proto_caller(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);-    if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype) {-        return js_throw_type_error(ctx, this_val, 0, NULL);-    }-    return JS_UNDEFINED;-}--static JSValue js_function_proto_fileName(JSContext *ctx,-                                          JSValueConst this_val)-{-    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);-    if (b && b->has_debug) {-        return JS_AtomToString(ctx, b->debug.filename);-    }-    return JS_UNDEFINED;-}--static JSValue js_function_proto_lineNumber(JSContext *ctx,-                                            JSValueConst this_val)-{-    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);-    if (b && b->has_debug) {-        return JS_NewInt32(ctx, b->debug.line_num);-    }-    return JS_UNDEFINED;-}--static int js_arguments_define_own_property(JSContext *ctx,-                                            JSValueConst this_obj,-                                            JSAtom prop, JSValueConst val,-                                            JSValueConst getter, JSValueConst setter, int flags)-{-    JSObject *p;-    uint32_t idx;-    p = JS_VALUE_GET_OBJ(this_obj);-    /* convert to normal array when redefining an existing numeric field */-    if (p->fast_array && JS_AtomIsArrayIndex(ctx, &idx, prop) &&-        idx < p->u.array.count) {-        if (convert_fast_array_to_array(ctx, p))-            return -1;-    }-    /* run the default define own property */-    return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,-                             flags | JS_PROP_NO_EXOTIC);-}--static const JSClassExoticMethods js_arguments_exotic_methods = {-    .define_own_property = js_arguments_define_own_property,-};--static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)-{-    JSValue val, *tab;-    JSProperty *pr;-    JSObject *p;-    int i;--    val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                                 JS_CLASS_ARGUMENTS);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_OBJ(val);--    /* add the length field (cannot fail) */-    pr = add_property(ctx, p, JS_ATOM_length,-                      JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    pr->u.value = JS_NewInt32(ctx, argc);--    /* initialize the fast array part */-    tab = NULL;-    if (argc > 0) {-        tab = js_malloc(ctx, sizeof(tab[0]) * argc);-        if (!tab) {-            JS_FreeValue(ctx, val);-            return JS_EXCEPTION;-        }-        for(i = 0; i < argc; i++) {-            tab[i] = JS_DupValue(ctx, argv[i]);-        }-    }-    p->u.array.u.values = tab;-    p->u.array.count = argc;--    JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,-                           JS_DupValue(ctx, ctx->array_proto_values),-                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);-    /* add callee property to throw a TypeError in strict mode */-    JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED,-                      ctx->throw_type_error, ctx->throw_type_error,-                      JS_PROP_HAS_GET | JS_PROP_HAS_SET);-    return val;-}--#define GLOBAL_VAR_OFFSET 0x40000000-#define ARGUMENT_VAR_OFFSET 0x20000000--/* legacy arguments object: add references to the function arguments */-static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,-                                         JSValueConst *argv,-                                         JSStackFrame *sf, int arg_count)-{-    JSValue val;-    JSProperty *pr;-    JSObject *p;-    int i;--    val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                                 JS_CLASS_MAPPED_ARGUMENTS);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_OBJ(val);--    /* add the length field (cannot fail) */-    pr = add_property(ctx, p, JS_ATOM_length,-                      JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    pr->u.value = JS_NewInt32(ctx, argc);--    for(i = 0; i < arg_count; i++) {-        JSVarRef *var_ref;-        var_ref = get_var_ref(ctx, sf, i, TRUE);-        if (!var_ref)-            goto fail;-        pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);-        if (!pr) {-            free_var_ref(ctx->rt, var_ref);-            goto fail;-        }-        pr->u.var_ref = var_ref;-    }--    /* the arguments not mapped to the arguments of the function can-       be normal properties */-    for(i = arg_count; i < argc; i++) {-        if (JS_DefinePropertyValueUint32(ctx, val, i,-                                         JS_DupValue(ctx, argv[i]),-                                         JS_PROP_C_W_E) < 0)-            goto fail;-    }--    JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,-                           JS_DupValue(ctx, ctx->array_proto_values),-                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);-    /* callee returns this function in non strict mode */-    JS_DefinePropertyValue(ctx, val, JS_ATOM_callee,-                           JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func),-                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);-    return val;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv)-{-    JSValue val;-    int i, ret;--    val = JS_NewArray(ctx);-    if (JS_IsException(val))-        return val;-    for (i = first; i < argc; i++) {-        ret = JS_DefinePropertyValueUint32(ctx, val, i - first,-                                           JS_DupValue(ctx, argv[i]),-                                           JS_PROP_C_W_E);-        if (ret < 0) {-            JS_FreeValue(ctx, val);-            return JS_EXCEPTION;-        }-    }-    return val;-}--static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)-{-    JSObject *p, *p1;-    JSPropertyEnum *tab_atom;-    int i;-    JSValue enum_obj;-    JSForInIterator *it;-    uint32_t tag, tab_atom_count;--    tag = JS_VALUE_GET_TAG(obj);-    if (tag != JS_TAG_OBJECT && tag != JS_TAG_NULL && tag != JS_TAG_UNDEFINED) {-        obj = JS_ToObjectFree(ctx, obj);-    }--    it = js_malloc(ctx, sizeof(*it));-    if (!it) {-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    enum_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_FOR_IN_ITERATOR);-    if (JS_IsException(enum_obj)) {-        js_free(ctx, it);-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    it->is_array = FALSE;-    it->obj = obj;-    it->idx = 0;-    p = JS_VALUE_GET_OBJ(enum_obj);-    p->u.for_in_iterator = it;--    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)-        return enum_obj;--    p = JS_VALUE_GET_OBJ(obj);--    /* fast path: assume no enumerable properties in the prototype chain */-    p1 = p->shape->proto;-    while (p1 != NULL) {-        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p1,-                                   JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))-            goto fail;-        js_free_prop_enum(ctx, tab_atom, tab_atom_count);-        if (tab_atom_count != 0) {-            goto slow_path;-        }-        p1 = p1->shape->proto;-    }-    if (p->fast_array) {-        JSShape *sh;-        JSShapeProperty *prs;-        /* check that there are no enumerable normal fields */-        sh = p->shape;-        for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {-            if (prs->flags & JS_PROP_ENUMERABLE)-                goto normal_case;-        }-        /* the implicit GetOwnProperty raises an exception if the-           typed array is detached */-        if ((p->class_id >= JS_CLASS_UINT8C_ARRAY &&-             p->class_id <= JS_CLASS_FLOAT64_ARRAY) &&-            typed_array_is_detached(ctx, p) &&-            typed_array_get_length(ctx, p) != 0) {-            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-            goto fail;-        }-        /* for fast arrays, we only store the number of elements */-        it->is_array = TRUE;-        it->array_length = p->u.array.count;-    } else {-    normal_case:-        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,-                                   JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))-            goto fail;-        for(i = 0; i < tab_atom_count; i++) {-            JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0);-        }-        js_free_prop_enum(ctx, tab_atom, tab_atom_count);-    }-    return enum_obj;-- slow_path:-    /* non enumerable properties hide the enumerables ones in the-       prototype chain */-    while (p != NULL) {-        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,-                                   JS_GPN_STRING_MASK | JS_GPN_SET_ENUM))-            goto fail;-        for(i = 0; i < tab_atom_count; i++) {-            JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,-                                   (tab_atom[i].is_enumerable ?-                                    JS_PROP_ENUMERABLE : 0));-        }-        js_free_prop_enum(ctx, tab_atom, tab_atom_count);-        p = p->shape->proto;-    }-    return enum_obj;-- fail:-    JS_FreeValue(ctx, enum_obj);-    return JS_EXCEPTION;-}--/* obj -> enum_obj */-static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)-{-    sp[-1] = build_for_in_iterator(ctx, sp[-1]);-    if (JS_IsException(sp[-1]))-        return -1;-    return 0;-}--/* enum_obj -> enum_obj value done */-static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)-{-    JSValueConst enum_obj;-    JSObject *p;-    JSAtom prop;-    JSForInIterator *it;-    int ret;--    enum_obj = sp[-1];-    /* fail safe */-    if (JS_VALUE_GET_TAG(enum_obj) != JS_TAG_OBJECT)-        goto done;-    p = JS_VALUE_GET_OBJ(enum_obj);-    if (p->class_id != JS_CLASS_FOR_IN_ITERATOR)-        goto done;-    it = p->u.for_in_iterator;--    for(;;) {-        if (it->is_array) {-            if (it->idx >= it->array_length)-                goto done;-            prop = __JS_AtomFromUInt32(it->idx);-            it->idx++;-        } else {-            JSShape *sh = p->shape;-            JSShapeProperty *prs;-            if (it->idx >= sh->prop_count)-                goto done;-            prs = get_shape_prop(sh) + it->idx;-            prop = prs->atom;-            it->idx++;-            if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE))-                continue;-        }-        /* check if the property was deleted */-        ret = JS_HasProperty(ctx, it->obj, prop);-        if (ret < 0)-            return ret;-        if (ret)-            break;-    }-    /* return the property */-    sp[0] = JS_AtomToValue(ctx, prop);-    sp[1] = JS_FALSE;-    return 0;- done:-    /* return the end */-    sp[0] = JS_UNDEFINED;-    sp[1] = JS_TRUE;-    return 0;-}--static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj,-                               JSValueConst method)-{-    JSValue enum_obj;--    enum_obj = JS_Call(ctx, method, obj, 0, NULL);-    if (JS_IsException(enum_obj))-        return enum_obj;-    if (!JS_IsObject(enum_obj)) {-        JS_FreeValue(ctx, enum_obj);-        return JS_ThrowTypeErrorNotAnObject(ctx);-    }-    return enum_obj;-}--static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)-{-    JSValue method, ret, sync_iter;--    if (is_async) {-        method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_asyncIterator);-        if (JS_IsException(method))-            return method;-        if (JS_IsUndefined(method) || JS_IsNull(method)) {-            method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);-            if (JS_IsException(method))-                return method;-            sync_iter = JS_GetIterator2(ctx, obj, method);-            JS_FreeValue(ctx, method);-            if (JS_IsException(sync_iter))-                return sync_iter;-            ret = JS_CreateAsyncFromSyncIterator(ctx, sync_iter);-            JS_FreeValue(ctx, sync_iter);-            return ret;-        }-    } else {-        method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);-        if (JS_IsException(method))-            return method;-    }-    if (!JS_IsFunction(ctx, method)) {-        JS_FreeValue(ctx, method);-        return JS_ThrowTypeError(ctx, "value is not iterable");-    }-    ret = JS_GetIterator2(ctx, obj, method);-    JS_FreeValue(ctx, method);-    return ret;-}--/* return *pdone = 2 if the iterator object is not parsed */-static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,-                                JSValueConst method,-                                int argc, JSValueConst *argv, int *pdone)-{-    JSValue obj;--    /* fast path for the built-in iterators (avoid creating the-       intermediate result object) */-    if (JS_IsObject(method)) {-        JSObject *p = JS_VALUE_GET_OBJ(method);-        if (p->class_id == JS_CLASS_C_FUNCTION &&-            p->u.cfunc.cproto == JS_CFUNC_iterator_next) {-            JSCFunctionType func;-            JSValueConst args[1];--            /* in case the function expects one argument */-            if (argc == 0) {-                args[0] = JS_UNDEFINED;-                argv = args;-            }-            func = p->u.cfunc.c_function;-            return func.iterator_next(ctx, enum_obj, argc, argv,-                                      pdone, p->u.cfunc.magic);-        }-    }-    obj = JS_Call(ctx, method, enum_obj, argc, argv);-    if (JS_IsException(obj))-        goto fail;-    if (!JS_IsObject(obj)) {-        JS_FreeValue(ctx, obj);-        JS_ThrowTypeError(ctx, "iterator must return an object");-        goto fail;-    }-    *pdone = 2;-    return obj;- fail:-    *pdone = FALSE;-    return JS_EXCEPTION;-}--static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,-                               JSValueConst method,-                               int argc, JSValueConst *argv, BOOL *pdone)-{-    JSValue obj, value, done_val;-    int done;--    obj = JS_IteratorNext2(ctx, enum_obj, method, argc, argv, &done);-    if (JS_IsException(obj))-        goto fail;-    if (done != 2) {-        *pdone = done;-        return obj;-    } else {-        done_val = JS_GetProperty(ctx, obj, JS_ATOM_done);-        if (JS_IsException(done_val))-            goto fail;-        *pdone = JS_ToBoolFree(ctx, done_val);-        value = JS_UNDEFINED;-        if (!*pdone) {-            value = JS_GetProperty(ctx, obj, JS_ATOM_value);-        }-        JS_FreeValue(ctx, obj);-        return value;-    }- fail:-    JS_FreeValue(ctx, obj);-    *pdone = FALSE;-    return JS_EXCEPTION;-}--/* return < 0 in case of exception */-static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,-                            BOOL is_exception_pending)-{-    JSValue method, ret, ex_obj;-    int res;--    if (is_exception_pending) {-        ex_obj = ctx->rt->current_exception;-        ctx->rt->current_exception = JS_NULL;-        res = -1;-    } else {-        ex_obj = JS_UNDEFINED;-        res = 0;-    }-    method = JS_GetProperty(ctx, enum_obj, JS_ATOM_return);-    if (JS_IsException(method)) {-        res = -1;-        goto done;-    }-    if (JS_IsUndefined(method) || JS_IsNull(method)) {-        goto done;-    }-    ret = JS_CallFree(ctx, method, enum_obj, 0, NULL);-    if (!is_exception_pending) {-        if (JS_IsException(ret)) {-            res = -1;-        } else if (!JS_IsObject(ret)) {-            JS_ThrowTypeErrorNotAnObject(ctx);-            res = -1;-        }-    }-    JS_FreeValue(ctx, ret);- done:-    if (is_exception_pending) {-        JS_Throw(ctx, ex_obj);-    }-    return res;-}--/* obj -> enum_rec (3 slots) */-static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,-                                       BOOL is_async)-{-    JSValue op1, obj, method;-    op1 = sp[-1];-    obj = JS_GetIterator(ctx, op1, is_async);-    if (JS_IsException(obj))-        return -1;-    JS_FreeValue(ctx, op1);-    sp[-1] = obj;-    method = JS_GetProperty(ctx, obj, JS_ATOM_next);-    if (JS_IsException(method))-        return -1;-    sp[0] = method;-    return 0;-}--/* enum_rec [objs] -> enum_rec [objs] value done. There are 'offset'-   objs. If 'done' is true or in case of exception, 'enum_rec' is set-   to undefined. If 'done' is true, 'value' is always set to-   undefined. */-static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)-{-    JSValue value = JS_UNDEFINED;-    int done = 1;--    if (likely(!JS_IsUndefined(sp[offset]))) {-        value = JS_IteratorNext(ctx, sp[offset], sp[offset + 1], 0, NULL, &done);-        if (JS_IsException(value))-            done = -1;-        if (done) {-            /* value is JS_UNDEFINED or JS_EXCEPTION */-            /* replace the iteration object with undefined */-            JS_FreeValue(ctx, sp[offset]);-            sp[offset] = JS_UNDEFINED;-            if (done < 0) {-                return -1;-            } else {-                JS_FreeValue(ctx, value);-                value = JS_UNDEFINED;-            }-        }-    }-    sp[0] = value;-    sp[1] = JS_NewBool(ctx, done);-    return 0;-}--static __exception int js_for_await_of_next(JSContext *ctx, JSValue *sp)-{-    JSValue result;-    result = JS_Call(ctx, sp[-2], sp[-3], 0, NULL);-    if (JS_IsException(result))-        return -1;-    sp[0] = result;-    return 0;-}--static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,-                                           BOOL *pdone)-{-    JSValue done_val, value;-    BOOL done;-    done_val = JS_GetProperty(ctx, obj, JS_ATOM_done);-    if (JS_IsException(done_val))-        goto fail;-    done = JS_ToBoolFree(ctx, done_val);-    value = JS_GetProperty(ctx, obj, JS_ATOM_value);-    if (JS_IsException(value))-        goto fail;-    *pdone = done;-    return value;- fail:-    *pdone = FALSE;-    return JS_EXCEPTION;-}--static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)-{-    JSValue obj, value;-    BOOL done;-    obj = sp[-1];-    if (!JS_IsObject(obj)) {-        JS_ThrowTypeError(ctx, "iterator must return an object");-        return -1;-    }-    value = JS_IteratorGetCompleteValue(ctx, obj, &done);-    if (JS_IsException(value))-        return -1;-    JS_FreeValue(ctx, obj);-    sp[-1] = value;-    sp[0] = JS_NewBool(ctx, done);-    return 0;-}--static JSValue js_create_iterator_result(JSContext *ctx,-                                         JSValue val,-                                         BOOL done)-{-    JSValue obj;-    obj = JS_NewObject(ctx);-    if (JS_IsException(obj)) {-        JS_FreeValue(ctx, val);-        return obj;-    }-    if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_value,-                               val, JS_PROP_C_W_E) < 0) {-        goto fail;-    }-    if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done,-                               JS_NewBool(ctx, done), JS_PROP_C_W_E) < 0) {-    fail:-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    return obj;-}--static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv,-                                      BOOL *pdone, int magic);--static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv, int magic);--static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj)-{-    /* Try and handle fast arrays explicitly */-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(obj);-        if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {-            return TRUE;-        }-    }-    return FALSE;-}--/* Access an Array's internal JSValue array if available */-static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,-                              JSValue **arrpp, uint32_t *countp)-{-    /* Try and handle fast arrays explicitly */-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(obj);-        if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {-            *countp = p->u.array.count;-            *arrpp = p->u.array.u.values;-            return TRUE;-        }-    }-    return FALSE;-}--static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)-{-    JSValue iterator, enumobj, method, value;-    int is_array_iterator;-    JSValue *arrp;-    uint32_t i, count32, pos;-    -    if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {-        JS_ThrowInternalError(ctx, "invalid index for append");-        return -1;-    }--    pos = JS_VALUE_GET_INT(sp[-2]);--    /* XXX: further optimisations:-       - use ctx->array_proto_values?-       - check if array_iterator_prototype next method is built-in and-         avoid constructing actual iterator object?-       - build this into js_for_of_start and use in all `for (x of o)` loops-     */-    iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator);-    if (JS_IsException(iterator))-        return -1;-    is_array_iterator = JS_IsCFunction(ctx, iterator,-                                       (JSCFunction *)js_create_array_iterator,-                                       JS_ITERATOR_KIND_VALUE);-    JS_FreeValue(ctx, iterator);--    enumobj = JS_GetIterator(ctx, sp[-1], FALSE);-    if (JS_IsException(enumobj))-        return -1;-    method = JS_GetProperty(ctx, enumobj, JS_ATOM_next);-    if (JS_IsException(method)) {-        JS_FreeValue(ctx, enumobj);-        return -1;-    }-    if (is_array_iterator-    &&  JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)-    &&  js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {-        uint32_t len;-        if (js_get_length32(ctx, &len, sp[-1]))-            goto exception;-        /* if len > count32, the elements >= count32 might be read in-           the prototypes and might have side effects */-        if (len != count32)-            goto general_case;-        /* Handle fast arrays explicitly */-        for (i = 0; i < count32; i++) {-            if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,-                                             JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)-                goto exception;-        }-    } else {-    general_case:-        for (;;) {-            BOOL done;-            value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done);-            if (JS_IsException(value))-                goto exception;-            if (done) {-                /* value is JS_UNDEFINED */-                break;-            }-            if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, value, JS_PROP_C_W_E) < 0)-                goto exception;-        }-    }-    /* Note: could raise an error if too many elements */-    sp[-2] = JS_NewInt32(ctx, pos);-    JS_FreeValue(ctx, enumobj);-    JS_FreeValue(ctx, method);-    return 0;--exception:-    JS_IteratorClose(ctx, enumobj, TRUE);-    JS_FreeValue(ctx, enumobj);-    JS_FreeValue(ctx, method);-    return -1;-}--static __exception int JS_CopyDataProperties(JSContext *ctx,-                                             JSValueConst target,-                                             JSValueConst source,-                                             JSValueConst excluded,-                                             BOOL setprop)-{-    JSPropertyEnum *tab_atom;-    JSValue val;-    uint32_t i, tab_atom_count;-    JSObject *p;-    JSObject *pexcl = NULL;-    int ret = 0, flags;--    if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)-        return 0;--    if (JS_VALUE_GET_TAG(excluded) == JS_TAG_OBJECT)-        pexcl = JS_VALUE_GET_OBJ(excluded);--    p = JS_VALUE_GET_OBJ(source);-    if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,-                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK |-                               JS_GPN_ENUM_ONLY))-        return -1;--    flags = JS_PROP_C_W_E;--    for (i = 0; i < tab_atom_count; i++) {-        if (pexcl) {-            ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom);-            if (ret) {-                if (ret < 0)-                    break;-                ret = 0;-                continue;-            }-        }-        ret = -1;-        val = JS_GetProperty(ctx, source, tab_atom[i].atom);-        if (JS_IsException(val))-            break;-        if (setprop)-            ret = JS_SetProperty(ctx, target, tab_atom[i].atom, val);-        else-            ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val, flags);-        if (ret < 0)-            break;-        ret = 0;-    }-    js_free_prop_enum(ctx, tab_atom, tab_atom_count);-    return ret;-}--/* only valid inside C functions */-static JSValueConst JS_GetActiveFunction(JSContext *ctx)-{-    return ctx->rt->current_stack_frame->cur_func;-}--static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,-                             int var_idx, BOOL is_arg)-{-    JSVarRef *var_ref;-    struct list_head *el;--    list_for_each(el, &sf->var_ref_list) {-        var_ref = list_entry(el, JSVarRef, header.link);-        if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) {-            var_ref->header.ref_count++;-            return var_ref;-        }-    }-    /* create a new one */-    var_ref = js_malloc(ctx, sizeof(JSVarRef));-    if (!var_ref)-        return NULL;-    var_ref->header.ref_count = 1;-    var_ref->is_detached = FALSE;-    var_ref->is_arg = is_arg;-    var_ref->var_idx = var_idx;-    list_add_tail(&var_ref->header.link, &sf->var_ref_list);-    if (is_arg)-        var_ref->pvalue = &sf->arg_buf[var_idx];-    else-        var_ref->pvalue = &sf->var_buf[var_idx];-    var_ref->value = JS_UNDEFINED;-    return var_ref;-}--static JSValue js_closure2(JSContext *ctx, JSValue func_obj,-                           JSFunctionBytecode *b,-                           JSVarRef **cur_var_refs,-                           JSStackFrame *sf)-{-    JSObject *p;-    JSVarRef **var_refs;-    int i;--    p = JS_VALUE_GET_OBJ(func_obj);-    p->u.func.function_bytecode = b;-    p->u.func.home_object = NULL;-    p->u.func.var_refs = NULL;-    if (b->closure_var_count) {-        var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count);-        if (!var_refs)-            goto fail;-        p->u.func.var_refs = var_refs;-        for(i = 0; i < b->closure_var_count; i++) {-            JSClosureVar *cv = &b->closure_var[i];-            JSVarRef *var_ref;-            if (cv->is_local) {-                /* reuse the existing variable reference if it already exists */-                var_ref = get_var_ref(ctx, sf, cv->var_idx, cv->is_arg);-                if (!var_ref)-                    goto fail;-            } else {-                var_ref = cur_var_refs[cv->var_idx];-                var_ref->header.ref_count++;-            }-            var_refs[i] = var_ref;-        }-    }-    return func_obj;- fail:-    /* bfunc is freed when func_obj is freed */-    JS_FreeValue(ctx, func_obj);-    return JS_EXCEPTION;-}--static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque)-{-    JSValue obj, this_val;-    int ret;--    this_val = JS_MKPTR(JS_TAG_OBJECT, p);-    obj = JS_NewObject(ctx);-    if (JS_IsException(obj))-        return -1;-    set_cycle_flag(ctx, obj);-    set_cycle_flag(ctx, this_val);-    ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor,-                                 JS_DupValue(ctx, this_val),-                                 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    if (JS_DefinePropertyValue(ctx, this_val, atom, obj, JS_PROP_WRITABLE) < 0 || ret < 0)-        return -1;-    return 0;-}--static const uint16_t func_kind_to_class_id[] = {-    [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION,-    [JS_FUNC_GENERATOR] = JS_CLASS_GENERATOR_FUNCTION,-    [JS_FUNC_ASYNC] = JS_CLASS_ASYNC_FUNCTION,-    [JS_FUNC_ASYNC_GENERATOR] = JS_CLASS_ASYNC_GENERATOR_FUNCTION,-};--static JSValue js_closure(JSContext *ctx, JSValue bfunc,-                          JSVarRef **cur_var_refs,-                          JSStackFrame *sf)-{-    JSFunctionBytecode *b;-    JSValue func_obj;-    JSAtom name_atom;--    b = JS_VALUE_GET_PTR(bfunc);-    func_obj = JS_NewObjectClass(ctx, func_kind_to_class_id[b->func_kind]);-    if (JS_IsException(func_obj)) {-        JS_FreeValue(ctx, bfunc);-        return JS_EXCEPTION;-    }-    func_obj = js_closure2(ctx, func_obj, b, cur_var_refs, sf);-    if (JS_IsException(func_obj)) {-        /* bfunc has been freed */-        goto fail;-    }-    name_atom = b->func_name;-    if (name_atom == JS_ATOM_NULL)-        name_atom = JS_ATOM_empty_string;-    js_function_set_properties(ctx, func_obj, name_atom,-                               b->defined_arg_count);--    if (b->func_kind & JS_FUNC_GENERATOR) {-        JSValue proto;-        int proto_class_id;-        /* generators have a prototype field which is used as-           prototype for the generator object */-        if (b->func_kind == JS_FUNC_ASYNC_GENERATOR)-            proto_class_id = JS_CLASS_ASYNC_GENERATOR;-        else-            proto_class_id = JS_CLASS_GENERATOR;-        proto = JS_NewObjectProto(ctx, ctx->class_proto[proto_class_id]);-        if (JS_IsException(proto))-            goto fail;-        JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, proto,-                               JS_PROP_WRITABLE);-    } else if (b->has_prototype) {-        /* add the 'prototype' property: delay instantiation to avoid-           creating cycles for every javascript function. The prototype-           object is created on the fly when first accessed */-        JS_SetConstructorBit(ctx, func_obj, TRUE);-        JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype,-                                  JS_AUTOINIT_ID_PROTOTYPE, NULL,-                                  JS_PROP_WRITABLE);-    }-    return func_obj;- fail:-    /* bfunc is freed when func_obj is freed */-    JS_FreeValue(ctx, func_obj);-    return JS_EXCEPTION;-}--#define JS_DEFINE_CLASS_HAS_HERITAGE     (1 << 0)--static int js_op_define_class(JSContext *ctx, JSValue *sp,-                              JSAtom class_name, int class_flags,-                              JSVarRef **cur_var_refs,-                              JSStackFrame *sf, BOOL is_computed_name)-{-    JSValue bfunc, parent_class, proto = JS_UNDEFINED;-    JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED;-    JSFunctionBytecode *b;--    parent_class = sp[-2];-    bfunc = sp[-1];--    if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE) {-        if (JS_IsNull(parent_class)) {-            parent_proto = JS_NULL;-            parent_class = JS_DupValue(ctx, ctx->function_proto);-        } else {-            if (!JS_IsConstructor(ctx, parent_class)) {-                JS_ThrowTypeError(ctx, "parent class must be constructor");-                goto fail;-            }-            parent_proto = JS_GetProperty(ctx, parent_class, JS_ATOM_prototype);-            if (JS_IsException(parent_proto))-                goto fail;-            if (!JS_IsNull(parent_proto) && !JS_IsObject(parent_proto)) {-                JS_ThrowTypeError(ctx, "parent prototype must be an object or null");-                goto fail;-            }-        }-    } else {-        /* parent_class is JS_UNDEFINED in this case */-        parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]);-        parent_class = JS_DupValue(ctx, ctx->function_proto);-    }-    proto = JS_NewObjectProto(ctx, parent_proto);-    if (JS_IsException(proto))-        goto fail;--    b = JS_VALUE_GET_PTR(bfunc);-    assert(b->func_kind == JS_FUNC_NORMAL);-    ctor = JS_NewObjectProtoClass(ctx, parent_class,-                                  JS_CLASS_BYTECODE_FUNCTION);-    if (JS_IsException(ctor))-        goto fail;-    ctor = js_closure2(ctx, ctor, b, cur_var_refs, sf);-    bfunc = JS_UNDEFINED;-    if (JS_IsException(ctor))-        goto fail;-    js_method_set_home_object(ctx, ctor, proto);-    JS_SetConstructorBit(ctx, ctor, TRUE);--    JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length,-                           JS_NewInt32(ctx, b->defined_arg_count),-                           JS_PROP_CONFIGURABLE);--    if (is_computed_name) {-        if (JS_DefineObjectNameComputed(ctx, ctor, sp[-3],-                                        JS_PROP_CONFIGURABLE) < 0)-            goto fail;-    } else {-        if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0)-            goto fail;-    }--    /* the constructor property must be first. It can be overriden by-       computed property names */-    if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,-                               JS_DupValue(ctx, ctor),-                               JS_PROP_CONFIGURABLE |-                               JS_PROP_WRITABLE | JS_PROP_THROW) < 0)-        goto fail;-    /* set the prototype property */-    if (JS_DefinePropertyValue(ctx, ctor, JS_ATOM_prototype,-                               JS_DupValue(ctx, proto), JS_PROP_THROW) < 0)-        goto fail;-    set_cycle_flag(ctx, ctor);-    set_cycle_flag(ctx, proto);--    JS_FreeValue(ctx, parent_proto);-    JS_FreeValue(ctx, parent_class);--    sp[-2] = ctor;-    sp[-1] = proto;-    return 0;- fail:-    JS_FreeValue(ctx, parent_class);-    JS_FreeValue(ctx, parent_proto);-    JS_FreeValue(ctx, bfunc);-    JS_FreeValue(ctx, proto);-    JS_FreeValue(ctx, ctor);-    sp[-2] = JS_UNDEFINED;-    sp[-1] = JS_UNDEFINED;-    return -1;-}--static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)-{-    struct list_head *el, *el1;-    JSVarRef *var_ref;-    int var_idx;--    list_for_each_safe(el, el1, &sf->var_ref_list) {-        var_ref = list_entry(el, JSVarRef, header.link);-        var_idx = var_ref->var_idx;-        if (var_ref->is_arg)-            var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]);-        else-            var_ref->value = JS_DupValueRT(rt, sf->var_buf[var_idx]);-        var_ref->pvalue = &var_ref->value;-        /* the reference is no longer to a local variable */-        var_ref->is_detached = TRUE;-        add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);-    }-}--static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_arg)-{-    struct list_head *el, *el1;-    JSVarRef *var_ref;-    int var_idx = idx;--    list_for_each_safe(el, el1, &sf->var_ref_list) {-        var_ref = list_entry(el, JSVarRef, header.link);-        if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) {-            var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]);-            var_ref->pvalue = &var_ref->value;-            list_del(&var_ref->header.link);-            /* the reference is no longer to a local variable */-            var_ref->is_detached = TRUE;-            add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);-        }-    }-}--#define JS_CALL_FLAG_COPY_ARGV   (1 << 1)-#define JS_CALL_FLAG_GENERATOR   (1 << 2)--static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,-                                  JSValueConst this_obj,-                                  int argc, JSValueConst *argv, int flags)-{-    JSRuntime *rt = ctx->rt;-    JSCFunctionType func;-    JSObject *p;-    JSStackFrame sf_s, *sf = &sf_s, *prev_sf;-    JSValue ret_val;-    JSValueConst *arg_buf;-    int arg_count, i;-    JSCFunctionEnum cproto;--    p = JS_VALUE_GET_OBJ(func_obj);-    cproto = p->u.cfunc.cproto;-    arg_count = p->u.cfunc.length;--    /* better to always check stack overflow */-    if (js_check_stack_overflow(rt, sizeof(arg_buf[0]) * arg_count))-        return JS_ThrowStackOverflow(ctx);--    prev_sf = rt->current_stack_frame;-    sf->prev_frame = prev_sf;-    rt->current_stack_frame = sf;-    ctx = p->u.cfunc.realm; /* change the current realm */-    -#ifdef CONFIG_BIGNUM-    /* we only propagate the bignum mode as some runtime functions-       test it */-    if (prev_sf)-        sf->js_mode = prev_sf->js_mode & JS_MODE_MATH;-    else-        sf->js_mode = 0;-#else-    sf->js_mode = 0;-#endif-    sf->cur_func = (JSValue)func_obj;-    sf->arg_count = argc;-    arg_buf = argv;--    if (unlikely(argc < arg_count)) {-        /* ensure that at least argc_count arguments are readable */-        arg_buf = alloca(sizeof(arg_buf[0]) * arg_count);-        for(i = 0; i < argc; i++)-            arg_buf[i] = argv[i];-        for(i = argc; i < arg_count; i++)-            arg_buf[i] = JS_UNDEFINED;-        sf->arg_count = arg_count;-    }-    sf->arg_buf = (JSValue*)arg_buf;--    func = p->u.cfunc.c_function;-    switch(cproto) {-    case JS_CFUNC_constructor:-    case JS_CFUNC_constructor_or_func:-        if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) {-            if (cproto == JS_CFUNC_constructor) {-            not_a_constructor:-                ret_val = JS_ThrowTypeError(ctx, "must be called with new");-                break;-            } else {-                this_obj = JS_UNDEFINED;-            }-        }-        /* here this_obj is new_target */-        /* fall thru */-    case JS_CFUNC_generic:-        ret_val = func.generic(ctx, this_obj, argc, arg_buf);-        break;-    case JS_CFUNC_constructor_magic:-    case JS_CFUNC_constructor_or_func_magic:-        if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) {-            if (cproto == JS_CFUNC_constructor_magic) {-                goto not_a_constructor;-            } else {-                this_obj = JS_UNDEFINED;-            }-        }-        /* fall thru */-    case JS_CFUNC_generic_magic:-        ret_val = func.generic_magic(ctx, this_obj, argc, arg_buf,-                                     p->u.cfunc.magic);-        break;-    case JS_CFUNC_getter:-        ret_val = func.getter(ctx, this_obj);-        break;-    case JS_CFUNC_setter:-        ret_val = func.setter(ctx, this_obj, arg_buf[0]);-        break;-    case JS_CFUNC_getter_magic:-        ret_val = func.getter_magic(ctx, this_obj, p->u.cfunc.magic);-        break;-    case JS_CFUNC_setter_magic:-        ret_val = func.setter_magic(ctx, this_obj, arg_buf[0], p->u.cfunc.magic);-        break;-    case JS_CFUNC_f_f:-        {-            double d1;--            if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) {-                ret_val = JS_EXCEPTION;-                break;-            }-            ret_val = JS_NewFloat64(ctx, func.f_f(d1));-        }-        break;-    case JS_CFUNC_f_f_f:-        {-            double d1, d2;--            if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) {-                ret_val = JS_EXCEPTION;-                break;-            }-            if (unlikely(JS_ToFloat64(ctx, &d2, arg_buf[1]))) {-                ret_val = JS_EXCEPTION;-                break;-            }-            ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2));-        }-        break;-    case JS_CFUNC_iterator_next:-        {-            int done;-            ret_val = func.iterator_next(ctx, this_obj, argc, arg_buf,-                                         &done, p->u.cfunc.magic);-            if (!JS_IsException(ret_val) && done != 2) {-                ret_val = js_create_iterator_result(ctx, ret_val, done);-            }-        }-        break;-    default:-        abort();-    }--    rt->current_stack_frame = sf->prev_frame;-    return ret_val;-}--static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,-                                      JSValueConst this_obj,-                                      int argc, JSValueConst *argv, int flags)-{-    JSObject *p;-    JSBoundFunction *bf;-    JSValueConst *arg_buf, new_target;-    int arg_count, i;--    p = JS_VALUE_GET_OBJ(func_obj);-    bf = p->u.bound_function;-    arg_count = bf->argc + argc;-    if (js_check_stack_overflow(ctx->rt, sizeof(JSValue) * arg_count))-        return JS_ThrowStackOverflow(ctx);-    arg_buf = alloca(sizeof(JSValue) * arg_count);-    for(i = 0; i < bf->argc; i++) {-        arg_buf[i] = bf->argv[i];-    }-    for(i = 0; i < argc; i++) {-        arg_buf[bf->argc + i] = argv[i];-    }-    if (flags & JS_CALL_FLAG_CONSTRUCTOR) {-        new_target = this_obj;-        if (js_same_value(ctx, func_obj, new_target))-            new_target = bf->func_obj;-        return JS_CallConstructor2(ctx, bf->func_obj, new_target,-                                   arg_count, arg_buf);-    } else {-        return JS_Call(ctx, bf->func_obj, bf->this_val,-                       arg_count, arg_buf);-    }-}--/* argument of OP_special_object */-typedef enum {-    OP_SPECIAL_OBJECT_ARGUMENTS,-    OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS,-    OP_SPECIAL_OBJECT_THIS_FUNC,-    OP_SPECIAL_OBJECT_NEW_TARGET,-    OP_SPECIAL_OBJECT_HOME_OBJECT,-    OP_SPECIAL_OBJECT_VAR_OBJECT,-    OP_SPECIAL_OBJECT_IMPORT_META,-} OPSpecialObjectEnum;--#define FUNC_RET_AWAIT      0-#define FUNC_RET_YIELD      1-#define FUNC_RET_YIELD_STAR 2--/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */-static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,-                               JSValueConst this_obj, JSValueConst new_target,-                               int argc, JSValue *argv, int flags)-{-    JSRuntime *rt = caller_ctx->rt;-    JSContext *ctx;-    JSObject *p;-    JSFunctionBytecode *b;-    JSStackFrame sf_s, *sf = &sf_s;-    const uint8_t *pc;-    int opcode, arg_allocated_size, i;-    JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval;-    JSVarRef **var_refs;-    size_t alloca_size;--#if !DIRECT_DISPATCH-#define SWITCH(pc)      switch (opcode = *pc++)-#define CASE(op)        case op-#define DEFAULT         default-#define BREAK           break-#else-    static const void * const dispatch_table[256] = {-#define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id,-#if SHORT_OPCODES-#define def(id, size, n_pop, n_push, f)-#else                                                     -#define def(id, size, n_pop, n_push, f) && case_default,-#endif-#include "quickjs-opcode.h"-        [ OP_COUNT ... 255 ] = &&case_default-    };-#define SWITCH(pc)      goto *dispatch_table[opcode = *pc++];-#define CASE(op)        case_ ## op-#define DEFAULT         case_default-#define BREAK           SWITCH(pc)-#endif--    if (js_poll_interrupts(caller_ctx))-        return JS_EXCEPTION;-    if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) {-        if (flags & JS_CALL_FLAG_GENERATOR) {-            JSAsyncFunctionState *s = JS_VALUE_GET_PTR(func_obj);-            /* func_obj get contains a pointer to JSFuncAsyncState */-            /* the stack frame is already allocated */-            sf = &s->frame;-            p = JS_VALUE_GET_OBJ(sf->cur_func);-            b = p->u.func.function_bytecode;-            ctx = b->realm;-            var_refs = p->u.func.var_refs;-            local_buf = arg_buf = sf->arg_buf;-            var_buf = sf->var_buf;-            stack_buf = sf->var_buf + b->var_count;-            sp = sf->cur_sp;-            sf->cur_sp = NULL; /* cur_sp is NULL if the function is running */-            pc = sf->cur_pc;-            sf->prev_frame = rt->current_stack_frame;-            rt->current_stack_frame = sf;-            if (s->throw_flag)-                goto exception;-            else-                goto restart;-        } else {-            goto not_a_function;-        }-    }-    p = JS_VALUE_GET_OBJ(func_obj);-    if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {-        JSClassCall *call_func;-        call_func = rt->class_array[p->class_id].call;-        if (!call_func) {-        not_a_function:-            return JS_ThrowTypeError(caller_ctx, "not a function");-        }-        return call_func(caller_ctx, func_obj, this_obj, argc,-                         (JSValueConst *)argv, flags);-    }-    b = p->u.func.function_bytecode;--    if (unlikely(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) {-        arg_allocated_size = b->arg_count;-    } else {-        arg_allocated_size = 0;-    }--    alloca_size = sizeof(JSValue) * (arg_allocated_size + b->var_count +-                                     b->stack_size);-    if (js_check_stack_overflow(rt, alloca_size))-        return JS_ThrowStackOverflow(caller_ctx);--    sf->js_mode = b->js_mode;-    arg_buf = argv;-    sf->arg_count = argc;-    sf->cur_func = (JSValue)func_obj;-    init_list_head(&sf->var_ref_list);-    var_refs = p->u.func.var_refs;--    local_buf = alloca(alloca_size);-    if (unlikely(arg_allocated_size)) {-        int n = min_int(argc, b->arg_count);-        arg_buf = local_buf;-        for(i = 0; i < n; i++)-            arg_buf[i] = JS_DupValue(caller_ctx, argv[i]);-        for(; i < b->arg_count; i++)-            arg_buf[i] = JS_UNDEFINED;-        sf->arg_count = b->arg_count;-    }-    var_buf = local_buf + arg_allocated_size;-    sf->var_buf = var_buf;-    sf->arg_buf = arg_buf;--    for(i = 0; i < b->var_count; i++)-        var_buf[i] = JS_UNDEFINED;--    stack_buf = var_buf + b->var_count;-    sp = stack_buf;-    pc = b->byte_code_buf;-    sf->prev_frame = rt->current_stack_frame;-    rt->current_stack_frame = sf;-    ctx = b->realm; /* set the current realm */-    - restart:-    for(;;) {-        int call_argc;-        JSValue *call_argv;--        SWITCH(pc) {-        CASE(OP_push_i32):-            *sp++ = JS_NewInt32(ctx, get_u32(pc));-            pc += 4;-            BREAK;-        CASE(OP_push_const):-            *sp++ = JS_DupValue(ctx, b->cpool[get_u32(pc)]);-            pc += 4;-            BREAK;-#if SHORT_OPCODES-        CASE(OP_push_minus1):-        CASE(OP_push_0):-        CASE(OP_push_1):-        CASE(OP_push_2):-        CASE(OP_push_3):-        CASE(OP_push_4):-        CASE(OP_push_5):-        CASE(OP_push_6):-        CASE(OP_push_7):-            *sp++ = JS_NewInt32(ctx, opcode - OP_push_0);-            BREAK;-        CASE(OP_push_i8):-            *sp++ = JS_NewInt32(ctx, get_i8(pc));-            pc += 1;-            BREAK;-        CASE(OP_push_i16):-            *sp++ = JS_NewInt32(ctx, get_i16(pc));-            pc += 2;-            BREAK;-        CASE(OP_push_const8):-            *sp++ = JS_DupValue(ctx, b->cpool[*pc++]);-            BREAK;-        CASE(OP_fclosure8):-            *sp++ = js_closure(ctx, JS_DupValue(ctx, b->cpool[*pc++]), var_refs, sf);-            if (unlikely(JS_IsException(sp[-1])))-                goto exception;-            BREAK;-        CASE(OP_push_empty_string):-            *sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);-            BREAK;-        CASE(OP_get_length):-            {-                JSValue val;--                val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);-                if (unlikely(JS_IsException(val)))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = val;-            }-            BREAK;-#endif-        CASE(OP_push_atom_value):-            *sp++ = JS_AtomToValue(ctx, get_u32(pc));-            pc += 4;-            BREAK;-        CASE(OP_undefined):-            *sp++ = JS_UNDEFINED;-            BREAK;-        CASE(OP_null):-            *sp++ = JS_NULL;-            BREAK;-        CASE(OP_push_this):-            /* OP_push_this is only called at the start of a function */-            {-                JSValue val;-                if (!(b->js_mode & JS_MODE_STRICT)) {-                    uint32_t tag = JS_VALUE_GET_TAG(this_obj);-                    if (likely(tag == JS_TAG_OBJECT))-                        goto normal_this;-                    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) {-                        val = JS_DupValue(ctx, ctx->global_obj);-                    } else {-                        val = JS_ToObject(ctx, this_obj);-                        if (JS_IsException(val))-                            goto exception;-                    }-                } else {-                normal_this:-                    val = JS_DupValue(ctx, this_obj);-                }-                *sp++ = val;-            }-            BREAK;-        CASE(OP_push_false):-            *sp++ = JS_FALSE;-            BREAK;-        CASE(OP_push_true):-            *sp++ = JS_TRUE;-            BREAK;-        CASE(OP_object):-            *sp++ = JS_NewObject(ctx);-            if (unlikely(JS_IsException(sp[-1])))-                goto exception;-            BREAK;-        CASE(OP_special_object):-            {-                int arg = *pc++;-                switch(arg) {-                case OP_SPECIAL_OBJECT_ARGUMENTS:-                    *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);-                    if (unlikely(JS_IsException(sp[-1])))-                        goto exception;-                    break;-                case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:-                    *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,-                                                      sf, min_int(argc, b->arg_count));-                    if (unlikely(JS_IsException(sp[-1])))-                        goto exception;-                    break;-                case OP_SPECIAL_OBJECT_THIS_FUNC:-                    *sp++ = JS_DupValue(ctx, sf->cur_func);-                    break;-                case OP_SPECIAL_OBJECT_NEW_TARGET:-                    *sp++ = JS_DupValue(ctx, new_target);-                    break;-                case OP_SPECIAL_OBJECT_HOME_OBJECT:-                    {-                        JSObject *p1;-                        p1 = p->u.func.home_object;-                        if (unlikely(!p1))-                            *sp++ = JS_UNDEFINED;-                        else-                            *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));-                    }-                    break;-                case OP_SPECIAL_OBJECT_VAR_OBJECT:-                    *sp++ = JS_NewObjectProto(ctx, JS_NULL);-                    if (unlikely(JS_IsException(sp[-1])))-                        goto exception;-                    break;-                case OP_SPECIAL_OBJECT_IMPORT_META:-                    *sp++ = js_import_meta(ctx);-                    if (unlikely(JS_IsException(sp[-1])))-                        goto exception;-                    break;-                default:-                    abort();-                }-            }-            BREAK;-        CASE(OP_rest):-            {-                int first = get_u16(pc);-                pc += 2;-                *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);-                if (unlikely(JS_IsException(sp[-1])))-                    goto exception;-            }-            BREAK;--        CASE(OP_drop):-            JS_FreeValue(ctx, sp[-1]);-            sp--;-            BREAK;-        CASE(OP_nip):-            JS_FreeValue(ctx, sp[-2]);-            sp[-2] = sp[-1];-            sp--;-            BREAK;-        CASE(OP_nip1): /* a b c -> b c */-            JS_FreeValue(ctx, sp[-3]);-            sp[-3] = sp[-2];-            sp[-2] = sp[-1];-            sp--;-            BREAK;-        CASE(OP_dup):-            sp[0] = JS_DupValue(ctx, sp[-1]);-            sp++;-            BREAK;-        CASE(OP_dup2): /* a b -> a b a b */-            sp[0] = JS_DupValue(ctx, sp[-2]);-            sp[1] = JS_DupValue(ctx, sp[-1]);-            sp += 2;-            BREAK;-        CASE(OP_dup3): /* a b c -> a b c a b c */-            sp[0] = JS_DupValue(ctx, sp[-3]);-            sp[1] = JS_DupValue(ctx, sp[-2]);-            sp[2] = JS_DupValue(ctx, sp[-1]);-            sp += 3;-            BREAK;-        CASE(OP_dup1): /* a b -> a a b */-            sp[0] = sp[-1];-            sp[-1] = JS_DupValue(ctx, sp[-2]);-            sp++;-            BREAK;-        CASE(OP_insert2): /* obj a -> a obj a (dup_x1) */-            sp[0] = sp[-1];-            sp[-1] = sp[-2];-            sp[-2] = JS_DupValue(ctx, sp[0]);-            sp++;-            BREAK;-        CASE(OP_insert3): /* obj prop a -> a obj prop a (dup_x2) */-            sp[0] = sp[-1];-            sp[-1] = sp[-2];-            sp[-2] = sp[-3];-            sp[-3] = JS_DupValue(ctx, sp[0]);-            sp++;-            BREAK;-        CASE(OP_insert4): /* this obj prop a -> a this obj prop a */-            sp[0] = sp[-1];-            sp[-1] = sp[-2];-            sp[-2] = sp[-3];-            sp[-3] = sp[-4];-            sp[-4] = JS_DupValue(ctx, sp[0]);-            sp++;-            BREAK;-        CASE(OP_perm3): /* obj a b -> a obj b (213) */-            {-                JSValue tmp;-                tmp = sp[-2];-                sp[-2] = sp[-3];-                sp[-3] = tmp;-            }-            BREAK;-        CASE(OP_rot3l): /* x a b -> a b x (231) */-            {-                JSValue tmp;-                tmp = sp[-3];-                sp[-3] = sp[-2];-                sp[-2] = sp[-1];-                sp[-1] = tmp;-            }-            BREAK;-        CASE(OP_rot4l): /* x a b c -> a b c x */-            {-                JSValue tmp;-                tmp = sp[-4];-                sp[-4] = sp[-3];-                sp[-3] = sp[-2];-                sp[-2] = sp[-1];-                sp[-1] = tmp;-            }-            BREAK;-        CASE(OP_rot5l): /* x a b c d -> a b c d x */-            {-                JSValue tmp;-                tmp = sp[-5];-                sp[-5] = sp[-4];-                sp[-4] = sp[-3];-                sp[-3] = sp[-2];-                sp[-2] = sp[-1];-                sp[-1] = tmp;-            }-            BREAK;-        CASE(OP_rot3r): /* a b x -> x a b (312) */-            {-                JSValue tmp;-                tmp = sp[-1];-                sp[-1] = sp[-2];-                sp[-2] = sp[-3];-                sp[-3] = tmp;-            }-            BREAK;-        CASE(OP_perm4): /* obj prop a b -> a obj prop b */-            {-                JSValue tmp;-                tmp = sp[-2];-                sp[-2] = sp[-3];-                sp[-3] = sp[-4];-                sp[-4] = tmp;-            }-            BREAK;-        CASE(OP_perm5): /* this obj prop a b -> a this obj prop b */-            {-                JSValue tmp;-                tmp = sp[-2];-                sp[-2] = sp[-3];-                sp[-3] = sp[-4];-                sp[-4] = sp[-5];-                sp[-5] = tmp;-            }-            BREAK;-        CASE(OP_swap): /* a b -> b a */-            {-                JSValue tmp;-                tmp = sp[-2];-                sp[-2] = sp[-1];-                sp[-1] = tmp;-            }-            BREAK;-        CASE(OP_swap2): /* a b c d -> c d a b */-            {-                JSValue tmp1, tmp2;-                tmp1 = sp[-4];-                tmp2 = sp[-3];-                sp[-4] = sp[-2];-                sp[-3] = sp[-1];-                sp[-2] = tmp1;-                sp[-1] = tmp2;-            }-            BREAK;--        CASE(OP_fclosure):-            {-                JSValue bfunc = JS_DupValue(ctx, b->cpool[get_u32(pc)]);-                pc += 4;-                *sp++ = js_closure(ctx, bfunc, var_refs, sf);-                if (unlikely(JS_IsException(sp[-1])))-                    goto exception;-            }-            BREAK;-#if SHORT_OPCODES-        CASE(OP_call0):-        CASE(OP_call1):-        CASE(OP_call2):-        CASE(OP_call3):-            call_argc = opcode - OP_call0;-            goto has_call_argc;-#endif-        CASE(OP_call):-        CASE(OP_tail_call):-            {-                call_argc = get_u16(pc);-                pc += 2;-                goto has_call_argc;-            has_call_argc:-                call_argv = sp - call_argc;-                sf->cur_pc = pc;-                ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED,-                                          JS_UNDEFINED, call_argc, call_argv, 0);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                if (opcode == OP_tail_call)-                    goto done;-                for(i = -1; i < call_argc; i++)-                    JS_FreeValue(ctx, call_argv[i]);-                sp -= call_argc + 1;-                *sp++ = ret_val;-            }-            BREAK;-        CASE(OP_call_constructor):-            {-                call_argc = get_u16(pc);-                pc += 2;-                call_argv = sp - call_argc;-                sf->cur_pc = pc;-                ret_val = JS_CallConstructorInternal(ctx, call_argv[-2],-                                                     call_argv[-1],-                                                     call_argc, call_argv, 0);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                for(i = -2; i < call_argc; i++)-                    JS_FreeValue(ctx, call_argv[i]);-                sp -= call_argc + 2;-                *sp++ = ret_val;-            }-            BREAK;-        CASE(OP_call_method):-        CASE(OP_tail_call_method):-            {-                call_argc = get_u16(pc);-                pc += 2;-                call_argv = sp - call_argc;-                sf->cur_pc = pc;-                ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2],-                                          JS_UNDEFINED, call_argc, call_argv, 0);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                if (opcode == OP_tail_call_method)-                    goto done;-                for(i = -2; i < call_argc; i++)-                    JS_FreeValue(ctx, call_argv[i]);-                sp -= call_argc + 2;-                *sp++ = ret_val;-            }-            BREAK;-        CASE(OP_array_from):-            {-                int i, ret;--                call_argc = get_u16(pc);-                pc += 2;-                ret_val = JS_NewArray(ctx);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                call_argv = sp - call_argc;-                for(i = 0; i < call_argc; i++) {-                    ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],-                                                 JS_PROP_C_W_E | JS_PROP_THROW);-                    call_argv[i] = JS_UNDEFINED;-                    if (ret < 0) {-                        JS_FreeValue(ctx, ret_val);-                        goto exception;-                    }-                }-                sp -= call_argc;-                *sp++ = ret_val;-            }-            BREAK;--        CASE(OP_apply):-            {-                int magic;-                magic = get_u16(pc);-                pc += 2;--                ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                JS_FreeValue(ctx, sp[-3]);-                JS_FreeValue(ctx, sp[-2]);-                JS_FreeValue(ctx, sp[-1]);-                sp -= 3;-                *sp++ = ret_val;-            }-            BREAK;-        CASE(OP_return):-            ret_val = *--sp;-            goto done;-        CASE(OP_return_undef):-            ret_val = JS_UNDEFINED;-            goto done;--        CASE(OP_check_ctor_return):-            /* return TRUE if 'this' should be returned */-            if (!JS_IsObject(sp[-1])) {-                if (!JS_IsUndefined(sp[-1])) {-                    JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined");-                    goto exception;-                }-                sp[0] = JS_TRUE;-            } else {-                sp[0] = JS_FALSE;-            }-            sp++;-            BREAK;-        CASE(OP_check_ctor):-            if (JS_IsUndefined(new_target)) {-                JS_ThrowTypeError(caller_ctx, "class constructors must be invoked with 'new'");-                goto exception;-            }-            BREAK;-        CASE(OP_check_brand):-            if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0)-                goto exception;-            BREAK;-        CASE(OP_add_brand):-            if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)-                goto exception;-            JS_FreeValue(ctx, sp[-2]);-            JS_FreeValue(ctx, sp[-1]);-            sp -= 2;-            BREAK;-            -        CASE(OP_throw):-            JS_Throw(ctx, *--sp);-            goto exception;--        CASE(OP_throw_var):-#define JS_THROW_VAR_RO             0-#define JS_THROW_VAR_REDECL         1-#define JS_THROW_VAR_UNINITIALIZED  2-#define JS_THROW_VAR_DELETE_SUPER   3-            {-                JSAtom atom;-                int type;-                atom = get_u32(pc);-                type = pc[4];-                pc += 5;-                if (type == JS_THROW_VAR_RO)-                    JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, atom);-                else-                if (type == JS_THROW_VAR_REDECL)-                    JS_ThrowSyntaxErrorVarRedeclaration(ctx, atom);-                else-                if (type == JS_THROW_VAR_UNINITIALIZED)-                    JS_ThrowReferenceErrorUninitialized(ctx, atom);-                else-                if (type == JS_THROW_VAR_DELETE_SUPER)-                    JS_ThrowReferenceError(ctx, "unsupported reference to 'super'");-                else-                    JS_ThrowInternalError(ctx, "invalid throw var type %d", type);-            }-            goto exception;--        CASE(OP_eval):-            {-                JSValueConst obj;-                int scope_idx;-                call_argc = get_u16(pc);-                scope_idx = get_u16(pc + 2) - 1;-                pc += 4;-                call_argv = sp - call_argc;-                sf->cur_pc = pc;-                if (js_same_value(ctx, call_argv[-1], ctx->eval_obj)) {-                    if (call_argc >= 1)-                        obj = call_argv[0];-                    else-                        obj = JS_UNDEFINED;-                    ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj,-                                            JS_EVAL_TYPE_DIRECT, scope_idx);-                } else {-                    ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED,-                                              JS_UNDEFINED, call_argc, call_argv, 0);-                }-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                for(i = -1; i < call_argc; i++)-                    JS_FreeValue(ctx, call_argv[i]);-                sp -= call_argc + 1;-                *sp++ = ret_val;-            }-            BREAK;-            /* could merge with OP_apply */-        CASE(OP_apply_eval):-            {-                int scope_idx;-                uint32_t len;-                JSValue *tab;-                JSValueConst obj;--                scope_idx = get_u16(pc) - 1;-                pc += 2;-                tab = build_arg_list(ctx, &len, sp[-1]);-                if (!tab)-                    goto exception;-                if (js_same_value(ctx, sp[-2], ctx->eval_obj)) {-                    if (len >= 1)-                        obj = tab[0];-                    else-                        obj = JS_UNDEFINED;-                    ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj,-                                            JS_EVAL_TYPE_DIRECT, scope_idx);-                } else {-                    ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,-                                      (JSValueConst *)tab);-                }-                free_arg_list(ctx, tab, len);-                if (unlikely(JS_IsException(ret_val)))-                    goto exception;-                JS_FreeValue(ctx, sp[-2]);-                JS_FreeValue(ctx, sp[-1]);-                sp -= 2;-                *sp++ = ret_val;-            }-            BREAK;--        CASE(OP_regexp):-            {-                sp[-2] = js_regexp_constructor_internal(ctx, JS_UNDEFINED,-                                                        sp[-2], sp[-1]);-                sp--;-            }-            BREAK;--        CASE(OP_get_super):-            {-                JSValue proto;-                proto = JS_GetPrototype(ctx, sp[-1]);-                if (JS_IsException(proto))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = proto;-            }-            BREAK;--        CASE(OP_import):-            {-                JSValue val;-                val = js_dynamic_import(ctx, sp[-1]);-                if (JS_IsException(val))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = val;-            }-            BREAK;--        CASE(OP_check_var):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                ret = JS_CheckGlobalVar(ctx, atom);-                if (ret < 0)-                    goto exception;-                *sp++ = JS_NewBool(ctx, ret);-            }-            BREAK;--        CASE(OP_get_var_undef):-        CASE(OP_get_var):-            {-                JSValue val;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef);-                if (unlikely(JS_IsException(val)))-                    goto exception;-                *sp++ = val;-            }-            BREAK;--        CASE(OP_put_var):-        CASE(OP_put_var_init):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var);-                sp--;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_put_var_strict):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                /* sp[-2] is JS_TRUE or JS_FALSE */-                if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) {-                    JS_ThrowReferenceErrorNotDefined(ctx, atom);-                    goto exception;-                }-                ret = JS_SetGlobalVar(ctx, atom, sp[-1], 2);-                sp -= 2;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_check_define_var):-            {-                JSAtom atom;-                int flags;-                atom = get_u32(pc);-                flags = pc[4];-                pc += 5;-                if (JS_CheckDefineGlobalVar(ctx, atom, flags))-                    goto exception;-            }-            BREAK;-        CASE(OP_define_var):-            {-                JSAtom atom;-                int flags;-                atom = get_u32(pc);-                flags = pc[4];-                pc += 5;-                if (JS_DefineGlobalVar(ctx, atom, flags))-                    goto exception;-            }-            BREAK;-        CASE(OP_define_func):-            {-                JSAtom atom;-                int flags;-                atom = get_u32(pc);-                flags = pc[4];-                pc += 5;-                if (JS_DefineGlobalFunction(ctx, atom, sp[-1], flags))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp--;-            }-            BREAK;--        CASE(OP_get_loc):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                sp[0] = JS_DupValue(ctx, var_buf[idx]);-                sp++;-            }-            BREAK;-        CASE(OP_put_loc):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, &var_buf[idx], sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_set_loc):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, &var_buf[idx], JS_DupValue(ctx, sp[-1]));-            }-            BREAK;-        CASE(OP_get_arg):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                sp[0] = JS_DupValue(ctx, arg_buf[idx]);-                sp++;-            }-            BREAK;-        CASE(OP_put_arg):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, &arg_buf[idx], sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_set_arg):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, &arg_buf[idx], JS_DupValue(ctx, sp[-1]));-            }-            BREAK;--#if SHORT_OPCODES-        CASE(OP_get_loc8): *sp++ = JS_DupValue(ctx, var_buf[*pc++]); BREAK;-        CASE(OP_put_loc8): set_value(ctx, &var_buf[*pc++], *--sp); BREAK;-        CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], JS_DupValue(ctx, sp[-1])); BREAK;--        CASE(OP_get_loc0): *sp++ = JS_DupValue(ctx, var_buf[0]); BREAK;-        CASE(OP_get_loc1): *sp++ = JS_DupValue(ctx, var_buf[1]); BREAK;-        CASE(OP_get_loc2): *sp++ = JS_DupValue(ctx, var_buf[2]); BREAK;-        CASE(OP_get_loc3): *sp++ = JS_DupValue(ctx, var_buf[3]); BREAK;-        CASE(OP_put_loc0): set_value(ctx, &var_buf[0], *--sp); BREAK;-        CASE(OP_put_loc1): set_value(ctx, &var_buf[1], *--sp); BREAK;-        CASE(OP_put_loc2): set_value(ctx, &var_buf[2], *--sp); BREAK;-        CASE(OP_put_loc3): set_value(ctx, &var_buf[3], *--sp); BREAK;-        CASE(OP_set_loc0): set_value(ctx, &var_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_loc1): set_value(ctx, &var_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_loc2): set_value(ctx, &var_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_loc3): set_value(ctx, &var_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_get_arg0): *sp++ = JS_DupValue(ctx, arg_buf[0]); BREAK;-        CASE(OP_get_arg1): *sp++ = JS_DupValue(ctx, arg_buf[1]); BREAK;-        CASE(OP_get_arg2): *sp++ = JS_DupValue(ctx, arg_buf[2]); BREAK;-        CASE(OP_get_arg3): *sp++ = JS_DupValue(ctx, arg_buf[3]); BREAK;-        CASE(OP_put_arg0): set_value(ctx, &arg_buf[0], *--sp); BREAK;-        CASE(OP_put_arg1): set_value(ctx, &arg_buf[1], *--sp); BREAK;-        CASE(OP_put_arg2): set_value(ctx, &arg_buf[2], *--sp); BREAK;-        CASE(OP_put_arg3): set_value(ctx, &arg_buf[3], *--sp); BREAK;-        CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_get_var_ref0): *sp++ = JS_DupValue(ctx, *var_refs[0]->pvalue); BREAK;-        CASE(OP_get_var_ref1): *sp++ = JS_DupValue(ctx, *var_refs[1]->pvalue); BREAK;-        CASE(OP_get_var_ref2): *sp++ = JS_DupValue(ctx, *var_refs[2]->pvalue); BREAK;-        CASE(OP_get_var_ref3): *sp++ = JS_DupValue(ctx, *var_refs[3]->pvalue); BREAK;-        CASE(OP_put_var_ref0): set_value(ctx, var_refs[0]->pvalue, *--sp); BREAK;-        CASE(OP_put_var_ref1): set_value(ctx, var_refs[1]->pvalue, *--sp); BREAK;-        CASE(OP_put_var_ref2): set_value(ctx, var_refs[2]->pvalue, *--sp); BREAK;-        CASE(OP_put_var_ref3): set_value(ctx, var_refs[3]->pvalue, *--sp); BREAK;-        CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;-        CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;-#endif--        CASE(OP_get_var_ref):-            {-                int idx;-                JSValue val;-                idx = get_u16(pc);-                pc += 2;-                val = *var_refs[idx]->pvalue;-                sp[0] = JS_DupValue(ctx, val);-                sp++;-            }-            BREAK;-        CASE(OP_put_var_ref):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_set_var_ref):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, var_refs[idx]->pvalue, JS_DupValue(ctx, sp[-1]));-            }-            BREAK;-        CASE(OP_get_var_ref_check):-            {-                int idx;-                JSValue val;-                idx = get_u16(pc);-                pc += 2;-                val = *var_refs[idx]->pvalue;-                if (unlikely(JS_IsUninitialized(val))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);-                    goto exception;-                }-                sp[0] = JS_DupValue(ctx, val);-                sp++;-            }-            BREAK;-        CASE(OP_put_var_ref_check):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);-                    goto exception;-                }-                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_put_var_ref_check_init):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);-                    goto exception;-                }-                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_set_loc_uninitialized):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                set_value(ctx, &var_buf[idx], JS_UNINITIALIZED);-            }-            BREAK;-        CASE(OP_get_loc_check):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                if (unlikely(JS_IsUninitialized(var_buf[idx]))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);-                    goto exception;-                }-                sp[0] = JS_DupValue(ctx, var_buf[idx]);-                sp++;-            }-            BREAK;-        CASE(OP_put_loc_check):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                if (unlikely(JS_IsUninitialized(var_buf[idx]))) {-                    JS_ThrowReferenceErrorUninitialized(ctx, JS_ATOM_NULL);-                    goto exception;-                }-                set_value(ctx, &var_buf[idx], sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_put_loc_check_init):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                if (unlikely(!JS_IsUninitialized(var_buf[idx]))) {-                    JS_ThrowReferenceError(ctx, "'this' can be initialized only once");-                    goto exception;-                }-                set_value(ctx, &var_buf[idx], sp[-1]);-                sp--;-            }-            BREAK;-        CASE(OP_close_loc):-            {-                int idx;-                idx = get_u16(pc);-                pc += 2;-                close_lexical_var(ctx, sf, idx, FALSE);-            }-            BREAK;--        CASE(OP_make_loc_ref):-        CASE(OP_make_arg_ref):-        CASE(OP_make_var_ref_ref):-            {-                JSVarRef *var_ref;-                JSProperty *pr;-                JSAtom atom;-                int idx;-                atom = get_u32(pc);-                idx = get_u16(pc + 4);-                pc += 6;-                *sp++ = JS_NewObjectProto(ctx, JS_NULL);-                if (unlikely(JS_IsException(sp[-1])))-                    goto exception;-                if (opcode == OP_make_var_ref_ref) {-                    var_ref = var_refs[idx];-                    var_ref->header.ref_count++;-                } else {-                    var_ref = get_var_ref(ctx, sf, idx, opcode == OP_make_arg_ref);-                    if (!var_ref)-                        goto exception;-                }-                pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom,-                                  JS_PROP_WRITABLE | JS_PROP_VARREF);-                if (!pr) {-                    free_var_ref(rt, var_ref);-                    goto exception;-                }-                pr->u.var_ref = var_ref;-                *sp++ = JS_AtomToValue(ctx, atom);-            }-            BREAK;-        CASE(OP_make_var_ref):-            {-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                if (JS_GetGlobalVarRef(ctx, atom, sp))-                    goto exception;-                sp += 2;-            }-            BREAK;--        CASE(OP_goto):-            pc += (int32_t)get_u32(pc);-            if (unlikely(js_poll_interrupts(ctx)))-                goto exception;-            BREAK;-#if SHORT_OPCODES-        CASE(OP_goto16):-            pc += (int16_t)get_u16(pc);-            if (unlikely(js_poll_interrupts(ctx)))-                goto exception;-            BREAK;-        CASE(OP_goto8):-            pc += (int8_t)pc[0];-            if (unlikely(js_poll_interrupts(ctx)))-                goto exception;-            BREAK;-#endif-        CASE(OP_if_true):-            {-                int res;-                JSValue op1;--                op1 = sp[-1];-                pc += 4;-                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {-                    res = JS_VALUE_GET_INT(op1);-                } else {-                    res = JS_ToBoolFree(ctx, op1);-                }-                sp--;-                if (res) {-                    pc += (int32_t)get_u32(pc - 4) - 4;-                }-                if (unlikely(js_poll_interrupts(ctx)))-                    goto exception;-            }-            BREAK;-        CASE(OP_if_false):-            {-                int res;-                JSValue op1;--                op1 = sp[-1];-                pc += 4;-                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {-                    res = JS_VALUE_GET_INT(op1);-                } else {-                    res = JS_ToBoolFree(ctx, op1);-                }-                sp--;-                if (!res) {-                    pc += (int32_t)get_u32(pc - 4) - 4;-                }-                if (unlikely(js_poll_interrupts(ctx)))-                    goto exception;-            }-            BREAK;-#if SHORT_OPCODES-        CASE(OP_if_true8):-            {-                int res;-                JSValue op1;--                op1 = sp[-1];-                pc += 1;-                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {-                    res = JS_VALUE_GET_INT(op1);-                } else {-                    res = JS_ToBoolFree(ctx, op1);-                }-                sp--;-                if (res) {-                    pc += (int8_t)pc[-1] - 1;-                }-                if (unlikely(js_poll_interrupts(ctx)))-                    goto exception;-            }-            BREAK;-        CASE(OP_if_false8):-            {-                int res;-                JSValue op1;--                op1 = sp[-1];-                pc += 1;-                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {-                    res = JS_VALUE_GET_INT(op1);-                } else {-                    res = JS_ToBoolFree(ctx, op1);-                }-                sp--;-                if (!res) {-                    pc += (int8_t)pc[-1] - 1;-                }-                if (unlikely(js_poll_interrupts(ctx)))-                    goto exception;-            }-            BREAK;-#endif-        CASE(OP_catch):-            {-                int32_t diff;-                diff = get_u32(pc);-                sp[0] = JS_NewCatchOffset(ctx, pc + diff - b->byte_code_buf);-                sp++;-                pc += 4;-            }-            BREAK;-        CASE(OP_gosub):-            {-                int32_t diff;-                diff = get_u32(pc);-                /* XXX: should have a different tag to avoid security flaw */-                sp[0] = JS_NewInt32(ctx, pc + 4 - b->byte_code_buf);-                sp++;-                pc += diff;-            }-            BREAK;-        CASE(OP_ret):-            {-                JSValue op1;-                uint32_t pos;-                op1 = sp[-1];-                if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_INT))-                    goto ret_fail;-                pos = JS_VALUE_GET_INT(op1);-                if (unlikely(pos >= b->byte_code_len)) {-                ret_fail:-                    JS_ThrowInternalError(ctx, "invalid ret value");-                    goto exception;-                }-                sp--;-                pc = b->byte_code_buf + pos;-            }-            BREAK;--        CASE(OP_for_in_start):-            if (js_for_in_start(ctx, sp))-                goto exception;-            BREAK;-        CASE(OP_for_in_next):-            if (js_for_in_next(ctx, sp))-                goto exception;-            sp += 2;-            BREAK;-        CASE(OP_for_of_start):-            if (js_for_of_start(ctx, sp, FALSE))-                goto exception;-            sp += 1;-            *sp++ = JS_NewCatchOffset(ctx, 0);-            BREAK;-        CASE(OP_for_of_next):-            {-                int offset = -3 - pc[0];-                pc += 1;-                if (js_for_of_next(ctx, sp, offset))-                    goto exception;-                sp += 2;-            }-            BREAK;-        CASE(OP_for_await_of_start):-            if (js_for_of_start(ctx, sp, TRUE))-                goto exception;-            sp += 1;-            *sp++ = JS_NewCatchOffset(ctx, 0);-            BREAK;-        CASE(OP_for_await_of_next):-            if (js_for_await_of_next(ctx, sp))-                goto exception;-            sp += 1;-            BREAK;-        CASE(OP_iterator_get_value_done):-            if (js_iterator_get_value_done(ctx, sp))-                goto exception;-            sp += 1;-            BREAK;--        CASE(OP_iterator_close):-            /* iter_obj next catch_offset -> */-            sp--; /* drop the catch offset to avoid getting caught by exception */-            JS_FreeValue(ctx, sp[-1]); /* drop the next method */-            sp--;-            if (!JS_IsUndefined(sp[-1])) {-                if (JS_IteratorClose(ctx, sp[-1], FALSE))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-            }-            sp--;-            BREAK;-        CASE(OP_iterator_close_return):-            {-                JSValue ret_val;-                /* iter_obj next catch_offset ... ret_val ->-                   ret_eval iter_obj next catch_offset */-                ret_val = *--sp;-                while (sp > stack_buf &&-                       JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_CATCH_OFFSET) {-                    JS_FreeValue(ctx, *--sp);-                }-                if (unlikely(sp < stack_buf + 3)) {-                    JS_ThrowInternalError(ctx, "iterator_close_return");-                    JS_FreeValue(ctx, ret_val);-                    goto exception;-                }-                sp[0] = sp[-1];-                sp[-1] = sp[-2];-                sp[-2] = sp[-3];-                sp[-3] = ret_val;-                sp++;-            }-            BREAK;--        CASE(OP_async_iterator_close):-            /* iter_obj next catch_offset -> value flag */-            {-                JSValue ret, method;-                int ret_flag;-                sp--; /* remove the catch offset */-                method = JS_GetProperty(ctx, sp[-2], JS_ATOM_return);-                if (JS_IsException(method))-                    goto exception;-                if (JS_IsUndefined(method) || JS_IsNull(method)) {-                    ret = JS_UNDEFINED;-                    ret_flag = TRUE;-                } else {-                    ret = JS_CallFree(ctx, method, sp[-2], 0, NULL);-                    if (JS_IsException(ret))-                        goto exception;-                    if (!JS_IsObject(ret)) {-                        JS_FreeValue(ctx, ret);-                        JS_ThrowTypeErrorNotAnObject(ctx);-                        goto exception;-                    }-                    ret_flag = FALSE;-                }-                JS_FreeValue(ctx, sp[-2]);-                JS_FreeValue(ctx, sp[-1]);-                sp[-2] = ret;-                sp[-1] = JS_NewBool(ctx, ret_flag);-            }-            BREAK;--        CASE(OP_async_iterator_next):-            /* stack: iter_obj next catch_offset val */-            {-                JSValue ret;-                ret = JS_Call(ctx, sp[-3], sp[-4],-                              1, (JSValueConst *)(sp - 1));-                if (JS_IsException(ret))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = ret;-            }-            BREAK;--        CASE(OP_async_iterator_get):-            /* stack: iter_obj next catch_offset val */-            {-                JSValue method, ret;-                BOOL ret_flag;-                int flags;-                flags = *pc++;-                /* XXX: use another opcode such as OP_throw_var */-                if (flags == 2) {-                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");-                    goto exception;-                }-                method = JS_GetProperty(ctx, sp[-4], flags ? JS_ATOM_throw : JS_ATOM_return);-                if (JS_IsException(method))-                    goto exception;-                if (JS_IsUndefined(method) || JS_IsNull(method)) {-                    ret_flag = TRUE;-                } else {-                    ret = JS_CallFree(ctx, method, sp[-4],-                                      1, (JSValueConst *)(sp - 1));-                    if (JS_IsException(ret))-                        goto exception;-                    JS_FreeValue(ctx, sp[-1]);-                    sp[-1] = ret;-                    ret_flag = FALSE;-                }-                sp[0] = JS_NewBool(ctx, ret_flag);-                sp += 1;-            }-            BREAK;--        CASE(OP_lnot):-            {-                int res;-                JSValue op1;--                op1 = sp[-1];-                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {-                    res = JS_VALUE_GET_INT(op1) != 0;-                } else {-                    res = JS_ToBoolFree(ctx, op1);-                }-                sp[-1] = JS_NewBool(ctx, !res);-            }-            BREAK;--        CASE(OP_get_field):-            {-                JSValue val;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                val = JS_GetProperty(ctx, sp[-1], atom);-                if (unlikely(JS_IsException(val)))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = val;-            }-            BREAK;--        CASE(OP_get_field2):-            {-                JSValue val;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                val = JS_GetProperty(ctx, sp[-1], atom);-                if (unlikely(JS_IsException(val)))-                    goto exception;-                *sp++ = val;-            }-            BREAK;--        CASE(OP_put_field):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1],-                                             JS_PROP_THROW_STRICT);-                JS_FreeValue(ctx, sp[-2]);-                sp -= 2;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_private_symbol):-            {-                JSAtom atom;-                JSValue val;-                -                atom = get_u32(pc);-                pc += 4;-                val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE);-                if (JS_IsException(val))-                    goto exception;-                *sp++ = val;-            }-            BREAK;-            -        CASE(OP_get_private_field):-            {-                JSValue val;--                val = JS_GetPrivateField(ctx, sp[-2], sp[-1]);-                JS_FreeValue(ctx, sp[-1]);-                JS_FreeValue(ctx, sp[-2]);-                sp[-2] = val;-                sp--;-                if (unlikely(JS_IsException(val)))-                    goto exception;-            }-            BREAK;--        CASE(OP_put_private_field):-            {-                int ret;-                ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]);-                JS_FreeValue(ctx, sp[-3]);-                JS_FreeValue(ctx, sp[-1]);-                sp -= 3;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_define_private_field):-            {-                int ret;-                ret = JS_DefinePrivateField(ctx, sp[-3], sp[-2], sp[-1]);-                JS_FreeValue(ctx, sp[-2]);-                sp -= 2;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_define_field):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                ret = JS_DefinePropertyValue(ctx, sp[-2], atom, sp[-1],-                                             JS_PROP_C_W_E | JS_PROP_THROW);-                sp--;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_set_name):-            {-                int ret;-                JSAtom atom;-                atom = get_u32(pc);-                pc += 4;--                ret = JS_DefineObjectName(ctx, sp[-1], atom, JS_PROP_CONFIGURABLE);-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;-        CASE(OP_set_name_computed):-            {-                int ret;-                ret = JS_DefineObjectNameComputed(ctx, sp[-1], sp[-2], JS_PROP_CONFIGURABLE);-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;-        CASE(OP_set_proto):-            {-                JSValue proto;-                proto = sp[-1];-                if (JS_IsObject(proto) || JS_IsNull(proto)) {-                    if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0)-                        goto exception;-                }-                JS_FreeValue(ctx, proto);-                sp--;-            }-            BREAK;-        CASE(OP_set_home_object):-            js_method_set_home_object(ctx, sp[-1], sp[-2]);-            BREAK;-        CASE(OP_define_method):-        CASE(OP_define_method_computed):-            {-                JSValue getter, setter, value;-                JSValueConst obj;-                JSAtom atom;-                int flags, ret, op_flags;-                BOOL is_computed;-#define OP_DEFINE_METHOD_METHOD 0-#define OP_DEFINE_METHOD_GETTER 1-#define OP_DEFINE_METHOD_SETTER 2-#define OP_DEFINE_METHOD_ENUMERABLE 4--                is_computed = (opcode == OP_define_method_computed);-                if (is_computed) {-                    atom = JS_ValueToAtom(ctx, sp[-2]);-                    if (unlikely(atom == JS_ATOM_NULL))-                        goto exception;-                    opcode += OP_define_method - OP_define_method_computed;-                } else {-                    atom = get_u32(pc);-                    pc += 4;-                }-                op_flags = *pc++;--                obj = sp[-2 - is_computed];-                flags = JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE |-                    JS_PROP_HAS_ENUMERABLE | JS_PROP_THROW;-                if (op_flags & OP_DEFINE_METHOD_ENUMERABLE)-                    flags |= JS_PROP_ENUMERABLE;-                op_flags &= 3;-                value = JS_UNDEFINED;-                getter = JS_UNDEFINED;-                setter = JS_UNDEFINED;-                if (op_flags == OP_DEFINE_METHOD_METHOD) {-                    value = sp[-1];-                    flags |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE;-                } else if (op_flags == OP_DEFINE_METHOD_GETTER) {-                    getter = sp[-1];-                    flags |= JS_PROP_HAS_GET;-                } else {-                    setter = sp[-1];-                    flags |= JS_PROP_HAS_SET;-                }-                ret = js_method_set_properties(ctx, sp[-1], atom, flags, obj);-                if (ret >= 0) {-                    ret = JS_DefineProperty(ctx, obj, atom, value,-                                            getter, setter, flags);-                }-                JS_FreeValue(ctx, sp[-1]);-                if (is_computed) {-                    JS_FreeAtom(ctx, atom);-                    JS_FreeValue(ctx, sp[-2]);-                }-                sp -= 1 + is_computed;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_define_class):-        CASE(OP_define_class_computed):-            {-                int class_flags;-                JSAtom atom;-                -                atom = get_u32(pc);-                class_flags = pc[4];-                pc += 5;-                if (js_op_define_class(ctx, sp, atom, class_flags,-                                       var_refs, sf,-                                       (opcode == OP_define_class_computed)) < 0)-                    goto exception;-            }-            BREAK;--        CASE(OP_get_array_el):-            {-                JSValue val;--                val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);-                JS_FreeValue(ctx, sp[-2]);-                sp[-2] = val;-                sp--;-                if (unlikely(JS_IsException(val)))-                    goto exception;-            }-            BREAK;--        CASE(OP_get_array_el2):-            {-                JSValue val;--                val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);-                sp[-1] = val;-                if (unlikely(JS_IsException(val)))-                    goto exception;-            }-            BREAK;--        CASE(OP_get_ref_value):-            {-                JSValue val;-                if (unlikely(JS_IsUndefined(sp[-2]))) {-                    JSAtom atom = JS_ValueToAtom(ctx, sp[-1]);-                    if (atom != JS_ATOM_NULL) {-                        JS_ThrowReferenceErrorNotDefined(ctx, atom);-                        JS_FreeAtom(ctx, atom);-                    }-                    goto exception;-                }-                val = JS_GetPropertyValue(ctx, sp[-2],-                                          JS_DupValue(ctx, sp[-1]));-                if (unlikely(JS_IsException(val)))-                    goto exception;-                sp[0] = val;-                sp++;-            }-            BREAK;--        CASE(OP_get_super_value):-            {-                JSValue val;-                JSAtom atom;-                atom = JS_ValueToAtom(ctx, sp[-1]);-                if (unlikely(atom == JS_ATOM_NULL))-                    goto exception;-                val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], FALSE);-                JS_FreeAtom(ctx, atom);-                if (unlikely(JS_IsException(val)))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                JS_FreeValue(ctx, sp[-2]);-                JS_FreeValue(ctx, sp[-3]);-                sp[-3] = val;-                sp -= 2;-            }-            BREAK;--        CASE(OP_put_array_el):-            {-                int ret;--                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);-                JS_FreeValue(ctx, sp[-3]);-                sp -= 3;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_put_ref_value):-            {-                int ret;-                if (unlikely(JS_IsUndefined(sp[-3]))) {-                    if (is_strict_mode(ctx)) {-                        JSAtom atom = JS_ValueToAtom(ctx, sp[-2]);-                        if (atom != JS_ATOM_NULL) {-                            JS_ThrowReferenceErrorNotDefined(ctx, atom);-                            JS_FreeAtom(ctx, atom);-                        }-                        goto exception;-                    } else {-                        sp[-3] = JS_DupValue(ctx, ctx->global_obj);-                    }-                }-                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);-                JS_FreeValue(ctx, sp[-3]);-                sp -= 3;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_put_super_value):-            {-                int ret;-                JSAtom atom;-                if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) {-                    JS_ThrowTypeErrorNotAnObject(ctx);-                    goto exception;-                }-                atom = JS_ValueToAtom(ctx, sp[-2]);-                if (unlikely(atom == JS_ATOM_NULL))-                    goto exception;-                ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(sp[-3]),-                                            atom, sp[-1], sp[-4],-                                            JS_PROP_THROW_STRICT);-                JS_FreeAtom(ctx, atom);-                JS_FreeValue(ctx, sp[-4]);-                JS_FreeValue(ctx, sp[-3]);-                JS_FreeValue(ctx, sp[-2]);-                sp -= 4;-                if (ret < 0)-                    goto exception;-            }-            BREAK;--        CASE(OP_define_array_el):-            {-                int ret;-                ret = JS_DefinePropertyValueValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1],-                                                  JS_PROP_C_W_E | JS_PROP_THROW);-                sp -= 1;-                if (unlikely(ret < 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_append):    /* array pos enumobj -- array pos */-            {-                if (js_append_enumerate(ctx, sp))-                    goto exception;-                JS_FreeValue(ctx, *--sp);-            }-            BREAK;--        CASE(OP_copy_data_properties):    /* target source excludeList */-            {-                /* stack offsets (-1 based):-                   2 bits for target,-                   3 bits for source,-                   2 bits for exclusionList */-                int mask;--                mask = *pc++;-                if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)],-                                          sp[-1 - ((mask >> 2) & 7)],-                                          sp[-1 - ((mask >> 5) & 7)], 0))-                    goto exception;-            }-            BREAK;--        CASE(OP_add):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    int64_t r;-                    r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2);-                    if (unlikely((int)r != r))-                        goto add_slow;-                    sp[-2] = JS_NewInt32(ctx, r);-                    sp--;-                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {-                    sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) +-                                             JS_VALUE_GET_FLOAT64(op2));-                    sp--;-                } else {-                add_slow:-                    if (js_add_slow(ctx, sp))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_add_loc):-            {-                JSValue *pv;-                int idx;-                idx = *pc;-                pc += 1;--                pv = &var_buf[idx];-                if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {-                    int64_t r;-                    r = (int64_t)JS_VALUE_GET_INT(*pv) +-                        JS_VALUE_GET_INT(sp[-1]);-                    if (unlikely((int)r != r))-                        goto add_loc_slow;-                    *pv = JS_NewInt32(ctx, r);-                    sp--;-                } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {-                    JSValue op1;-                    op1 = sp[-1];-                    sp--;-                    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);-                    if (JS_IsException(op1))-                        goto exception;-                    op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);-                    if (JS_IsException(op1))-                        goto exception;-                    set_value(ctx, pv, op1);-                } else {-                    JSValue ops[2];-                add_loc_slow:-                    /* In case of exception, js_add_slow frees ops[0]-                       and ops[1], so we must duplicate *pv */-                    ops[0] = JS_DupValue(ctx, *pv);-                    ops[1] = sp[-1];-                    sp--;-                    if (js_add_slow(ctx, ops + 2))-                        goto exception;-                    set_value(ctx, pv, ops[0]);-                }-            }-            BREAK;-        CASE(OP_sub):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    int64_t r;-                    r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2);-                    if (unlikely((int)r != r))-                        goto binary_arith_slow;-                    sp[-2] = JS_NewInt32(ctx, r);-                    sp--;-                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {-                    sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) --                                             JS_VALUE_GET_FLOAT64(op2));-                    sp--;-                } else {-                    goto binary_arith_slow;-                }-            }-            BREAK;-        CASE(OP_mul):-            {-                JSValue op1, op2;-                double d;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    int32_t v1, v2;-                    int64_t r;-                    v1 = JS_VALUE_GET_INT(op1);-                    v2 = JS_VALUE_GET_INT(op2);-                    r = (int64_t)v1 * v2;-                    if (unlikely((int)r != r)) {-#ifdef CONFIG_BIGNUM-                        if (unlikely(sf->js_mode & JS_MODE_MATH) &&-                            (r < -MAX_SAFE_INTEGER || r > MAX_SAFE_INTEGER))-                            goto binary_arith_slow;-#endif-                        d = (double)r;-                        goto mul_fp_res;-                    }-                    /* need to test zero case for -0 result */-                    if (unlikely(r == 0 && (v1 | v2) < 0)) {-                        d = -0.0;-                        goto mul_fp_res;-                    }-                    sp[-2] = JS_NewInt32(ctx, r);-                    sp--;-                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {-#ifdef CONFIG_BIGNUM-                    if (unlikely(sf->js_mode & JS_MODE_MATH))-                        goto binary_arith_slow;-#endif-                    d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);-                mul_fp_res:-                    sp[-2] = __JS_NewFloat64(ctx, d);-                    sp--;-                } else {-                    goto binary_arith_slow;-                }-            }-            BREAK;-        CASE(OP_div):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    int v1, v2;-                    if (unlikely(sf->js_mode & JS_MODE_MATH))-                        goto binary_arith_slow;-                    v1 = JS_VALUE_GET_INT(op1);-                    v2 = JS_VALUE_GET_INT(op2);-                    sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);-                    sp--;-                } else {-                    goto binary_arith_slow;-                }-            }-            BREAK;-        CASE(OP_mod):-#ifdef CONFIG_BIGNUM-        CASE(OP_math_mod):-#endif-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    int v1, v2, r;-                    v1 = JS_VALUE_GET_INT(op1);-                    v2 = JS_VALUE_GET_INT(op2);-                    /* We must avoid v2 = 0, v1 = INT32_MIN and v2 =-                       -1 and the cases where the result is -0. */-                    if (unlikely(v1 < 0 || v2 <= 0))-                        goto binary_arith_slow;-                    r = v1 % v2;-                    sp[-2] = JS_NewInt32(ctx, r);-                    sp--;-                } else {-                    goto binary_arith_slow;-                }-            }-            BREAK;-        CASE(OP_pow):-        binary_arith_slow:-            if (js_binary_arith_slow(ctx, sp, opcode))-                goto exception;-            sp--;-            BREAK;--        CASE(OP_plus):-            {-                JSValue op1;-                uint32_t tag;-                op1 = sp[-1];-                tag = JS_VALUE_GET_TAG(op1);-                if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) {-                } else {-                    if (js_unary_arith_slow(ctx, sp, opcode))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_neg):-            {-                JSValue op1;-                uint32_t tag;-                int val;-                double d;-                op1 = sp[-1];-                tag = JS_VALUE_GET_TAG(op1);-                if (tag == JS_TAG_INT) {-                    val = JS_VALUE_GET_INT(op1);-                    /* Note: -0 cannot be expressed as integer */-                    if (unlikely(val == 0)) {-                        d = -0.0;-                        goto neg_fp_res;-                    }-                    if (unlikely(val == INT32_MIN)) {-                        d = -(double)val;-                        goto neg_fp_res;-                    }-                    sp[-1] = JS_NewInt32(ctx, -val);-                } else if (JS_TAG_IS_FLOAT64(tag)) {-                    d = -JS_VALUE_GET_FLOAT64(op1);-                neg_fp_res:-                    sp[-1] = __JS_NewFloat64(ctx, d);-                } else {-                    if (js_unary_arith_slow(ctx, sp, opcode))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_inc):-            {-                JSValue op1;-                int val;-                op1 = sp[-1];-                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {-                    val = JS_VALUE_GET_INT(op1);-                    if (unlikely(val == INT32_MAX))-                        goto inc_slow;-                    sp[-1] = JS_NewInt32(ctx, val + 1);-                } else {-                inc_slow:-                    if (js_unary_arith_slow(ctx, sp, opcode))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_dec):-            {-                JSValue op1;-                int val;-                op1 = sp[-1];-                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {-                    val = JS_VALUE_GET_INT(op1);-                    if (unlikely(val == INT32_MIN))-                        goto dec_slow;-                    sp[-1] = JS_NewInt32(ctx, val - 1);-                } else {-                dec_slow:-                    if (js_unary_arith_slow(ctx, sp, opcode))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_post_inc):-        CASE(OP_post_dec):-            if (js_post_inc_slow(ctx, sp, opcode))-                goto exception;-            sp++;-            BREAK;-        CASE(OP_inc_loc):-            {-                JSValue op1;-                int val;-                int idx;-                idx = *pc;-                pc += 1;--                op1 = var_buf[idx];-                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {-                    val = JS_VALUE_GET_INT(op1);-                    if (unlikely(val == INT32_MAX))-                        goto inc_loc_slow;-                    var_buf[idx] = JS_NewInt32(ctx, val + 1);-                } else {-                inc_loc_slow:-                    if (js_unary_arith_slow(ctx, var_buf + idx + 1, OP_inc))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_dec_loc):-            {-                JSValue op1;-                int val;-                int idx;-                idx = *pc;-                pc += 1;--                op1 = var_buf[idx];-                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {-                    val = JS_VALUE_GET_INT(op1);-                    if (unlikely(val == INT32_MIN))-                        goto dec_loc_slow;-                    var_buf[idx] = JS_NewInt32(ctx, val - 1);-                } else {-                dec_loc_slow:-                    if (js_unary_arith_slow(ctx, var_buf + idx + 1, OP_dec))-                        goto exception;-                }-            }-            BREAK;-        CASE(OP_not):-            {-                JSValue op1;-                op1 = sp[-1];-                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {-                    sp[-1] = JS_NewInt32(ctx, ~JS_VALUE_GET_INT(op1));-                } else {-                    if (js_not_slow(ctx, sp))-                        goto exception;-                }-            }-            BREAK;--        CASE(OP_shl):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    uint32_t v1, v2;-                    v1 = JS_VALUE_GET_INT(op1);-                    v2 = JS_VALUE_GET_INT(op2);-#ifdef CONFIG_BIGNUM-                    {-                        int64_t r;-                        if (unlikely(sf->js_mode & JS_MODE_MATH)) {-                            if (v2 > 0x1f)-                                goto shl_slow;-                            r = (int64_t)v1 << v2;-                            if ((int)r != r)-                                goto shl_slow;-                        } else {-                            v2 &= 0x1f;-                        }-                    }-#else-                    v2 &= 0x1f;-#endif-                    sp[-2] = JS_NewInt32(ctx, v1 << v2);-                    sp--;-                } else {-#ifdef CONFIG_BIGNUM-                shl_slow:-#endif-                    if (js_binary_logic_slow(ctx, sp, opcode))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_shr):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    uint32_t v2;-                    v2 = JS_VALUE_GET_INT(op2);-                    /* v1 >>> v2 retains its JS semantics if CONFIG_BIGNUM */-                    v2 &= 0x1f;-                    sp[-2] = JS_NewUint32(ctx,-                                          (uint32_t)JS_VALUE_GET_INT(op1) >>-                                          v2);-                    sp--;-                } else {-                    if (js_shr_slow(ctx, sp))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_sar):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    uint32_t v2;-                    v2 = JS_VALUE_GET_INT(op2);-#ifdef CONFIG_BIGNUM-                    if (unlikely(v2 > 0x1f)) {-                        if (unlikely(sf->js_mode & JS_MODE_MATH))-                            goto sar_slow;-                        else-                            v2 &= 0x1f;-                    }-#else-                    v2 &= 0x1f;-#endif-                    sp[-2] = JS_NewInt32(ctx,-                                          (int)JS_VALUE_GET_INT(op1) >> v2);-                    sp--;-                } else {-#ifdef CONFIG_BIGNUM-                sar_slow:-#endif-                    if (js_binary_logic_slow(ctx, sp, opcode))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_and):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    sp[-2] = JS_NewInt32(ctx,-                                         JS_VALUE_GET_INT(op1) &-                                         JS_VALUE_GET_INT(op2));-                    sp--;-                } else {-                    if (js_binary_logic_slow(ctx, sp, opcode))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_or):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    sp[-2] = JS_NewInt32(ctx,-                                         JS_VALUE_GET_INT(op1) |-                                         JS_VALUE_GET_INT(op2));-                    sp--;-                } else {-                    if (js_binary_logic_slow(ctx, sp, opcode))-                        goto exception;-                    sp--;-                }-            }-            BREAK;-        CASE(OP_xor):-            {-                JSValue op1, op2;-                op1 = sp[-2];-                op2 = sp[-1];-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {-                    sp[-2] = JS_NewInt32(ctx,-                                         JS_VALUE_GET_INT(op1) ^-                                         JS_VALUE_GET_INT(op2));-                    sp--;-                } else {-                    if (js_binary_logic_slow(ctx, sp, opcode))-                        goto exception;-                    sp--;-                }-            }-            BREAK;---#define OP_CMP(opcode, binary_op, slow_call)              \-            CASE(opcode):                                 \-                {                                         \-                JSValue op1, op2;                         \-                op1 = sp[-2];                             \-                op2 = sp[-1];                                   \-                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {           \-                    sp[-2] = JS_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \-                    sp--;                                               \-                } else {                                                \-                    if (slow_call)                                      \-                        goto exception;                                 \-                    sp--;                                               \-                }                                                       \-                }                                                       \-            BREAK--            OP_CMP(OP_lt, <, js_relational_slow(ctx, sp, opcode));-            OP_CMP(OP_lte, <=, js_relational_slow(ctx, sp, opcode));-            OP_CMP(OP_gt, >, js_relational_slow(ctx, sp, opcode));-            OP_CMP(OP_gte, >=, js_relational_slow(ctx, sp, opcode));-            OP_CMP(OP_eq, ==, js_eq_slow(ctx, sp, 0));-            OP_CMP(OP_neq, !=, js_eq_slow(ctx, sp, 1));-            OP_CMP(OP_strict_eq, ==, js_strict_eq_slow(ctx, sp, 0));-            OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1));--#ifdef CONFIG_BIGNUM-        CASE(OP_mul_pow10):-            if (rt->bigfloat_ops.mul_pow10(ctx, sp))-                goto exception;-            sp--;-            BREAK;-#endif-        CASE(OP_in):-            if (js_operator_in(ctx, sp))-                goto exception;-            sp--;-            BREAK;-        CASE(OP_instanceof):-            if (js_operator_instanceof(ctx, sp))-                goto exception;-            sp--;-            BREAK;-        CASE(OP_typeof):-            {-                JSValue op1;-                JSAtom atom;--                op1 = sp[-1];-                atom = js_operator_typeof(ctx, op1);-                JS_FreeValue(ctx, op1);-                sp[-1] = JS_AtomToString(ctx, atom);-            }-            BREAK;-        CASE(OP_delete):-            if (js_operator_delete(ctx, sp))-                goto exception;-            sp--;-            BREAK;-        CASE(OP_delete_var):-            {-                JSAtom atom;-                int ret;--                atom = get_u32(pc);-                pc += 4;--                ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0);-                if (unlikely(ret < 0))-                    goto exception;-                *sp++ = JS_NewBool(ctx, ret);-            }-            BREAK;--        CASE(OP_to_object):-            if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) {-                ret_val = JS_ToObject(ctx, sp[-1]);-                if (JS_IsException(ret_val))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = ret_val;-            }-            BREAK;--        CASE(OP_to_propkey):-            switch (JS_VALUE_GET_TAG(sp[-1])) {-            case JS_TAG_INT:-            case JS_TAG_STRING:-            case JS_TAG_SYMBOL:-                break;-            default:-                ret_val = JS_ToPropertyKey(ctx, sp[-1]);-                if (JS_IsException(ret_val))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = ret_val;-                break;-            }-            BREAK;--        CASE(OP_to_propkey2):-            /* must be tested first */-            if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) {-                JS_ThrowTypeError(ctx, "value has no property");-                goto exception;-            }-            switch (JS_VALUE_GET_TAG(sp[-1])) {-            case JS_TAG_INT:-            case JS_TAG_STRING:-            case JS_TAG_SYMBOL:-                break;-            default:-                ret_val = JS_ToPropertyKey(ctx, sp[-1]);-                if (JS_IsException(ret_val))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = ret_val;-                break;-            }-            BREAK;-#if 0-        CASE(OP_to_string):-            if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_STRING) {-                ret_val = JS_ToString(ctx, sp[-1]);-                if (JS_IsException(ret_val))-                    goto exception;-                JS_FreeValue(ctx, sp[-1]);-                sp[-1] = ret_val;-            }-            BREAK;-#endif-        CASE(OP_with_get_var):-        CASE(OP_with_put_var):-        CASE(OP_with_delete_var):-        CASE(OP_with_make_ref):-        CASE(OP_with_get_ref):-        CASE(OP_with_get_ref_undef):-            {-                JSAtom atom;-                int32_t diff;-                JSValue obj, val;-                int ret, is_with;-                atom = get_u32(pc);-                diff = get_u32(pc + 4);-                is_with = pc[8];-                pc += 9;--                obj = sp[-1];-                ret = JS_HasProperty(ctx, obj, atom);-                if (unlikely(ret < 0))-                    goto exception;-                if (ret) {-                    if (is_with) {-                        ret = js_has_unscopable(ctx, obj, atom);-                        if (unlikely(ret < 0))-                            goto exception;-                        if (ret)-                            goto no_with;-                    }-                    switch (opcode) {-                    case OP_with_get_var:-                        val = JS_GetProperty(ctx, obj, atom);-                        if (unlikely(JS_IsException(val)))-                            goto exception;-                        set_value(ctx, &sp[-1], val);-                        break;-                    case OP_with_put_var:-                        ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],-                                                     JS_PROP_THROW_STRICT);-                        JS_FreeValue(ctx, sp[-1]);-                        sp -= 2;-                        if (unlikely(ret < 0))-                            goto exception;-                        break;-                    case OP_with_delete_var:-                        ret = JS_DeleteProperty(ctx, obj, atom, 0);-                        if (unlikely(ret < 0))-                            goto exception;-                        JS_FreeValue(ctx, sp[-1]);-                        sp[-1] = JS_NewBool(ctx, ret);-                        break;-                    case OP_with_make_ref:-                        /* produce a pair object/propname on the stack */-                        *sp++ = JS_AtomToValue(ctx, atom);-                        break;-                    case OP_with_get_ref:-                        /* produce a pair object/method on the stack */-                        val = JS_GetProperty(ctx, obj, atom);-                        if (unlikely(JS_IsException(val)))-                            goto exception;-                        *sp++ = val;-                        break;-                    case OP_with_get_ref_undef:-                        /* produce a pair undefined/function on the stack */-                        val = JS_GetProperty(ctx, obj, atom);-                        if (unlikely(JS_IsException(val)))-                            goto exception;-                        JS_FreeValue(ctx, sp[-1]);-                        sp[-1] = JS_UNDEFINED;-                        *sp++ = val;-                        break;-                    }-                    pc += diff - 5;-                } else {-                no_with:-                    /* if not jumping, drop the object argument */-                    JS_FreeValue(ctx, sp[-1]);-                    sp--;-                }-            }-            BREAK;--        CASE(OP_await):-            ret_val = JS_NewInt32(ctx, FUNC_RET_AWAIT);-            goto done_generator;-        CASE(OP_yield):-            ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD);-            goto done_generator;-        CASE(OP_yield_star):-        CASE(OP_async_yield_star):-            ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR);-            goto done_generator;-        CASE(OP_return_async):-        CASE(OP_initial_yield):-            ret_val = JS_UNDEFINED;-            goto done_generator;--        CASE(OP_nop):-            BREAK;-        CASE(OP_is_undefined_or_null):-            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED ||-                JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) {-                goto set_true;-            } else {-                goto free_and_set_false;-            }-#if SHORT_OPCODES-        CASE(OP_is_undefined):-            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED) {-                goto set_true;-            } else {-                goto free_and_set_false;-            }-        CASE(OP_is_null):-            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) {-                goto set_true;-            } else {-                goto free_and_set_false;-            }-            /* XXX: could merge to a single opcode */-        CASE(OP_typeof_is_undefined):-            /* different from OP_is_undefined because of isHTMLDDA */-            if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_undefined) {-                goto free_and_set_true;-            } else {-                goto free_and_set_false;-            }-        CASE(OP_typeof_is_function):-            if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) {-                goto free_and_set_true;-            } else {-                goto free_and_set_false;-            }-        free_and_set_true:-            JS_FreeValue(ctx, sp[-1]);-#endif-        set_true:-            sp[-1] = JS_TRUE;-            BREAK;-        free_and_set_false:-            JS_FreeValue(ctx, sp[-1]);-            sp[-1] = JS_FALSE;-            BREAK;-        CASE(OP_invalid):-        DEFAULT:-            JS_ThrowInternalError(ctx, "invalid opcode: pc=%u opcode=0x%02x",-                                  (int)(pc - b->byte_code_buf - 1), opcode);-            goto exception;-        }-    }- exception:-    if (is_backtrace_needed(ctx, rt->current_exception)) {-        /* add the backtrace information now (it is not done-           before if the exception happens in a bytecode-           operation */-        sf->cur_pc = pc;-        build_backtrace(ctx, rt->current_exception, NULL, 0, 0);-    }-    if (!JS_IsUncatchableError(ctx, rt->current_exception)) {-        while (sp > stack_buf) {-            JSValue val = *--sp;-            JS_FreeValue(ctx, val);-            if (JS_VALUE_GET_TAG(val) == JS_TAG_CATCH_OFFSET) {-                int pos = JS_VALUE_GET_INT(val);-                if (pos == 0) {-                    /* enumerator: close it with a throw */-                    JS_FreeValue(ctx, sp[-1]); /* drop the next method */-                    sp--;-                    JS_IteratorClose(ctx, sp[-1], TRUE);-                } else {-                    *sp++ = rt->current_exception;-                    rt->current_exception = JS_NULL;-                    pc = b->byte_code_buf + pos;-                    goto restart;-                }-            }-        }-    }-    ret_val = JS_EXCEPTION;-    /* the local variables are freed by the caller in the generator-       case. Hence the label 'done' should never be reached in a-       generator function. */-    if (b->func_kind != JS_FUNC_NORMAL) {-    done_generator:-        sf->cur_pc = pc;-        sf->cur_sp = sp;-    } else {-    done:-        if (unlikely(!list_empty(&sf->var_ref_list))) {-            /* variable references reference the stack: must close them */-            close_var_refs(rt, sf);-        }-        /* free the local variables and stack */-        for(pval = local_buf; pval < sp; pval++) {-            JS_FreeValue(ctx, *pval);-        }-    }-    rt->current_stack_frame = sf->prev_frame;-    return ret_val;-}--JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,-                int argc, JSValueConst *argv)-{-    return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,-                           argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);-}--static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,-                           int argc, JSValueConst *argv)-{-    JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,-                                  argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);-    JS_FreeValue(ctx, func_obj);-    return res;-}--/* warning: the refcount of the context is not incremented. Return-   NULL in case of exception (case of revoked proxy only) */-static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)-{-    JSObject *p;-    JSContext *realm;-    -    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)-        return ctx;-    p = JS_VALUE_GET_OBJ(func_obj);-    switch(p->class_id) {-    case JS_CLASS_C_FUNCTION:-        realm = p->u.cfunc.realm;-        break;-    case JS_CLASS_BYTECODE_FUNCTION:-    case JS_CLASS_GENERATOR_FUNCTION:-    case JS_CLASS_ASYNC_FUNCTION:-    case JS_CLASS_ASYNC_GENERATOR_FUNCTION:-        {-            JSFunctionBytecode *b;-            b = p->u.func.function_bytecode;-            realm = b->realm;-        }-        break;-    case JS_CLASS_PROXY:-        {-            JSProxyData *s = p->u.opaque;-            if (!s)-                return ctx;-            if (s->is_revoked) {-                JS_ThrowTypeErrorRevokedProxy(ctx);-                return NULL;-            } else {-                realm = JS_GetFunctionRealm(ctx, s->target);-            }-        }-        break;-    case JS_CLASS_BOUND_FUNCTION:-        {-            JSBoundFunction *bf = p->u.bound_function;-            realm = JS_GetFunctionRealm(ctx, bf->func_obj);-        }-        break;-    default:-        realm = ctx;-        break;-    }-    return realm;-}--static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,-                                   int class_id)-{-    JSValue proto, obj;-    JSContext *realm;-    -    if (JS_IsUndefined(ctor)) {-        proto = JS_DupValue(ctx, ctx->class_proto[class_id]);-    } else {-        proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);-        if (JS_IsException(proto))-            return proto;-        if (!JS_IsObject(proto)) {-            JS_FreeValue(ctx, proto);-            realm = JS_GetFunctionRealm(ctx, ctor);-            if (!realm)-                return JS_EXCEPTION;-            proto = JS_DupValue(ctx, realm->class_proto[class_id]);-        }-    }-    obj = JS_NewObjectProtoClass(ctx, proto, class_id);-    JS_FreeValue(ctx, proto);-    return obj;-}--/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */-static JSValue JS_CallConstructorInternal(JSContext *ctx,-                                          JSValueConst func_obj,-                                          JSValueConst new_target,-                                          int argc, JSValue *argv, int flags)-{-    JSObject *p;-    JSFunctionBytecode *b;--    if (js_poll_interrupts(ctx))-        return JS_EXCEPTION;-    flags |= JS_CALL_FLAG_CONSTRUCTOR;-    if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT))-        goto not_a_function;-    p = JS_VALUE_GET_OBJ(func_obj);-    if (unlikely(!p->is_constructor))-        return JS_ThrowTypeError(ctx, "not a constructor");-    if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {-        JSClassCall *call_func;-        call_func = ctx->rt->class_array[p->class_id].call;-        if (!call_func) {-        not_a_function:-            return JS_ThrowTypeError(ctx, "not a function");-        }-        return call_func(ctx, func_obj, new_target, argc,-                         (JSValueConst *)argv, flags);-    }--    b = p->u.func.function_bytecode;-    if (b->is_derived_class_constructor) {-        return JS_CallInternal(ctx, func_obj, JS_UNDEFINED, new_target, argc, argv, flags);-    } else {-        JSValue obj, ret;-        /* legacy constructor behavior */-        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);-        if (JS_IsException(obj))-            return JS_EXCEPTION;-        ret = JS_CallInternal(ctx, func_obj, obj, new_target, argc, argv, flags);-        if (JS_VALUE_GET_TAG(ret) == JS_TAG_OBJECT ||-            JS_IsException(ret)) {-            JS_FreeValue(ctx, obj);-            return ret;-        } else {-            JS_FreeValue(ctx, ret);-            return obj;-        }-    }-}--JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,-                            JSValueConst new_target,-                            int argc, JSValueConst *argv)-{-    return JS_CallConstructorInternal(ctx, func_obj, new_target,-                                      argc, (JSValue *)argv,-                                      JS_CALL_FLAG_COPY_ARGV);-}--JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,-                           int argc, JSValueConst *argv)-{-    return JS_CallConstructorInternal(ctx, func_obj, func_obj,-                                      argc, (JSValue *)argv,-                                      JS_CALL_FLAG_COPY_ARGV);-}--JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,-                  int argc, JSValueConst *argv)-{-    JSValue func_obj;-    func_obj = JS_GetProperty(ctx, this_val, atom);-    if (JS_IsException(func_obj))-        return func_obj;-    return JS_CallFree(ctx, func_obj, this_val, argc, argv);-}--static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,-                             int argc, JSValueConst *argv)-{-    JSValue res = JS_Invoke(ctx, this_val, atom, argc, argv);-    JS_FreeValue(ctx, this_val);-    return res;-}--/* JSAsyncFunctionState (used by generator and async functions) */-static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,-                                       JSValueConst func_obj, JSValueConst this_obj,-                                       int argc, JSValueConst *argv)-{-    JSObject *p;-    JSFunctionBytecode *b;-    JSStackFrame *sf;-    int local_count, i, arg_buf_len, n;--    sf = &s->frame;-    init_list_head(&sf->var_ref_list);-    p = JS_VALUE_GET_OBJ(func_obj);-    b = p->u.func.function_bytecode;-    sf->js_mode = b->js_mode;-    sf->cur_pc = b->byte_code_buf;-    arg_buf_len = max_int(b->arg_count, argc);-    local_count = arg_buf_len + b->var_count + b->stack_size;-    sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1));-    if (!sf->arg_buf)-        return -1;-    sf->cur_func = JS_DupValue(ctx, func_obj);-    s->this_val = JS_DupValue(ctx, this_obj);-    s->argc = argc;-    sf->arg_count = arg_buf_len;-    sf->var_buf = sf->arg_buf + arg_buf_len;-    sf->cur_sp = sf->var_buf + b->var_count;-    for(i = 0; i < argc; i++)-        sf->arg_buf[i] = JS_DupValue(ctx, argv[i]);-    n = arg_buf_len + b->var_count;-    for(i = argc; i < n; i++)-        sf->arg_buf[i] = JS_UNDEFINED;-    return 0;-}--static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,-                            JS_MarkFunc *mark_func)-{-    JSStackFrame *sf;-    JSValue *sp;--    sf = &s->frame;-    JS_MarkValue(rt, sf->cur_func, mark_func);-    JS_MarkValue(rt, s->this_val, mark_func);-    if (sf->cur_sp) {-        /* if the function is running, cur_sp is not known so we-           cannot mark the stack. Marking the variables is not needed-           because a running function cannot be part of a removable-           cycle */-        for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)-            JS_MarkValue(rt, *sp, mark_func);-    }-}--static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)-{-    JSStackFrame *sf;-    JSValue *sp;--    sf = &s->frame;--    /* close the closure variables. */-    close_var_refs(rt, sf);-    -    if (sf->arg_buf) {-        /* cannot free the function if it is running */-        assert(sf->cur_sp != NULL);-        for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) {-            JS_FreeValueRT(rt, *sp);-        }-        js_free_rt(rt, sf->arg_buf);-    }-    JS_FreeValueRT(rt, sf->cur_func);-    JS_FreeValueRT(rt, s->this_val);-}--static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s)-{-    JSValue func_obj;--    if (js_check_stack_overflow(ctx->rt, 0))-        return JS_ThrowStackOverflow(ctx);--    /* the tag does not matter provided it is not an object */-    func_obj = JS_MKPTR(JS_TAG_INT, s);-    return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,-                           s->argc, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR);-}---/* Generators */--typedef enum JSGeneratorStateEnum {-    JS_GENERATOR_STATE_SUSPENDED_START,-    JS_GENERATOR_STATE_SUSPENDED_YIELD,-    JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR,-    JS_GENERATOR_STATE_EXECUTING,-    JS_GENERATOR_STATE_COMPLETED,-} JSGeneratorStateEnum;--typedef struct JSGeneratorData {-    JSGeneratorStateEnum state;-    JSAsyncFunctionState func_state;-} JSGeneratorData;--static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)-{-    if (s->state == JS_GENERATOR_STATE_COMPLETED)-        return;-    async_func_free(rt, &s->func_state);-    s->state = JS_GENERATOR_STATE_COMPLETED;-}--static void js_generator_finalizer(JSRuntime *rt, JSValue obj)-{-    JSGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_GENERATOR);--    if (s) {-        free_generator_stack_rt(rt, s);-        js_free_rt(rt, s);-    }-}--static void free_generator_stack(JSContext *ctx, JSGeneratorData *s)-{-    free_generator_stack_rt(ctx->rt, s);-}--static void js_generator_mark(JSRuntime *rt, JSValueConst val,-                              JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSGeneratorData *s = p->u.generator_data;--    if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)-        return;-    async_func_mark(rt, &s->func_state, mark_func);-}--/* XXX: use enum */-#define GEN_MAGIC_NEXT   0-#define GEN_MAGIC_RETURN 1-#define GEN_MAGIC_THROW  2--static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv,-                                 BOOL *pdone, int magic)-{-    JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR);-    JSStackFrame *sf;-    JSValue ret, func_ret;-    JSValueConst iter_args[1];--    *pdone = TRUE;-    if (!s)-        return JS_ThrowTypeError(ctx, "not a generator");-    sf = &s->func_state.frame;- redo:-    switch(s->state) {-    default:-    case JS_GENERATOR_STATE_SUSPENDED_START:-        if (magic == GEN_MAGIC_NEXT) {-            goto exec_no_arg;-        } else {-            free_generator_stack(ctx, s);-            goto done;-        }-        break;-    case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:-        {-            int done;-            JSValue method, iter_obj;--            iter_obj = sf->cur_sp[-2];-            if (magic == GEN_MAGIC_NEXT) {-                method = JS_DupValue(ctx, sf->cur_sp[-1]);-            } else {-                method = JS_GetProperty(ctx, iter_obj,-                                        magic == GEN_MAGIC_RETURN ?-                                        JS_ATOM_return : JS_ATOM_throw);-                if (JS_IsException(method))-                    goto iter_exception;-            }-            if (magic != GEN_MAGIC_NEXT &&-                (JS_IsUndefined(method) || JS_IsNull(method))) {-                /* default action */-                if (magic == GEN_MAGIC_RETURN) {-                    ret = JS_DupValue(ctx, argv[0]);-                    goto iter_done;-                } else {-                    if (JS_IteratorClose(ctx, iter_obj, FALSE))-                        goto iter_exception;-                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");-                    goto iter_exception;-                }-            }-            ret = JS_IteratorNext2(ctx, iter_obj, method, argc, argv, &done);-            JS_FreeValue(ctx, method);-            if (JS_IsException(ret)) {-            iter_exception:-                goto exec_throw;-            }-            /* if not done, the iterator returns the exact object-               returned by 'method' */-            if (done == 2) {-                JSValue done_val, value;-                done_val = JS_GetProperty(ctx, ret, JS_ATOM_done);-                if (JS_IsException(done_val)) {-                    JS_FreeValue(ctx, ret);-                    goto iter_exception;-                }-                done = JS_ToBoolFree(ctx, done_val);-                if (done) {-                    value = JS_GetProperty(ctx, ret, JS_ATOM_value);-                    JS_FreeValue(ctx, ret);-                    if (JS_IsException(value))-                        goto iter_exception;-                    ret = value;-                    goto iter_done;-                } else {-                    *pdone = 2;-                }-            } else {-                if (done) {-                    /* 'yield *' returns the value associated to done = true */-                iter_done:-                    JS_FreeValue(ctx, sf->cur_sp[-2]);-                    JS_FreeValue(ctx, sf->cur_sp[-1]);-                    sf->cur_sp--;-                    goto exec_arg;-                } else {-                    *pdone = FALSE;-                }-            }-            break;-        }-        break;-    case JS_GENERATOR_STATE_SUSPENDED_YIELD:-        /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */-        ret = JS_DupValue(ctx, argv[0]);-        if (magic == GEN_MAGIC_THROW) {-            JS_Throw(ctx, ret);-        exec_throw:-            s->func_state.throw_flag = TRUE;-        } else {-        exec_arg:-            sf->cur_sp[-1] = ret;-            sf->cur_sp[0] = JS_NewBool(ctx, (magic == GEN_MAGIC_RETURN));-            sf->cur_sp++;-        exec_no_arg:-            s->func_state.throw_flag = FALSE;-        }-        s->state = JS_GENERATOR_STATE_EXECUTING;-        func_ret = async_func_resume(ctx, &s->func_state);-        s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;-        if (JS_IsException(func_ret)) {-            /* finalize the execution in case of exception */-            free_generator_stack(ctx, s);-            return func_ret;-        }-        if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {-            if (JS_VALUE_GET_INT(func_ret) == FUNC_RET_YIELD_STAR) {-                /* 'yield *' */-                s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR;-                iter_args[0] = JS_UNDEFINED;-                argc = 1;-                argv = iter_args;-                goto redo;-            } else {-                /* get the return the yield value at the top of the stack */-                ret = sf->cur_sp[-1];-                sf->cur_sp[-1] = JS_UNDEFINED;-                *pdone = FALSE;-            }-        } else {-            /* end of iterator */-            ret = sf->cur_sp[-1];-            sf->cur_sp[-1] = JS_UNDEFINED;-            JS_FreeValue(ctx, func_ret);-            free_generator_stack(ctx, s);-        }-        break;-    case JS_GENERATOR_STATE_COMPLETED:-    done:-        /* execution is finished */-        switch(magic) {-        default:-        case GEN_MAGIC_NEXT:-            ret = JS_UNDEFINED;-            break;-        case GEN_MAGIC_RETURN:-            ret = JS_DupValue(ctx, argv[0]);-            break;-        case GEN_MAGIC_THROW:-            ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0]));-            break;-        }-        break;-    case JS_GENERATOR_STATE_EXECUTING:-        ret = JS_ThrowTypeError(ctx, "cannot invoke a running generator");-        break;-    }-    return ret;-}--static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,-                                          JSValueConst this_obj,-                                          int argc, JSValueConst *argv,-                                          int flags)-{-    JSValue obj, func_ret;-    JSGeneratorData *s;--    s = js_mallocz(ctx, sizeof(*s));-    if (!s)-        return JS_EXCEPTION;-    s->state = JS_GENERATOR_STATE_SUSPENDED_START;-    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {-        s->state = JS_GENERATOR_STATE_COMPLETED;-        goto fail;-    }--    /* execute the function up to 'OP_initial_yield' */-    func_ret = async_func_resume(ctx, &s->func_state);-    if (JS_IsException(func_ret))-        goto fail;-    JS_FreeValue(ctx, func_ret);--    obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR);-    if (JS_IsException(obj))-        goto fail;-    JS_SetOpaque(obj, s);-    return obj;- fail:-    free_generator_stack_rt(ctx->rt, s);-    js_free(ctx, s);-    return JS_EXCEPTION;-}--/* AsyncFunction */--static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s)-{-    if (s->is_active) {-        async_func_free(rt, &s->func_state);-        s->is_active = FALSE;-    }-}--static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s)-{-    js_async_function_terminate(rt, s);-    JS_FreeValueRT(rt, s->resolving_funcs[0]);-    JS_FreeValueRT(rt, s->resolving_funcs[1]);-    remove_gc_object(&s->header);-    js_free_rt(rt, s);-}--static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s)-{-    if (--s->header.ref_count == 0) {-        js_async_function_free0(rt, s);-    }-}--static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSAsyncFunctionData *s = p->u.async_function_data;-    if (s) {-        js_async_function_free(rt, s);-    }-}--static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,-                                           JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSAsyncFunctionData *s = p->u.async_function_data;-    if (s) {-        mark_func(rt, &s->header);-    }-}--static int js_async_function_resolve_create(JSContext *ctx,-                                            JSAsyncFunctionData *s,-                                            JSValue *resolving_funcs)-{-    int i;-    JSObject *p;--    for(i = 0; i < 2; i++) {-        resolving_funcs[i] =-            JS_NewObjectProtoClass(ctx, ctx->function_proto,-                                   JS_CLASS_ASYNC_FUNCTION_RESOLVE + i);-        if (JS_IsException(resolving_funcs[i])) {-            if (i == 1)-                JS_FreeValue(ctx, resolving_funcs[0]);-            return -1;-        }-        p = JS_VALUE_GET_OBJ(resolving_funcs[i]);-        s->header.ref_count++;-        p->u.async_function_data = s;-    }-    return 0;-}--static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)-{-    JSValue func_ret, ret2;--    func_ret = async_func_resume(ctx, &s->func_state);-    if (JS_IsException(func_ret)) {-        JSValue error;-    fail:-        error = JS_GetException(ctx);-        ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,-                       1, (JSValueConst *)&error);-        JS_FreeValue(ctx, error);-        js_async_function_terminate(ctx->rt, s);-        JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */-    } else {-        JSValue value;-        value = s->func_state.frame.cur_sp[-1];-        s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;-        if (JS_IsUndefined(func_ret)) {-            /* function returned */-            ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,-                           1, (JSValueConst *)&value);-            JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */-            JS_FreeValue(ctx, value);-            js_async_function_terminate(ctx->rt, s);-        } else {-            JSValue promise, resolving_funcs[2], resolving_funcs1[2];-            int i, res;--            /* await */-            JS_FreeValue(ctx, func_ret); /* not used */-            promise = js_promise_resolve(ctx, ctx->promise_ctor,-                                         1, (JSValueConst *)&value, 0);-            JS_FreeValue(ctx, value);-            if (JS_IsException(promise))-                goto fail;-            if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {-                JS_FreeValue(ctx, promise);-                goto fail;-            }--            /* Note: no need to create 'thrownawayCapability' as in-               the spec */-            for(i = 0; i < 2; i++)-                resolving_funcs1[i] = JS_UNDEFINED;-            res = perform_promise_then(ctx, promise,-                                       (JSValueConst *)resolving_funcs,-                                       (JSValueConst *)resolving_funcs1);-            JS_FreeValue(ctx, promise);-            for(i = 0; i < 2; i++)-                JS_FreeValue(ctx, resolving_funcs[i]);-            if (res)-                goto fail;-        }-    }-}--static JSValue js_async_function_resolve_call(JSContext *ctx,-                                              JSValueConst func_obj,-                                              JSValueConst this_obj,-                                              int argc, JSValueConst *argv,-                                              int flags)-{-    JSObject *p = JS_VALUE_GET_OBJ(func_obj);-    JSAsyncFunctionData *s = p->u.async_function_data;-    BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;-    JSValueConst arg;--    if (argc > 0)-        arg = argv[0];-    else-        arg = JS_UNDEFINED;-    s->func_state.throw_flag = is_reject;-    if (is_reject) {-        JS_Throw(ctx, JS_DupValue(ctx, arg));-    } else {-        /* return value of await */-        s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);-    }-    js_async_function_resume(ctx, s);-    return JS_UNDEFINED;-}--static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj,-                                      JSValueConst this_obj,-                                      int argc, JSValueConst *argv, int flags)-{-    JSValue promise;-    JSAsyncFunctionData *s;--    s = js_mallocz(ctx, sizeof(*s));-    if (!s)-        return JS_EXCEPTION;-    s->header.ref_count = 1;-    add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);-    s->is_active = FALSE;-    s->resolving_funcs[0] = JS_UNDEFINED;-    s->resolving_funcs[1] = JS_UNDEFINED;--    promise = JS_NewPromiseCapability(ctx, s->resolving_funcs);-    if (JS_IsException(promise))-        goto fail;--    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {-    fail:-        JS_FreeValue(ctx, promise);-        js_async_function_free(ctx->rt, s);-        return JS_EXCEPTION;-    }-    s->is_active = TRUE;--    js_async_function_resume(ctx, s);--    js_async_function_free(ctx->rt, s);--    return promise;-}--/* AsyncGenerator */--typedef enum JSAsyncGeneratorStateEnum {-    JS_ASYNC_GENERATOR_STATE_SUSPENDED_START,-    JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD,-    JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR,-    JS_ASYNC_GENERATOR_STATE_EXECUTING,-    JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN,-    JS_ASYNC_GENERATOR_STATE_COMPLETED,-} JSAsyncGeneratorStateEnum;--typedef struct JSAsyncGeneratorRequest {-    struct list_head link;-    /* completion */-    int completion_type; /* GEN_MAGIC_x */-    JSValue result;-    /* promise capability */-    JSValue promise;-    JSValue resolving_funcs[2];-} JSAsyncGeneratorRequest;--typedef struct JSAsyncGeneratorData {-    JSObject *generator; /* back pointer to the object (const) */-    JSAsyncGeneratorStateEnum state;-    JSAsyncFunctionState func_state;-    struct list_head queue; /* list of JSAsyncGeneratorRequest.link */-} JSAsyncGeneratorData;--static void js_async_generator_free(JSRuntime *rt,-                                    JSAsyncGeneratorData *s)-{-    struct list_head *el, *el1;-    JSAsyncGeneratorRequest *req;--    list_for_each_safe(el, el1, &s->queue) {-        req = list_entry(el, JSAsyncGeneratorRequest, link);-        JS_FreeValueRT(rt, req->result);-        JS_FreeValueRT(rt, req->promise);-        JS_FreeValueRT(rt, req->resolving_funcs[0]);-        JS_FreeValueRT(rt, req->resolving_funcs[1]);-        js_free_rt(rt, req);-    }-    if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&-        s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {-        async_func_free(rt, &s->func_state);-    }-    js_free_rt(rt, s);-}--static void js_async_generator_finalizer(JSRuntime *rt, JSValue obj)-{-    JSAsyncGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_ASYNC_GENERATOR);--    if (s) {-        js_async_generator_free(rt, s);-    }-}--static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,-                                    JS_MarkFunc *mark_func)-{-    JSAsyncGeneratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_GENERATOR);-    struct list_head *el;-    JSAsyncGeneratorRequest *req;-    if (s) {-        list_for_each(el, &s->queue) {-            req = list_entry(el, JSAsyncGeneratorRequest, link);-            JS_MarkValue(rt, req->result, mark_func);-            JS_MarkValue(rt, req->promise, mark_func);-            JS_MarkValue(rt, req->resolving_funcs[0], mark_func);-            JS_MarkValue(rt, req->resolving_funcs[1], mark_func);-        }-        if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&-            s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {-            async_func_mark(rt, &s->func_state, mark_func);-        }-    }-}--static JSValue js_async_generator_resolve_function(JSContext *ctx,-                                          JSValueConst this_obj,-                                          int argc, JSValueConst *argv,-                                          int magic, JSValue *func_data);--static int js_async_generator_resolve_function_create(JSContext *ctx,-                                                      JSValueConst generator,-                                                      JSValue *resolving_funcs,-                                                      BOOL is_resume_next)-{-    int i;-    JSValue func;--    for(i = 0; i < 2; i++) {-        func = JS_NewCFunctionData(ctx, js_async_generator_resolve_function, 1,-                                   i + is_resume_next * 2, 1, &generator);-        if (JS_IsException(func)) {-            if (i == 1)-                JS_FreeValue(ctx, resolving_funcs[0]);-            return -1;-        }-        resolving_funcs[i] = func;-    }-    return 0;-}--static int js_async_generator_await(JSContext *ctx,-                                    JSAsyncGeneratorData *s,-                                    JSValueConst value)-{-    JSValue promise, resolving_funcs[2], resolving_funcs1[2];-    int i, res;--    promise = js_promise_resolve(ctx, ctx->promise_ctor,-                                 1, &value, 0);-    if (JS_IsException(promise))-        goto fail;--    if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator),-                                                   resolving_funcs, FALSE)) {-        JS_FreeValue(ctx, promise);-        goto fail;-    }--    /* Note: no need to create 'thrownawayCapability' as in-       the spec */-    for(i = 0; i < 2; i++)-        resolving_funcs1[i] = JS_UNDEFINED;-    res = perform_promise_then(ctx, promise,-                               (JSValueConst *)resolving_funcs,-                               (JSValueConst *)resolving_funcs1);-    JS_FreeValue(ctx, promise);-    for(i = 0; i < 2; i++)-        JS_FreeValue(ctx, resolving_funcs[i]);-    if (res)-        goto fail;-    return 0;- fail:-    return -1;-}--static void js_async_generator_resolve_or_reject(JSContext *ctx,-                                                 JSAsyncGeneratorData *s,-                                                 JSValueConst result,-                                                 int is_reject)-{-    JSAsyncGeneratorRequest *next;-    JSValue ret;--    next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);-    list_del(&next->link);-    ret = JS_Call(ctx, next->resolving_funcs[is_reject], JS_UNDEFINED, 1,-                  &result);-    JS_FreeValue(ctx, ret);-    JS_FreeValue(ctx, next->result);-    JS_FreeValue(ctx, next->promise);-    JS_FreeValue(ctx, next->resolving_funcs[0]);-    JS_FreeValue(ctx, next->resolving_funcs[1]);-    js_free(ctx, next);-}--static void js_async_generator_resolve(JSContext *ctx,-                                       JSAsyncGeneratorData *s,-                                       JSValueConst value,-                                       BOOL done)-{-    JSValue result;-    result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done);-    /* XXX: better exception handling ? */-    js_async_generator_resolve_or_reject(ctx, s, result, 0);-    JS_FreeValue(ctx, result);- }--static void js_async_generator_reject(JSContext *ctx,-                                       JSAsyncGeneratorData *s,-                                       JSValueConst exception)-{-    js_async_generator_resolve_or_reject(ctx, s, exception, 1);-}--static void js_async_generator_complete(JSContext *ctx,-                                        JSAsyncGeneratorData *s)-{-    if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) {-        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;-        async_func_free(ctx->rt, &s->func_state);-    }-}--static int js_async_generator_completed_return(JSContext *ctx,-                                               JSAsyncGeneratorData *s,-                                               JSValueConst value)-{-    JSValue promise, resolving_funcs[2], resolving_funcs1[2];-    int res;--    promise = js_promise_resolve(ctx, ctx->promise_ctor,-                                 1, (JSValueConst *)&value, 0);-    if (JS_IsException(promise))-        return -1;-    if (js_async_generator_resolve_function_create(ctx,-                                                   JS_MKPTR(JS_TAG_OBJECT, s->generator),-                                                   resolving_funcs1,-                                                   TRUE)) {-        JS_FreeValue(ctx, promise);-        return -1;-    }-    resolving_funcs[0] = JS_UNDEFINED;-    resolving_funcs[1] = JS_UNDEFINED;-    res = perform_promise_then(ctx, promise,-                               (JSValueConst *)resolving_funcs1,-                               (JSValueConst *)resolving_funcs);-    JS_FreeValue(ctx, resolving_funcs1[0]);-    JS_FreeValue(ctx, resolving_funcs1[1]);-    JS_FreeValue(ctx, promise);-    return res;-}--static void js_async_generator_resume_next(JSContext *ctx,-                                           JSAsyncGeneratorData *s)-{-    JSAsyncGeneratorRequest *next;-    JSValue func_ret, value;--    for(;;) {-        if (list_empty(&s->queue))-            break;-        next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);-        switch(s->state) {-        case JS_ASYNC_GENERATOR_STATE_EXECUTING:-            /* only happens when restarting execution after await() */-            goto resume_exec;-        case JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN:-            goto done;-        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_START:-            if (next->completion_type == GEN_MAGIC_NEXT) {-                goto exec_no_arg;-            } else {-                js_async_generator_complete(ctx, s);-            }-            break;-        case JS_ASYNC_GENERATOR_STATE_COMPLETED:-            if (next->completion_type == GEN_MAGIC_NEXT) {-                js_async_generator_resolve(ctx, s, JS_UNDEFINED, TRUE);-            } else if (next->completion_type == GEN_MAGIC_RETURN) {-                s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;-                js_async_generator_completed_return(ctx, s, next->result);-                goto done;-            } else {-                js_async_generator_reject(ctx, s, next->result);-            }-            goto done;-        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD:-        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR:-            value = JS_DupValue(ctx, next->result);-            if (next->completion_type == GEN_MAGIC_THROW &&-                s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {-                JS_Throw(ctx, value);-                s->func_state.throw_flag = TRUE;-            } else {-                /* 'yield' returns a value. 'yield *' also returns a value-                   in case the 'throw' method is called */-                s->func_state.frame.cur_sp[-1] = value;-                s->func_state.frame.cur_sp[0] =-                    JS_NewInt32(ctx, next->completion_type);-                s->func_state.frame.cur_sp++;-            exec_no_arg:-                s->func_state.throw_flag = FALSE;-            }-            s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;-        resume_exec:-            func_ret = async_func_resume(ctx, &s->func_state);-            if (JS_IsException(func_ret)) {-                value = JS_GetException(ctx);-                js_async_generator_complete(ctx, s);-                js_async_generator_reject(ctx, s, value);-                JS_FreeValue(ctx, value);-            } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {-                int func_ret_code;-                value = s->func_state.frame.cur_sp[-1];-                s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;-                func_ret_code = JS_VALUE_GET_INT(func_ret);-                switch(func_ret_code) {-                case FUNC_RET_YIELD:-                case FUNC_RET_YIELD_STAR:-                    if (func_ret_code == FUNC_RET_YIELD_STAR)-                        s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR;-                    else-                        s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD;-                    js_async_generator_resolve(ctx, s, value, FALSE);-                    JS_FreeValue(ctx, value);-                    break;-                case FUNC_RET_AWAIT:-                    js_async_generator_await(ctx, s, value);-                    JS_FreeValue(ctx, value);-                    goto done;-                default:-                    abort();-                }-            } else {-                assert(JS_IsUndefined(func_ret));-                /* end of function */-                value = s->func_state.frame.cur_sp[-1];-                s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;-                js_async_generator_complete(ctx, s);-                js_async_generator_resolve(ctx, s, value, TRUE);-                JS_FreeValue(ctx, value);-            }-            break;-        default:-            abort();-        }-    }- done: ;-}--static JSValue js_async_generator_resolve_function(JSContext *ctx,-                                                   JSValueConst this_obj,-                                                   int argc, JSValueConst *argv,-                                                   int magic, JSValue *func_data)-{-    BOOL is_reject = magic & 1;-    JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR);-    JSValueConst arg = argv[0];--    /* XXX: what if s == NULL */--    if (magic >= 2) {-        /* resume next case in AWAITING_RETURN state */-        assert(s->state == JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN ||-               s->state == JS_ASYNC_GENERATOR_STATE_COMPLETED);-        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;-        if (is_reject) {-            js_async_generator_reject(ctx, s, arg);-        } else {-            js_async_generator_resolve(ctx, s, arg, TRUE);-        }-    } else {-        /* restart function execution after await() */-        assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);-        s->func_state.throw_flag = is_reject;-        if (is_reject) {-            JS_Throw(ctx, JS_DupValue(ctx, arg));-        } else {-            /* return value of await */-            s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);-        }-        js_async_generator_resume_next(ctx, s);-    }-    return JS_UNDEFINED;-}--/* magic = GEN_MAGIC_x */-static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv,-                                       int magic)-{-    JSAsyncGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_GENERATOR);-    JSValue promise, resolving_funcs[2];-    JSAsyncGeneratorRequest *req;--    promise = JS_NewPromiseCapability(ctx, resolving_funcs);-    if (JS_IsException(promise))-        return JS_EXCEPTION;-    if (!s) {-        JSValue err, res2;-        JS_ThrowTypeError(ctx, "not an AsyncGenerator object");-        err = JS_GetException(ctx);-        res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,-                       1, (JSValueConst *)&err);-        JS_FreeValue(ctx, err);-        JS_FreeValue(ctx, res2);-        JS_FreeValue(ctx, resolving_funcs[0]);-        JS_FreeValue(ctx, resolving_funcs[1]);-        return promise;-    }-    req = js_mallocz(ctx, sizeof(*req));-    if (!req)-        goto fail;-    req->completion_type = magic;-    req->result = JS_DupValue(ctx, argv[0]);-    req->promise = JS_DupValue(ctx, promise);-    req->resolving_funcs[0] = resolving_funcs[0];-    req->resolving_funcs[1] = resolving_funcs[1];-    list_add_tail(&req->link, &s->queue);-    if (s->state != JS_ASYNC_GENERATOR_STATE_EXECUTING) {-        js_async_generator_resume_next(ctx, s);-    }-    return promise;- fail:-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    JS_FreeValue(ctx, promise);-    return JS_EXCEPTION;-}--static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj,-                                                JSValueConst this_obj,-                                                int argc, JSValueConst *argv,-                                                int flags)-{-    JSValue obj, func_ret;-    JSAsyncGeneratorData *s;--    s = js_mallocz(ctx, sizeof(*s));-    if (!s)-        return JS_EXCEPTION;-    s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START;-    init_list_head(&s->queue);-    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {-        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;-        goto fail;-    }--    /* execute the function up to 'OP_initial_yield' (no yield nor-       await are possible) */-    func_ret = async_func_resume(ctx, &s->func_state);-    if (JS_IsException(func_ret))-        goto fail;-    JS_FreeValue(ctx, func_ret);--    obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_ASYNC_GENERATOR);-    if (JS_IsException(obj))-        goto fail;-    s->generator = JS_VALUE_GET_OBJ(obj);-    JS_SetOpaque(obj, s);-    return obj;- fail:-    js_async_generator_free(ctx->rt, s);-    return JS_EXCEPTION;-}--/* JS parser */--enum {-    TOK_NUMBER = -128,-    TOK_STRING,-    TOK_TEMPLATE,-    TOK_IDENT,-    TOK_REGEXP,-    /* warning: order matters (see js_parse_assign_expr) */-    TOK_MUL_ASSIGN,-    TOK_DIV_ASSIGN,-    TOK_MOD_ASSIGN,-    TOK_PLUS_ASSIGN,-    TOK_MINUS_ASSIGN,-    TOK_SHL_ASSIGN,-    TOK_SAR_ASSIGN,-    TOK_SHR_ASSIGN,-    TOK_AND_ASSIGN,-    TOK_XOR_ASSIGN,-    TOK_OR_ASSIGN,-#ifdef CONFIG_BIGNUM-    TOK_MATH_POW_ASSIGN,-#endif-    TOK_POW_ASSIGN,-    TOK_LAND_ASSIGN,-    TOK_LOR_ASSIGN,-    TOK_DOUBLE_QUESTION_MARK_ASSIGN,-    TOK_DEC,-    TOK_INC,-    TOK_SHL,-    TOK_SAR,-    TOK_SHR,-    TOK_LT,-    TOK_LTE,-    TOK_GT,-    TOK_GTE,-    TOK_EQ,-    TOK_STRICT_EQ,-    TOK_NEQ,-    TOK_STRICT_NEQ,-    TOK_LAND,-    TOK_LOR,-#ifdef CONFIG_BIGNUM-    TOK_MATH_POW,-#endif-    TOK_POW,-    TOK_ARROW,-    TOK_ELLIPSIS,-    TOK_DOUBLE_QUESTION_MARK,-    TOK_QUESTION_MARK_DOT,-    TOK_ERROR,-    TOK_PRIVATE_NAME,-    TOK_EOF,-    /* keywords: WARNING: same order as atoms */-    TOK_NULL, /* must be first */-    TOK_FALSE,-    TOK_TRUE,-    TOK_IF,-    TOK_ELSE,-    TOK_RETURN,-    TOK_VAR,-    TOK_THIS,-    TOK_DELETE,-    TOK_VOID,-    TOK_TYPEOF,-    TOK_NEW,-    TOK_IN,-    TOK_INSTANCEOF,-    TOK_DO,-    TOK_WHILE,-    TOK_FOR,-    TOK_BREAK,-    TOK_CONTINUE,-    TOK_SWITCH,-    TOK_CASE,-    TOK_DEFAULT,-    TOK_THROW,-    TOK_TRY,-    TOK_CATCH,-    TOK_FINALLY,-    TOK_FUNCTION,-    TOK_DEBUGGER,-    TOK_WITH,-    /* FutureReservedWord */-    TOK_CLASS,-    TOK_CONST,-    TOK_ENUM,-    TOK_EXPORT,-    TOK_EXTENDS,-    TOK_IMPORT,-    TOK_SUPER,-    /* FutureReservedWords when parsing strict mode code */-    TOK_IMPLEMENTS,-    TOK_INTERFACE,-    TOK_LET,-    TOK_PACKAGE,-    TOK_PRIVATE,-    TOK_PROTECTED,-    TOK_PUBLIC,-    TOK_STATIC,-    TOK_YIELD,-    TOK_AWAIT, /* must be last */-    TOK_OF,     /* only used for js_parse_skip_parens_token() */-};--#define TOK_FIRST_KEYWORD   TOK_NULL-#define TOK_LAST_KEYWORD    TOK_AWAIT--/* unicode code points */-#define CP_NBSP 0x00a0-#define CP_BOM  0xfeff--#define CP_LS   0x2028-#define CP_PS   0x2029--typedef struct BlockEnv {-    struct BlockEnv *prev;-    JSAtom label_name; /* JS_ATOM_NULL if none */-    int label_break; /* -1 if none */-    int label_cont; /* -1 if none */-    int drop_count; /* number of stack elements to drop */-    int label_finally; /* -1 if none */-    int scope_level;-    int has_iterator;-} BlockEnv;--typedef struct JSHoistedDef {-    int cpool_idx; /* -1 means variable global definition */-    uint8_t force_init : 1; /* initialize to undefined */-    uint8_t is_lexical : 1; /* global let/const definition */-    uint8_t is_const   : 1; /* const definition */-    int var_idx;   /* function object index if cpool_idx >= 0 */-    int scope_level;    /* scope of definition */-    JSAtom var_name;  /* variable name if cpool_idx < 0 */-} JSHoistedDef;--typedef struct RelocEntry {-    struct RelocEntry *next;-    uint32_t addr; /* address to patch */-    int size;   /* address size: 1, 2 or 4 bytes */-} RelocEntry;--typedef struct JumpSlot {-    int op;-    int size;-    int pos;-    int label;-} JumpSlot;--typedef struct LabelSlot {-    int ref_count;-    int pos;    /* phase 1 address, -1 means not resolved yet */-    int pos2;   /* phase 2 address, -1 means not resolved yet */-    int addr;   /* phase 3 address, -1 means not resolved yet */-    RelocEntry *first_reloc;-} LabelSlot;--typedef struct LineNumberSlot {-    uint32_t pc;-    int line_num;-} LineNumberSlot;--typedef enum JSParseFunctionEnum {-    JS_PARSE_FUNC_STATEMENT,-    JS_PARSE_FUNC_VAR,-    JS_PARSE_FUNC_EXPR,-    JS_PARSE_FUNC_ARROW,-    JS_PARSE_FUNC_GETTER,-    JS_PARSE_FUNC_SETTER,-    JS_PARSE_FUNC_METHOD,-    JS_PARSE_FUNC_CLASS_CONSTRUCTOR,-    JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,-} JSParseFunctionEnum;--typedef enum JSParseExportEnum {-    JS_PARSE_EXPORT_NONE,-    JS_PARSE_EXPORT_NAMED,-    JS_PARSE_EXPORT_DEFAULT,-} JSParseExportEnum;--typedef struct JSFunctionDef {-    JSContext *ctx;-    struct JSFunctionDef *parent;-    int parent_cpool_idx; /* index in the constant pool of the parent-                             or -1 if none */-    int parent_scope_level; /* scope level in parent at point of definition */-    struct list_head child_list; /* list of JSFunctionDef.link */-    struct list_head link;--    BOOL is_eval; /* TRUE if eval code */-    int eval_type; /* only valid if is_eval = TRUE */-    BOOL is_global_var; /* TRUE if variables are not defined locally:-                           eval global, eval module or non strict eval */-    BOOL is_func_expr; /* TRUE if function expression */-    BOOL has_home_object; /* TRUE if the home object is available */-    BOOL has_prototype; /* true if a prototype field is necessary */-    BOOL has_simple_parameter_list;-    BOOL has_use_strict; /* to reject directive in special cases */-    BOOL has_eval_call; /* true if the function contains a call to eval() */-    BOOL has_arguments_binding; /* true if the 'arguments' binding is-                                   available in the function */-    BOOL has_this_binding; /* true if the 'this' and new.target binding are-                              available in the function */-    BOOL new_target_allowed; /* true if the 'new.target' does not-                                throw a syntax error */-    BOOL super_call_allowed; /* true if super() is allowed */-    BOOL super_allowed; /* true if super. or super[] is allowed */-    BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */-    BOOL is_derived_class_constructor;-    BOOL in_function_body;-    BOOL backtrace_barrier;-    JSFunctionKindEnum func_kind : 8;-    JSParseFunctionEnum func_type : 8;-    uint8_t js_mode; /* bitmap of JS_MODE_x */-    JSAtom func_name; /* JS_ATOM_NULL if no name */--    JSVarDef *vars;-    int var_size; /* allocated size for vars[] */-    int var_count;-    JSVarDef *args;-    int arg_size; /* allocated size for args[] */-    int arg_count; /* number of arguments */-    int defined_arg_count;-    int var_object_idx; /* -1 if none */-    int arguments_var_idx; /* -1 if none */-    int func_var_idx; /* variable containing the current function (-1-                         if none, only used if is_func_expr is true) */-    int eval_ret_idx; /* variable containing the return value of the eval, -1 if none */-    int this_var_idx; /* variable containg the 'this' value, -1 if none */-    int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */-    int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */-    int home_object_var_idx;-    BOOL need_home_object;-    -    int scope_level;    /* index into fd->scopes if the current lexical scope */-    int scope_first;    /* index into vd->vars of first lexically scoped variable */-    int scope_size;     /* allocated size of fd->scopes array */-    int scope_count;    /* number of entries used in the fd->scopes array */-    JSVarScope *scopes;-    JSVarScope def_scope_array[4];--    int hoisted_def_count;-    int hoisted_def_size;-    JSHoistedDef *hoisted_def;--    DynBuf byte_code;-    int last_opcode_pos; /* -1 if no last opcode */-    int last_opcode_line_num;-    BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */-    -    LabelSlot *label_slots;-    int label_size; /* allocated size for label_slots[] */-    int label_count;-    BlockEnv *top_break; /* break/continue label stack */--    /* constant pool (strings, functions, numbers) */-    JSValue *cpool;-    int cpool_count;-    int cpool_size;--    /* list of variables in the closure */-    int closure_var_count;-    int closure_var_size;-    JSClosureVar *closure_var;--    JumpSlot *jump_slots;-    int jump_size;-    int jump_count;--    LineNumberSlot *line_number_slots;-    int line_number_size;-    int line_number_count;-    int line_number_last;-    int line_number_last_pc;--    /* pc2line table */-    JSAtom filename;-    int line_num;-    DynBuf pc2line;--    char *source;  /* raw source, utf-8 encoded */-    int source_len;--    JSModuleDef *module; /* != NULL when parsing a module */-} JSFunctionDef;--typedef struct JSToken {-    int val;-    int line_num;   /* line number of token start */-    const uint8_t *ptr;-    union {-        struct {-            JSValue str;-            int sep;-        } str;-        struct {-            JSValue val;-#ifdef CONFIG_BIGNUM-            slimb_t exponent; /* may be != 0 only if val is a float */-#endif-        } num;-        struct {-            JSAtom atom;-            BOOL has_escape;-            BOOL is_reserved;-        } ident;-        struct {-            JSValue body;-            JSValue flags;-        } regexp;-    } u;-} JSToken;--typedef struct JSParseState {-    JSContext *ctx;-    int last_line_num;  /* line number of last token */-    int line_num;       /* line number of current offset */-    const char *filename;-    JSToken token;-    BOOL got_lf; /* true if got line feed before the current token */-    const uint8_t *last_ptr;-    const uint8_t *buf_ptr;-    const uint8_t *buf_end;--    /* current function code */-    JSFunctionDef *cur_func;-    BOOL is_module; /* parsing a module */-    BOOL allow_html_comments;-    BOOL ext_json; /* true if accepting JSON superset */-} JSParseState;--typedef struct JSOpCode {-#ifdef DUMP_BYTECODE-    const char *name;-#endif-    uint8_t size; /* in bytes */-    /* the opcodes remove n_pop items from the top of the stack, then-       pushes n_push items */-    uint8_t n_pop;-    uint8_t n_push;-    uint8_t fmt;-} JSOpCode;--static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {-#define FMT(f)-#ifdef DUMP_BYTECODE-#define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f },-#else-#define DEF(id, size, n_pop, n_push, f) { size, n_pop, n_push, OP_FMT_ ## f },-#endif-#include "quickjs-opcode.h"-#undef DEF-#undef FMT-};--#if SHORT_OPCODES-/* After the final compilation pass, short opcodes are used. Their-   opcodes overlap with the temporary opcodes which cannot appear in-   the final bytecode. Their description is after the temporary-   opcodes in opcode_info[]. */-#define short_opcode_info(op)           \-    opcode_info[(op) >= OP_TEMP_START ? \-                (op) + (OP_TEMP_END - OP_TEMP_START) : (op)]-#else-#define short_opcode_info(op) opcode_info[op]-#endif--static __exception int next_token(JSParseState *s);--static void free_token(JSParseState *s, JSToken *token)-{-    switch(token->val) {-#ifdef CONFIG_BIGNUM-    case TOK_NUMBER:-        JS_FreeValue(s->ctx, token->u.num.val);-        break;-#endif-    case TOK_STRING:-    case TOK_TEMPLATE:-        JS_FreeValue(s->ctx, token->u.str.str);-        break;-    case TOK_REGEXP:-        JS_FreeValue(s->ctx, token->u.regexp.body);-        JS_FreeValue(s->ctx, token->u.regexp.flags);-        break;-    case TOK_IDENT:-    case TOK_PRIVATE_NAME:-        JS_FreeAtom(s->ctx, token->u.ident.atom);-        break;-    default:-        if (token->val >= TOK_FIRST_KEYWORD &&-            token->val <= TOK_LAST_KEYWORD) {-            JS_FreeAtom(s->ctx, token->u.ident.atom);-        }-        break;-    }-}--static void __attribute((unused)) dump_token(JSParseState *s,-                                             const JSToken *token)-{-    switch(token->val) {-    case TOK_NUMBER:-        {-            double d;-            JS_ToFloat64(s->ctx, &d, token->u.num.val);  /* no exception possible */-            printf("number: %.14g\n", d);-        }-        break;-    case TOK_IDENT:-    dump_atom:-        {-            char buf[ATOM_GET_STR_BUF_SIZE];-            printf("ident: '%s'\n",-                   JS_AtomGetStr(s->ctx, buf, sizeof(buf), token->u.ident.atom));-        }-        break;-    case TOK_STRING:-        {-            const char *str;-            /* XXX: quote the string */-            str = JS_ToCString(s->ctx, token->u.str.str);-            printf("string: '%s'\n", str);-            JS_FreeCString(s->ctx, str);-        }-        break;-    case TOK_TEMPLATE:-        {-            const char *str;-            str = JS_ToCString(s->ctx, token->u.str.str);-            printf("template: `%s`\n", str);-            JS_FreeCString(s->ctx, str);-        }-        break;-    case TOK_REGEXP:-        {-            const char *str, *str2;-            str = JS_ToCString(s->ctx, token->u.regexp.body);-            str2 = JS_ToCString(s->ctx, token->u.regexp.flags);-            printf("regexp: '%s' '%s'\n", str, str2);-            JS_FreeCString(s->ctx, str);-            JS_FreeCString(s->ctx, str2);-        }-        break;-    case TOK_EOF:-        printf("eof\n");-        break;-    default:-        if (s->token.val >= TOK_NULL && s->token.val <= TOK_LAST_KEYWORD) {-            goto dump_atom;-        } else if (s->token.val >= 256) {-            printf("token: %d\n", token->val);-        } else {-            printf("token: '%c'\n", token->val);-        }-        break;-    }-}--int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const char *fmt, ...)-{-    JSContext *ctx = s->ctx;-    va_list ap;-    int backtrace_flags;-    -    va_start(ap, fmt);-    JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);-    va_end(ap);-    backtrace_flags = 0;-    if (s->cur_func && s->cur_func->backtrace_barrier)-        backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;-    build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,-                    backtrace_flags);-    return -1;-}--static int js_parse_expect(JSParseState *s, int tok)-{-    if (s->token.val != tok) {-        /* XXX: dump token correctly in all cases */-        return js_parse_error(s, "expecting '%c'", tok);-    }-    return next_token(s);-}--static int js_parse_expect_semi(JSParseState *s)-{-    if (s->token.val != ';') {-        /* automatic insertion of ';' */-        if (s->token.val == TOK_EOF || s->token.val == '}' || s->got_lf) {-            return 0;-        }-        return js_parse_error(s, "expecting '%c'", ';');-    }-    return next_token(s);-}--static int js_parse_error_reserved_identifier(JSParseState *s)-{-    char buf1[ATOM_GET_STR_BUF_SIZE];-    return js_parse_error(s, "'%s' is a reserved identifier",-                          JS_AtomGetStr(s->ctx, buf1, sizeof(buf1),-                                        s->token.u.ident.atom));-}--static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)-{-    uint32_t c;-    StringBuffer b_s, *b = &b_s;--    /* p points to the first byte of the template part */-    if (string_buffer_init(s->ctx, b, 32))-        goto fail;-    for(;;) {-        if (p >= s->buf_end)-            goto unexpected_eof;-        c = *p++;-        if (c == '`') {-            /* template end part */-            break;-        }-        if (c == '$' && *p == '{') {-            /* template start or middle part */-            p++;-            break;-        }-        if (c == '\\') {-            if (string_buffer_putc8(b, c))-                goto fail;-            if (p >= s->buf_end)-                goto unexpected_eof;-            c = *p++;-        }-        /* newline sequences are normalized as single '\n' bytes */-        if (c == '\r') {-            if (*p == '\n')-                p++;-            c = '\n';-        }-        if (c == '\n') {-            s->line_num++;-        } else if (c >= 0x80) {-            const uint8_t *p_next;-            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);-            if (c > 0x10FFFF) {-                js_parse_error(s, "invalid UTF-8 sequence");-                goto fail;-            }-            p = p_next;-        }-        if (string_buffer_putc(b, c))-            goto fail;-    }-    s->token.val = TOK_TEMPLATE;-    s->token.u.str.sep = c;-    s->token.u.str.str = string_buffer_end(b);-    s->buf_ptr = p;-    return 0;-- unexpected_eof:-    js_parse_error(s, "unexpected end of string");- fail:-    string_buffer_free(b);-    return -1;-}--static __exception int js_parse_string(JSParseState *s, int sep,-                                       BOOL do_throw, const uint8_t *p,-                                       JSToken *token, const uint8_t **pp)-{-    int ret;-    uint32_t c;-    StringBuffer b_s, *b = &b_s;--    /* string */-    if (string_buffer_init(s->ctx, b, 32))-        goto fail;-    for(;;) {-        if (p >= s->buf_end)-            goto invalid_char;-        c = *p;-        if (c < 0x20) {-            if (!s->cur_func) {-                if (do_throw)-                    js_parse_error(s, "invalid character in a JSON string");-                goto fail;-            }-            if (sep == '`') {-                if (c == '\r') {-                    if (p[1] == '\n')-                        p++;-                    c = '\n';-                }-                /* do not update s->line_num */-            } else if (c == '\n' || c == '\r')-                goto invalid_char;-        }-        p++;-        if (c == sep)-            break;-        if (c == '$' && *p == '{' && sep == '`') {-            /* template start or middle part */-            p++;-            break;-        }-        if (c == '\\') {-            c = *p;-            /* XXX: need a specific JSON case to avoid-               accepting invalid escapes */-            switch(c) {-            case '\0':-                if (p >= s->buf_end)-                    goto invalid_char;-                p++;-                break;-            case '\'':-            case '\"':-            case '\\':-                p++;-                break;-            case '\r':  /* accept DOS and MAC newline sequences */-                if (p[1] == '\n') {-                    p++;-                }-                /* fall thru */-            case '\n':-                /* ignore escaped newline sequence */-                p++;-                if (sep != '`')-                    s->line_num++;-                continue;-            default:-                if (c >= '0' && c <= '9') {-                    if (!s->cur_func)-                        goto invalid_escape; /* JSON case */-                    if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')-                        goto parse_escape;-                    if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {-                        p++;-                        c = '\0';-                    } else {-                        if (c >= '8' || sep == '`') {-                            /* Note: according to ES2021, \8 and \9 are not-                               accepted in strict mode or in templates. */-                            goto invalid_escape;-                        } else {-                            if (do_throw)-                                js_parse_error(s, "octal escape sequences are not allowed in strict mode");-                        }-                        goto fail;-                    }-                } else if (c >= 0x80) {-                    const uint8_t *p_next;-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);-                    if (c > 0x10FFFF) {-                        goto invalid_utf8;-                    }-                    p = p_next;-                    /* LS or PS are skipped */-                    if (c == CP_LS || c == CP_PS)-                        continue;-                } else {-                parse_escape:-                    ret = lre_parse_escape(&p, TRUE);-                    if (ret == -1) {-                    invalid_escape:-                        if (do_throw)-                            js_parse_error(s, "malformed escape sequence in string literal");-                        goto fail;-                    } else if (ret < 0) {-                        /* ignore the '\' (could output a warning) */-                        p++;-                    } else {-                        c = ret;-                    }-                }-                break;-            }-        } else if (c >= 0x80) {-            const uint8_t *p_next;-            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);-            if (c > 0x10FFFF)-                goto invalid_utf8;-            p = p_next;-        }-        if (string_buffer_putc(b, c))-            goto fail;-    }-    token->val = TOK_STRING;-    token->u.str.sep = c;-    token->u.str.str = string_buffer_end(b);-    *pp = p;-    return 0;-- invalid_utf8:-    if (do_throw)-        js_parse_error(s, "invalid UTF-8 sequence");-    goto fail;- invalid_char:-    if (do_throw)-        js_parse_error(s, "unexpected end of string");- fail:-    string_buffer_free(b);-    return -1;-}--static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {-    return s->token.val == TOK_IDENT && s->token.u.ident.atom == atom &&-        !s->token.u.ident.has_escape;-}--static __exception int js_parse_regexp(JSParseState *s)-{-    const uint8_t *p;-    BOOL in_class;-    StringBuffer b_s, *b = &b_s;-    StringBuffer b2_s, *b2 = &b2_s;-    uint32_t c;--    p = s->buf_ptr;-    p++;-    in_class = FALSE;-    if (string_buffer_init(s->ctx, b, 32))-        return -1;-    if (string_buffer_init(s->ctx, b2, 1))-        goto fail;-    for(;;) {-        if (p >= s->buf_end) {-        eof_error:-            js_parse_error(s, "unexpected end of regexp");-            goto fail;-        }-        c = *p++;-        if (c == '\n' || c == '\r') {-            goto eol_error;-        } else if (c == '/') {-            if (!in_class)-                break;-        } else if (c == '[') {-            in_class = TRUE;-        } else if (c == ']') {-            /* XXX: incorrect as the first character in a class */-            in_class = FALSE;-        } else if (c == '\\') {-            if (string_buffer_putc8(b, c))-                goto fail;-            c = *p++;-            if (c == '\n' || c == '\r')-                goto eol_error;-            else if (c == '\0' && p >= s->buf_end)-                goto eof_error;-            else if (c >= 0x80) {-                const uint8_t *p_next;-                c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);-                if (c > 0x10FFFF) {-                    goto invalid_utf8;-                }-                p = p_next;-                if (c == CP_LS || c == CP_PS)-                    goto eol_error;-            }-        } else if (c >= 0x80) {-            const uint8_t *p_next;-            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);-            if (c > 0x10FFFF) {-            invalid_utf8:-                js_parse_error(s, "invalid UTF-8 sequence");-                goto fail;-            }-            p = p_next;-            /* LS or PS are considered as line terminator */-            if (c == CP_LS || c == CP_PS) {-            eol_error:-                js_parse_error(s, "unexpected line terminator in regexp");-                goto fail;-            }-        }-        if (string_buffer_putc(b, c))-            goto fail;-    }--    /* flags */-    for(;;) {-        const uint8_t *p_next = p;-        c = *p_next++;-        if (c >= 0x80) {-            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);-            if (c > 0x10FFFF) {-                goto invalid_utf8;-            }-        }-        if (!lre_js_is_ident_next(c))-            break;-        if (string_buffer_putc(b2, c))-            goto fail;-        p = p_next;-    }--    s->token.val = TOK_REGEXP;-    s->token.u.regexp.body = string_buffer_end(b);-    s->token.u.regexp.flags = string_buffer_end(b2);-    s->buf_ptr = p;-    return 0;- fail:-    string_buffer_free(b);-    string_buffer_free(b2);-    return -1;-}--static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,-                                     char *static_buf)-{-    char *buf, *new_buf;-    size_t size, new_size;-    -    buf = *pbuf;-    size = *psize;-    if (size >= (SIZE_MAX / 3) * 2)-        new_size = SIZE_MAX;-    else-        new_size = size + (size >> 1);-    if (buf == static_buf) {-        new_buf = js_malloc(ctx, new_size);-        if (!new_buf)-            return -1;-        memcpy(new_buf, buf, size);-    } else {-        new_buf = js_realloc(ctx, buf, new_size);-        if (!new_buf)-            return -1;-    }-    *pbuf = new_buf;-    *psize = new_size;-    return 0;-}--/* 'c' is the first character. Return JS_ATOM_NULL in case of error */-static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,-                          BOOL *pident_has_escape, int c, BOOL is_private)-{-    const uint8_t *p, *p1;-    char ident_buf[128], *buf;-    size_t ident_size, ident_pos;-    JSAtom atom;-    -    p = *pp;-    buf = ident_buf;-    ident_size = sizeof(ident_buf);-    ident_pos = 0;-    if (is_private)-        buf[ident_pos++] = '#';-    for(;;) {-        p1 = p;-        -        if (c < 128) {-            buf[ident_pos++] = c;-        } else {-            ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c);-        }-        c = *p1++;-        if (c == '\\' && *p1 == 'u') {-            c = lre_parse_escape(&p1, TRUE);-            *pident_has_escape = TRUE;-        } else if (c >= 128) {-            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);-        }-        if (!lre_js_is_ident_next(c))-            break;-        p = p1;-        if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {-            if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {-                atom = JS_ATOM_NULL;-                goto done;-            }-        }-    }-    atom = JS_NewAtomLen(s->ctx, buf, ident_pos);- done:-    if (unlikely(buf != ident_buf))-        js_free(s->ctx, buf);-    *pp = p;-    return atom;-}---static __exception int next_token(JSParseState *s)-{-    const uint8_t *p;-    int c;-    BOOL ident_has_escape;-    JSAtom atom;-    -    if (js_check_stack_overflow(s->ctx->rt, 0)) {-        return js_parse_error(s, "stack overflow");-    }-    -    free_token(s, &s->token);--    p = s->last_ptr = s->buf_ptr;-    s->got_lf = FALSE;-    s->last_line_num = s->token.line_num;- redo:-    s->token.line_num = s->line_num;-    s->token.ptr = p;-    c = *p;-    switch(c) {-    case 0:-        if (p >= s->buf_end) {-            s->token.val = TOK_EOF;-        } else {-            goto def_token;-        }-        break;-    case '`':-        if (js_parse_template_part(s, p + 1))-            goto fail;-        p = s->buf_ptr;-        break;-    case '\'':-    case '\"':-        if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))-            goto fail;-        break;-    case '\r':  /* accept DOS and MAC newline sequences */-        if (p[1] == '\n') {-            p++;-        }-        /* fall thru */-    case '\n':-        p++;-    line_terminator:-        s->got_lf = TRUE;-        s->line_num++;-        goto redo;-    case '\f':-    case '\v':-    case ' ':-    case '\t':-        p++;-        goto redo;-    case '/':-        if (p[1] == '*') {-            /* comment */-            p += 2;-            for(;;) {-                if (*p == '\0' && p >= s->buf_end) {-                    js_parse_error(s, "unexpected end of comment");-                    goto fail;-                }-                if (p[0] == '*' && p[1] == '/') {-                    p += 2;-                    break;-                }-                if (*p == '\n') {-                    s->line_num++;-                    s->got_lf = TRUE; /* considered as LF for ASI */-                    p++;-                } else if (*p == '\r') {-                    s->got_lf = TRUE; /* considered as LF for ASI */-                    p++;-                } else if (*p >= 0x80) {-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-                    if (c == CP_LS || c == CP_PS) {-                        s->got_lf = TRUE; /* considered as LF for ASI */-                    } else if (c == -1) {-                        p++; /* skip invalid UTF-8 */-                    }-                } else {-                    p++;-                }-            }-            goto redo;-        } else if (p[1] == '/') {-            /* line comment */-            p += 2;-        skip_line_comment:-            for(;;) {-                if (*p == '\0' && p >= s->buf_end)-                    break;-                if (*p == '\r' || *p == '\n')-                    break;-                if (*p >= 0x80) {-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-                    /* LS or PS are considered as line terminator */-                    if (c == CP_LS || c == CP_PS) {-                        break;-                    } else if (c == -1) {-                        p++; /* skip invalid UTF-8 */-                    }-                } else {-                    p++;-                }-            }-            goto redo;-        } else if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_DIV_ASSIGN;-        } else {-            p++;-            s->token.val = c;-        }-        break;-    case '\\':-        if (p[1] == 'u') {-            const uint8_t *p1 = p + 1;-            int c1 = lre_parse_escape(&p1, TRUE);-            if (c1 >= 0 && lre_js_is_ident_first(c1)) {-                c = c1;-                p = p1;-                ident_has_escape = TRUE;-                goto has_ident;-            } else {-                /* XXX: syntax error? */-            }-        }-        goto def_token;-    case 'a': case 'b': case 'c': case 'd':-    case 'e': case 'f': case 'g': case 'h':-    case 'i': case 'j': case 'k': case 'l':-    case 'm': case 'n': case 'o': case 'p':-    case 'q': case 'r': case 's': case 't':-    case 'u': case 'v': case 'w': case 'x':-    case 'y': case 'z': -    case 'A': case 'B': case 'C': case 'D':-    case 'E': case 'F': case 'G': case 'H':-    case 'I': case 'J': case 'K': case 'L':-    case 'M': case 'N': case 'O': case 'P':-    case 'Q': case 'R': case 'S': case 'T':-    case 'U': case 'V': case 'W': case 'X':-    case 'Y': case 'Z': -    case '_':-    case '$':-        /* identifier */-        p++;-        ident_has_escape = FALSE;-    has_ident:-        atom = parse_ident(s, &p, &ident_has_escape, c, FALSE);-        if (atom == JS_ATOM_NULL)-            goto fail;-        s->token.u.ident.atom = atom;-        s->token.u.ident.has_escape = ident_has_escape;-        s->token.u.ident.is_reserved = FALSE;-        if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||-            (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&-             (s->cur_func->js_mode & JS_MODE_STRICT)) ||-            (s->token.u.ident.atom == JS_ATOM_yield &&-             ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||-              (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&-               !s->cur_func->in_function_body && s->cur_func->parent &&-               (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||-            (s->token.u.ident.atom == JS_ATOM_await &&-             (s->is_module ||-              (((s->cur_func->func_kind & JS_FUNC_ASYNC) ||-                (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&-                 !s->cur_func->in_function_body && s->cur_func->parent &&-                 (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {-                  if (ident_has_escape) {-                      s->token.u.ident.is_reserved = TRUE;-                      s->token.val = TOK_IDENT;-                  } else {-                      /* The keywords atoms are pre allocated */-                      s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;-                  }-        } else {-            s->token.val = TOK_IDENT;-        }-        break;-    case '#':-        /* private name */-        {-            const uint8_t *p1;-            p++;-            p1 = p;-            c = *p1++;-            if (c == '\\' && *p1 == 'u') {-                c = lre_parse_escape(&p1, TRUE);-            } else if (c >= 128) {-                c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);-            }-            if (!lre_js_is_ident_first(c)) {-                js_parse_error(s, "invalid first character of private name");-                goto fail;-            }-            p = p1;-            ident_has_escape = FALSE; /* not used */-            atom = parse_ident(s, &p, &ident_has_escape, c, TRUE);-            if (atom == JS_ATOM_NULL)-                goto fail;-            s->token.u.ident.atom = atom;-            s->token.val = TOK_PRIVATE_NAME;-        }-        break;-    case '.':-        if (p[1] == '.' && p[2] == '.') {-            p += 3;-            s->token.val = TOK_ELLIPSIS;-            break;-        }-        if (p[1] >= '0' && p[1] <= '9') {-            goto parse_number;-        } else {-            goto def_token;-        }-        break;-    case '0':-        /* in strict mode, octal literals are not accepted */-        if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) {-            js_parse_error(s, "octal literals are deprecated in strict mode");-            goto fail;-        }-        goto parse_number;-    case '1': case '2': case '3': case '4':-    case '5': case '6': case '7': case '8':-    case '9': -        /* number */-    parse_number:-        {-            JSValue ret;-            const uint8_t *p1;-            int flags, radix;-            flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |-                ATOD_ACCEPT_UNDERSCORES;-#ifdef CONFIG_BIGNUM-            flags |= ATOD_ACCEPT_SUFFIX;-            if (s->cur_func->js_mode & JS_MODE_MATH) {-                flags |= ATOD_MODE_BIGINT;-                if (s->cur_func->js_mode & JS_MODE_MATH)-                    flags |= ATOD_TYPE_BIG_FLOAT;-            }-#endif-            radix = 0;-#ifdef CONFIG_BIGNUM-            s->token.u.num.exponent = 0;-            ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix,-                           flags, &s->token.u.num.exponent);-#else-            ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,-                          flags);-#endif-            if (JS_IsException(ret))-                goto fail;-            /* reject `10instanceof Number` */-            if (JS_VALUE_IS_NAN(ret) ||-                lre_js_is_ident_next(unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1))) {-                JS_FreeValue(s->ctx, ret);-                js_parse_error(s, "invalid number literal");-                goto fail;-            }-            s->token.val = TOK_NUMBER;-            s->token.u.num.val = ret;-        }-        break;-    case '*':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_MUL_ASSIGN;-        } else if (p[1] == '*') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_POW_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_POW;-            }-        } else {-            goto def_token;-        }-        break;-    case '%':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_MOD_ASSIGN;-        } else {-            goto def_token;-        }-        break;-    case '+':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_PLUS_ASSIGN;-        } else if (p[1] == '+') {-            p += 2;-            s->token.val = TOK_INC;-        } else {-            goto def_token;-        }-        break;-    case '-':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_MINUS_ASSIGN;-        } else if (p[1] == '-') {-            if (s->allow_html_comments &&-                p[2] == '>' && s->last_line_num != s->line_num) {-                /* Annex B: `-->` at beginning of line is an html comment end.-                   It extends to the end of the line.-                 */-                goto skip_line_comment;-            }-            p += 2;-            s->token.val = TOK_DEC;-        } else {-            goto def_token;-        }-        break;-    case '<':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_LTE;-        } else if (p[1] == '<') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_SHL_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_SHL;-            }-        } else if (s->allow_html_comments &&-                   p[1] == '!' && p[2] == '-' && p[3] == '-') {-            /* Annex B: handle `<!--` single line html comments */-            goto skip_line_comment;-        } else {-            goto def_token;-        }-        break;-    case '>':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_GTE;-        } else if (p[1] == '>') {-            if (p[2] == '>') {-                if (p[3] == '=') {-                    p += 4;-                    s->token.val = TOK_SHR_ASSIGN;-                } else {-                    p += 3;-                    s->token.val = TOK_SHR;-                }-            } else if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_SAR_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_SAR;-            }-        } else {-            goto def_token;-        }-        break;-    case '=':-        if (p[1] == '=') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_STRICT_EQ;-            } else {-                p += 2;-                s->token.val = TOK_EQ;-            }-        } else if (p[1] == '>') {-            p += 2;-            s->token.val = TOK_ARROW;-        } else {-            goto def_token;-        }-        break;-    case '!':-        if (p[1] == '=') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_STRICT_NEQ;-            } else {-                p += 2;-                s->token.val = TOK_NEQ;-            }-        } else {-            goto def_token;-        }-        break;-    case '&':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_AND_ASSIGN;-        } else if (p[1] == '&') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_LAND_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_LAND;-            }-        } else {-            goto def_token;-        }-        break;-#ifdef CONFIG_BIGNUM-        /* in math mode, '^' is the power operator. '^^' is always the-           xor operator and '**' is always the power operator */-    case '^':-        if (p[1] == '=') {-            p += 2;-            if (s->cur_func->js_mode & JS_MODE_MATH)-                s->token.val = TOK_MATH_POW_ASSIGN;-            else-                s->token.val = TOK_XOR_ASSIGN;-        } else if (p[1] == '^') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_XOR_ASSIGN;-            } else {-                p += 2;-                s->token.val = '^';-            }-        } else {-            p++;-            if (s->cur_func->js_mode & JS_MODE_MATH)-                s->token.val = TOK_MATH_POW;-            else-                s->token.val = '^';-        }-        break;-#else-    case '^':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_XOR_ASSIGN;-        } else {-            goto def_token;-        }-        break;-#endif-    case '|':-        if (p[1] == '=') {-            p += 2;-            s->token.val = TOK_OR_ASSIGN;-        } else if (p[1] == '|') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_LOR_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_LOR;-            }-        } else {-            goto def_token;-        }-        break;-    case '?':-        if (p[1] == '?') {-            if (p[2] == '=') {-                p += 3;-                s->token.val = TOK_DOUBLE_QUESTION_MARK_ASSIGN;-            } else {-                p += 2;-                s->token.val = TOK_DOUBLE_QUESTION_MARK;-            }-        } else if (p[1] == '.' && !(p[2] >= '0' && p[2] <= '9')) {-            p += 2;-            s->token.val = TOK_QUESTION_MARK_DOT;-        } else {-            goto def_token;-        }-        break;-    default:-        if (c >= 128) {-            /* unicode value */-            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-            switch(c) {-            case CP_PS:-            case CP_LS:-                /* XXX: should avoid incrementing line_number, but-                   needed to handle HTML comments */-                goto line_terminator; -            default:-                if (lre_is_space(c)) {-                    goto redo;-                } else if (lre_js_is_ident_first(c)) {-                    ident_has_escape = FALSE;-                    goto has_ident;-                } else {-                    js_parse_error(s, "unexpected character");-                    goto fail;-                }-            }-        }-    def_token:-        s->token.val = c;-        p++;-        break;-    }-    s->buf_ptr = p;--    //    dump_token(s, &s->token);-    return 0;-- fail:-    s->token.val = TOK_ERROR;-    return -1;-}--/* 'c' is the first character. Return JS_ATOM_NULL in case of error */-static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)-{-    const uint8_t *p;-    char ident_buf[128], *buf;-    size_t ident_size, ident_pos;-    JSAtom atom;-    -    p = *pp;-    buf = ident_buf;-    ident_size = sizeof(ident_buf);-    ident_pos = 0;-    for(;;) {-        buf[ident_pos++] = c;-        c = *p;-        if (c >= 128 ||-            !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))-            break;-        p++;-        if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {-            if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {-                atom = JS_ATOM_NULL;-                goto done;-            }-        }-    }-    atom = JS_NewAtomLen(s->ctx, buf, ident_pos);- done:-    if (unlikely(buf != ident_buf))-        js_free(s->ctx, buf);-    *pp = p;-    return atom;-}--static __exception int json_next_token(JSParseState *s)-{-    const uint8_t *p;-    int c;-    JSAtom atom;-    -    if (js_check_stack_overflow(s->ctx->rt, 0)) {-        return js_parse_error(s, "stack overflow");-    }-    -    free_token(s, &s->token);--    p = s->last_ptr = s->buf_ptr;-    s->last_line_num = s->token.line_num;- redo:-    s->token.line_num = s->line_num;-    s->token.ptr = p;-    c = *p;-    switch(c) {-    case 0:-        if (p >= s->buf_end) {-            s->token.val = TOK_EOF;-        } else {-            goto def_token;-        }-        break;-    case '\'':-        if (!s->ext_json) {-            /* JSON does not accept single quoted strings */-            goto def_token;-        }-        /* fall through */-    case '\"':-        if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))-            goto fail;-        break;-    case '\r':  /* accept DOS and MAC newline sequences */-        if (p[1] == '\n') {-            p++;-        }-        /* fall thru */-    case '\n':-        p++;-        s->line_num++;-        goto redo;-    case '\f':-    case '\v':-        if (!s->ext_json) {-            /* JSONWhitespace does not match <VT>, nor <FF> */-            goto def_token;-        }-        /* fall through */-    case ' ':-    case '\t':-        p++;-        goto redo;-    case '/':-        if (!s->ext_json) {-            /* JSON does not accept comments */-            goto def_token;-        }-        if (p[1] == '*') {-            /* comment */-            p += 2;-            for(;;) {-                if (*p == '\0' && p >= s->buf_end) {-                    js_parse_error(s, "unexpected end of comment");-                    goto fail;-                }-                if (p[0] == '*' && p[1] == '/') {-                    p += 2;-                    break;-                }-                if (*p == '\n') {-                    s->line_num++;-                    p++;-                } else if (*p == '\r') {-                    p++;-                } else if (*p >= 0x80) {-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-                    if (c == -1) {-                        p++; /* skip invalid UTF-8 */-                    }-                } else {-                    p++;-                }-            }-            goto redo;-        } else if (p[1] == '/') {-            /* line comment */-            p += 2;-            for(;;) {-                if (*p == '\0' && p >= s->buf_end)-                    break;-                if (*p == '\r' || *p == '\n')-                    break;-                if (*p >= 0x80) {-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-                    /* LS or PS are considered as line terminator */-                    if (c == CP_LS || c == CP_PS) {-                        break;-                    } else if (c == -1) {-                        p++; /* skip invalid UTF-8 */-                    }-                } else {-                    p++;-                }-            }-            goto redo;-        } else {-            goto def_token;-        }-        break;-    case 'a': case 'b': case 'c': case 'd':-    case 'e': case 'f': case 'g': case 'h':-    case 'i': case 'j': case 'k': case 'l':-    case 'm': case 'n': case 'o': case 'p':-    case 'q': case 'r': case 's': case 't':-    case 'u': case 'v': case 'w': case 'x':-    case 'y': case 'z': -    case 'A': case 'B': case 'C': case 'D':-    case 'E': case 'F': case 'G': case 'H':-    case 'I': case 'J': case 'K': case 'L':-    case 'M': case 'N': case 'O': case 'P':-    case 'Q': case 'R': case 'S': case 'T':-    case 'U': case 'V': case 'W': case 'X':-    case 'Y': case 'Z': -    case '_':-    case '$':-        /* identifier : only pure ascii characters are accepted */-        p++;-        atom = json_parse_ident(s, &p, c);-        if (atom == JS_ATOM_NULL)-            goto fail;-        s->token.u.ident.atom = atom;-        s->token.u.ident.has_escape = FALSE;-        s->token.u.ident.is_reserved = FALSE;-        s->token.val = TOK_IDENT;-        break;-    case '+':-        if (!s->ext_json || !is_digit(p[1]))-            goto def_token;-        goto parse_number;-    case '0':-        if (is_digit(p[1]))-            goto def_token;-        goto parse_number;-    case '-':-        if (!is_digit(p[1]))-            goto def_token;-        goto parse_number;-    case '1': case '2': case '3': case '4':-    case '5': case '6': case '7': case '8':-    case '9': -        /* number */-    parse_number:-        {-            JSValue ret;-            int flags, radix;-            if (!s->ext_json) {-                flags = 0;-                radix = 10;-            } else {-                flags = ATOD_ACCEPT_BIN_OCT;-                radix = 0;-            }-            ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,-                          flags);-            if (JS_IsException(ret))-                goto fail;-            s->token.val = TOK_NUMBER;-            s->token.u.num.val = ret;-        }-        break;-    default:-        if (c >= 128) {-            js_parse_error(s, "unexpected character");-            goto fail;-        }-    def_token:-        s->token.val = c;-        p++;-        break;-    }-    s->buf_ptr = p;--    //    dump_token(s, &s->token);-    return 0;-- fail:-    s->token.val = TOK_ERROR;-    return -1;-}--/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is-   only set if TOK_IMPORT is returned */-/* XXX: handle all unicode cases */-static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)-{-    const uint8_t *p;-    uint32_t c;-    -    /* skip spaces and comments */-    p = *pp;-    for (;;) {-        switch(c = *p++) {-        case '\r':-        case '\n':-            if (no_line_terminator)-                return '\n';-            continue;-        case ' ':-        case '\t':-        case '\v':-        case '\f':-            continue;-        case '/':-            if (*p == '/') {-                if (no_line_terminator)-                    return '\n';-                while (*p && *p != '\r' && *p != '\n')-                    p++;-                continue;-            }-            if (*p == '*') {-                while (*++p) {-                    if ((*p == '\r' || *p == '\n') && no_line_terminator)-                        return '\n';-                    if (*p == '*' && p[1] == '/') {-                        p += 2;-                        break;-                    }-                }-                continue;-            }-            break;-        case '=':-            if (*p == '>')-                return TOK_ARROW;-            break;-        default:-            if (lre_js_is_ident_first(c)) {-                if (c == 'i') {-                    if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) {-                        return TOK_IN;-                    }-                    if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' &&-                        p[3] == 'r' && p[4] == 't' &&-                        !lre_js_is_ident_next(p[5])) {-                        *pp = p + 5;-                        return TOK_IMPORT;-                    }-                } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {-                    return TOK_OF;-                } else if (c == 'e' &&-                           p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&-                           p[3] == 'r' && p[4] == 't' &&-                           !lre_js_is_ident_next(p[5])) {-                    *pp = p + 5;-                    return TOK_EXPORT;-                } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&-                         p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&-                         p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {-                    return TOK_FUNCTION;-                }-                return TOK_IDENT;-            }-            break;-        }-        return c;-    }-}--static int peek_token(JSParseState *s, BOOL no_line_terminator)-{-    const uint8_t *p = s->buf_ptr;-    return simple_next_token(&p, no_line_terminator);-}--/* return true if 'input' contains the source of a module-   (heuristic). 'input' must be a zero terminated.--   Heuristic: skip comments and expect 'import' keyword not followed-   by '(' or '.' or export keyword.-*/-BOOL JS_DetectModule(const char *input, size_t input_len)-{-    const uint8_t *p = (const uint8_t *)input;-    int tok;-    switch(simple_next_token(&p, FALSE)) {-    case TOK_IMPORT:-        tok = simple_next_token(&p, FALSE);-        return (tok != '.' && tok != '(');-    case TOK_EXPORT:-        return TRUE;-    default:-        return FALSE;-    }-}--static inline int get_prev_opcode(JSFunctionDef *fd) {-    if (fd->last_opcode_pos < 0)-        return OP_invalid;-    else-        return fd->byte_code.buf[fd->last_opcode_pos];-}--static BOOL js_is_live_code(JSParseState *s) {-    switch (get_prev_opcode(s->cur_func)) {-    case OP_tail_call:-    case OP_tail_call_method:-    case OP_return:-    case OP_return_undef:-    case OP_return_async:-    case OP_throw:-    case OP_throw_var:-    case OP_goto:-#if SHORT_OPCODES-    case OP_goto8:-    case OP_goto16:-#endif-    case OP_ret:-        return FALSE;-    default:-        return TRUE;-    }-}--static void emit_u8(JSParseState *s, uint8_t val)-{-    dbuf_putc(&s->cur_func->byte_code, val);-}--static void emit_u16(JSParseState *s, uint16_t val)-{-    dbuf_put_u16(&s->cur_func->byte_code, val);-}--static void emit_u32(JSParseState *s, uint32_t val)-{-    dbuf_put_u32(&s->cur_func->byte_code, val);-}--static void emit_op(JSParseState *s, uint8_t val)-{-    JSFunctionDef *fd = s->cur_func;-    DynBuf *bc = &fd->byte_code;--    /* Use the line number of the last token used, not the next token,-       nor the current offset in the source file.-     */-    if (unlikely(fd->last_opcode_line_num != s->last_line_num)) {-        dbuf_putc(bc, OP_line_num);-        dbuf_put_u32(bc, s->last_line_num);-        fd->last_opcode_line_num = s->last_line_num;-    }-    fd->last_opcode_pos = bc->size;-    dbuf_putc(bc, val);-}--static void emit_atom(JSParseState *s, JSAtom name)-{-    emit_u32(s, JS_DupAtom(s->ctx, name));-}--static int update_label(JSFunctionDef *s, int label, int delta)-{-    LabelSlot *ls;--    assert(label >= 0 && label < s->label_count);-    ls = &s->label_slots[label];-    ls->ref_count += delta;-    assert(ls->ref_count >= 0);-    return ls->ref_count;-}--static int new_label_fd(JSFunctionDef *fd, int label)-{-    LabelSlot *ls;--    if (label < 0) {-        if (js_resize_array(fd->ctx, (void *)&fd->label_slots,-                            sizeof(fd->label_slots[0]),-                            &fd->label_size, fd->label_count + 1))-            return -1;-        label = fd->label_count++;-        ls = &fd->label_slots[label];-        ls->ref_count = 0;-        ls->pos = -1;-        ls->pos2 = -1;-        ls->addr = -1;-        ls->first_reloc = NULL;-    }-    return label;-}--static int new_label(JSParseState *s)-{-    return new_label_fd(s->cur_func, -1);-}--/* return the label ID offset */-static int emit_label(JSParseState *s, int label)-{-    if (label >= 0) {-        emit_op(s, OP_label);-        emit_u32(s, label);-        s->cur_func->label_slots[label].pos = s->cur_func->byte_code.size;-        return s->cur_func->byte_code.size - 4;-    } else {-        return -1;-    }-}--/* return label or -1 if dead code */-static int emit_goto(JSParseState *s, int opcode, int label)-{-    if (js_is_live_code(s)) {-        if (label < 0)-            label = new_label(s);-        emit_op(s, opcode);-        emit_u32(s, label);-        s->cur_func->label_slots[label].ref_count++;-        return label;-    }-    return -1;-}--/* return the constant pool index. 'val' is not duplicated. */-static int cpool_add(JSParseState *s, JSValue val)-{-    JSFunctionDef *fd = s->cur_func;-    -    if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]),-                        &fd->cpool_size, fd->cpool_count + 1))-        return -1;-    fd->cpool[fd->cpool_count++] = val;-    return fd->cpool_count - 1;-}--static __exception int emit_push_const(JSParseState *s, JSValueConst val,-                                       BOOL as_atom)-{-    int idx;--    if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING && as_atom) {-        JSAtom atom;-        /* warning: JS_NewAtomStr frees the string value */-        JS_DupValue(s->ctx, val);-        atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));-        if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {-            emit_op(s, OP_push_atom_value);-            emit_u32(s, atom);-            return 0;-        }-    }--    idx = cpool_add(s, JS_DupValue(s->ctx, val));-    if (idx < 0)-        return -1;-    emit_op(s, OP_push_const);-    emit_u32(s, idx);-    return 0;-}--/* return the variable index or -1 if not found,-   add ARGUMENT_VAR_OFFSET for argument variables */-static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    int i;-    for(i = fd->arg_count; i-- > 0;) {-        if (fd->args[i].var_name == name)-            return i | ARGUMENT_VAR_OFFSET;-    }-    return -1;-}--static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    int i;-    for(i = fd->var_count; i-- > 0;) {-        if (fd->vars[i].var_name == name && fd->vars[i].scope_level == 0)-            return i;-    }-    return find_arg(ctx, fd, name);-}--/* return true if scope == parent_scope or if scope is a child of-   parent_scope */-static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd,-                           int scope, int parent_scope)-{-    while (scope >= 0) {-        if (scope == parent_scope)-            return TRUE;-        scope = fd->scopes[scope].parent;-    }-    return FALSE;-}--/* find a 'var' declaration in the same scope or a child scope */-static int find_var_in_child_scope(JSContext *ctx, JSFunctionDef *fd,-                                   JSAtom name, int scope_level)-{-    int i;-    for(i = 0; i < fd->var_count; i++) {-        JSVarDef *vd = &fd->vars[i];-        if (vd->var_name == name && vd->scope_level == 0) {-            if (is_child_scope(ctx, fd, vd->func_pool_or_scope_idx,-                               scope_level))-                return i;-        }-    }-    return -1;-}---static JSHoistedDef *find_hoisted_def(JSFunctionDef *fd, JSAtom name)-{-    int i;-    for(i = 0; i < fd->hoisted_def_count; i++) {-        JSHoistedDef *hf = &fd->hoisted_def[i];-        if (hf->var_name == name)-            return hf;-    }-    return NULL;--}--static JSHoistedDef *find_lexical_hoisted_def(JSFunctionDef *fd, JSAtom name)-{-    JSHoistedDef *hf = find_hoisted_def(fd, name);-    if (hf && hf->is_lexical)-        return hf;-    else-        return NULL;-}--static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name,-                             int scope_idx, BOOL check_catch_var)-{-    while (scope_idx >= 0) {-        JSVarDef *vd = &fd->vars[scope_idx];-        if (vd->var_name == name &&-            (vd->is_lexical || (vd->var_kind == JS_VAR_CATCH &&-                                check_catch_var)))-            return scope_idx;-        scope_idx = vd->scope_next;-    }--    if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_GLOBAL) {-        if (find_lexical_hoisted_def(fd, name))-            return GLOBAL_VAR_OFFSET;-    }-    return -1;-}--static int push_scope(JSParseState *s) {-    if (s->cur_func) {-        JSFunctionDef *fd = s->cur_func;-        int scope = fd->scope_count;-        /* XXX: should check for scope overflow */-        if ((fd->scope_count + 1) > fd->scope_size) {-            int new_size;-            size_t slack;-            JSVarScope *new_buf;-            /* XXX: potential arithmetic overflow */-            new_size = max_int(fd->scope_count + 1, fd->scope_size * 3 / 2);-            if (fd->scopes == fd->def_scope_array) {-                new_buf = js_realloc2(s->ctx, NULL, new_size * sizeof(*fd->scopes), &slack);-                if (!new_buf)-                    return -1;-                memcpy(new_buf, fd->scopes, fd->scope_count * sizeof(*fd->scopes));-            } else {-                new_buf = js_realloc2(s->ctx, fd->scopes, new_size * sizeof(*fd->scopes), &slack);-                if (!new_buf)-                    return -1;-            }-            new_size += slack / sizeof(*new_buf);-            fd->scopes = new_buf;-            fd->scope_size = new_size;-        }-        fd->scope_count++;-        fd->scopes[scope].parent = fd->scope_level;-        fd->scopes[scope].first = fd->scope_first;-        emit_op(s, OP_enter_scope);-        emit_u16(s, scope);-        return fd->scope_level = scope;-    }-    return 0;-}--static int get_first_lexical_var(JSFunctionDef *fd, int scope)-{-    while (scope >= 0) {-        int scope_idx = fd->scopes[scope].first;-        if (scope_idx >= 0)-            return scope_idx;-        scope = fd->scopes[scope].parent;-    }-    return -1;-}--static void pop_scope(JSParseState *s) {-    if (s->cur_func) {-        /* disable scoped variables */-        JSFunctionDef *fd = s->cur_func;-        int scope = fd->scope_level;-        emit_op(s, OP_leave_scope);-        emit_u16(s, scope);-        fd->scope_level = fd->scopes[scope].parent;-        fd->scope_first = get_first_lexical_var(fd, fd->scope_level);-    }-}--static void close_scopes(JSParseState *s, int scope, int scope_stop)-{-    while (scope > scope_stop) {-        emit_op(s, OP_leave_scope);-        emit_u16(s, scope);-        scope = s->cur_func->scopes[scope].parent;-    }-}--/* return the variable index or -1 if error */-static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    JSVarDef *vd;--    /* the local variable indexes are currently stored on 16 bits */-    if (fd->var_count >= JS_MAX_LOCAL_VARS) {-        JS_ThrowInternalError(ctx, "too many local variables");-        return -1;-    }-    if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]),-                        &fd->var_size, fd->var_count + 1))-        return -1;-    vd = &fd->vars[fd->var_count++];-    memset(vd, 0, sizeof(*vd));-    vd->var_name = JS_DupAtom(ctx, name);-    return fd->var_count - 1;-}--static int add_scope_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name,-                         JSVarKindEnum var_kind)-{-    int idx = add_var(ctx, fd, name);-    if (idx >= 0) {-        JSVarDef *vd = &fd->vars[idx];-        vd->var_kind = var_kind;-        vd->scope_level = fd->scope_level;-        vd->scope_next = fd->scope_first;-        fd->scopes[fd->scope_level].first = idx;-        fd->scope_first = idx;-    }-    return idx;-}--static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    int idx = fd->func_var_idx;-    if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {-        fd->func_var_idx = idx;-        fd->vars[idx].is_func_var = TRUE;-        if (fd->js_mode & JS_MODE_STRICT)-            fd->vars[idx].is_const = TRUE;-    }-    return idx;-}--static int add_arguments_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    int idx = fd->arguments_var_idx;-    if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {-        fd->arguments_var_idx = idx;-    }-    return idx;-}--static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)-{-    JSVarDef *vd;--    /* the local variable indexes are currently stored on 16 bits */-    if (fd->arg_count >= JS_MAX_LOCAL_VARS) {-        JS_ThrowInternalError(ctx, "too many arguments");-        return -1;-    }-    if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]),-                        &fd->arg_size, fd->arg_count + 1))-        return -1;-    vd = &fd->args[fd->arg_count++];-    memset(vd, 0, sizeof(*vd));-    vd->var_name = JS_DupAtom(ctx, name);-    return fd->arg_count - 1;-}--/* add a Hoisted definition for a function (cpool_idx >= 0) or a-   global variable (cpool_idx = -1) */-static JSHoistedDef *add_hoisted_def(JSContext *ctx,-                                     JSFunctionDef *s, int cpool_idx,-                                     JSAtom name, int var_idx, BOOL is_lexical)-{-    JSHoistedDef *hf;--    if (js_resize_array(ctx, (void **)&s->hoisted_def,-                        sizeof(s->hoisted_def[0]),-                        &s->hoisted_def_size, s->hoisted_def_count + 1))-        return NULL;-    hf = &s->hoisted_def[s->hoisted_def_count++];-    hf->cpool_idx = cpool_idx;-    hf->force_init = 0;-    hf->is_lexical = is_lexical;-    hf->is_const = FALSE;-    hf->var_idx = var_idx;-    hf->scope_level = s->scope_level;-    hf->var_name = JS_ATOM_NULL;-    if (name != JS_ATOM_NULL) {-        hf->var_name = JS_DupAtom(ctx, name);-    }-    return hf;-}--typedef enum {-    JS_VAR_DEF_WITH,-    JS_VAR_DEF_LET,-    JS_VAR_DEF_CONST,-    JS_VAR_DEF_FUNCTION_DECL, /* function declaration */-    JS_VAR_DEF_NEW_FUNCTION_DECL, /* async/generator function declaration */-    JS_VAR_DEF_CATCH,-    JS_VAR_DEF_VAR,-} JSVarDefEnum;--static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,-                      JSVarDefEnum var_def_type)-{-    JSContext *ctx = s->ctx;-    JSVarDef *vd;-    int idx;--    switch (var_def_type) {-    case JS_VAR_DEF_WITH:-        idx = add_scope_var(ctx, fd, name, JS_VAR_NORMAL);-        break;--    case JS_VAR_DEF_LET:-    case JS_VAR_DEF_CONST:-    case JS_VAR_DEF_FUNCTION_DECL:-    case JS_VAR_DEF_NEW_FUNCTION_DECL:-        idx = find_lexical_decl(ctx, fd, name, fd->scope_first, TRUE);-        if (idx >= 0) {-            if (idx < GLOBAL_VAR_OFFSET) {-                if (fd->vars[idx].scope_level == fd->scope_level) {-                    /* same scope: in non strict mode, functions-                       can be redefined (annex B.3.3.4). */-                    if (!(!(fd->js_mode & JS_MODE_STRICT) &&-                          var_def_type == JS_VAR_DEF_FUNCTION_DECL &&-                          fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) {-                        goto redef_lex_error;-                    }-                } else if (fd->vars[idx].var_kind == JS_VAR_CATCH && (fd->vars[idx].scope_level + 2) == fd->scope_level) {-                    goto redef_lex_error;-                }-            } else {-                if (fd->scope_level == 1) {-                redef_lex_error:-                    /* redefining a scoped var in the same scope: error */-                    return js_parse_error(s, "invalid redefinition of lexical identifier");-                }-            }-        }-        if (var_def_type != JS_VAR_DEF_FUNCTION_DECL &&-            var_def_type != JS_VAR_DEF_NEW_FUNCTION_DECL &&-            fd->scope_level == 1 &&-            find_arg(ctx, fd, name) >= 0) {-            /* lexical variable redefines a parameter name */-            return js_parse_error(s, "invalid redefinition of parameter name");-        }--        if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) {-            return js_parse_error(s, "invalid redefinition of a variable");-        }-        -        if (fd->is_global_var) {-            JSHoistedDef *hf;-            hf = find_hoisted_def(fd, name);-            if (hf && is_child_scope(ctx, fd, hf->scope_level,-                                     fd->scope_level)) {-                return js_parse_error(s, "invalid redefinition of global identifier");-            }-        }-        -        if (fd->is_eval &&-            (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||-             fd->eval_type == JS_EVAL_TYPE_MODULE) &&-            fd->scope_level == 1) {-            JSHoistedDef *hf;-            hf = add_hoisted_def(s->ctx, fd, -1, name, -1, TRUE);-            if (!hf)-                return -1;-            hf->is_const = (var_def_type == JS_VAR_DEF_CONST);-            idx = GLOBAL_VAR_OFFSET;-        } else {-            JSVarKindEnum var_kind;-            if (var_def_type == JS_VAR_DEF_FUNCTION_DECL)-                var_kind = JS_VAR_FUNCTION_DECL;-            else if (var_def_type == JS_VAR_DEF_NEW_FUNCTION_DECL)-                var_kind = JS_VAR_NEW_FUNCTION_DECL;-            else-                var_kind = JS_VAR_NORMAL;-            idx = add_scope_var(ctx, fd, name, var_kind);-            if (idx >= 0) {-                vd = &fd->vars[idx];-                vd->is_lexical = 1;-                vd->is_const = (var_def_type == JS_VAR_DEF_CONST);-            }-        }-        break;--    case JS_VAR_DEF_CATCH:-        idx = add_scope_var(ctx, fd, name, JS_VAR_CATCH);-        break;--    case JS_VAR_DEF_VAR:-        if (find_lexical_decl(ctx, fd, name, fd->scope_first,-                              FALSE) >= 0) {-       invalid_lexical_redefinition:-            /* error to redefine a var that inside a lexical scope */-            return js_parse_error(s, "invalid redefinition of lexical identifier");-        }-        if (fd->is_global_var) {-            JSHoistedDef *hf;-            hf = find_hoisted_def(fd, name);-            if (hf && hf->is_lexical && hf->scope_level == fd->scope_level &&-                fd->eval_type == JS_EVAL_TYPE_MODULE) {-                goto invalid_lexical_redefinition;-            }-            hf = add_hoisted_def(s->ctx, fd, -1, name, -1, FALSE);-            if (!hf)-                return -1;-            idx = GLOBAL_VAR_OFFSET;-        } else {-            /* if the variable already exists, don't add it again  */-            idx = find_var(ctx, fd, name);-            if (idx >= 0)-                break;-            idx = add_var(ctx, fd, name);-            if (idx >= 0) {-                if (name == JS_ATOM_arguments && fd->has_arguments_binding)-                    fd->arguments_var_idx = idx;-                fd->vars[idx].func_pool_or_scope_idx = fd->scope_level;-            }-        }-        break;-    default:-        abort();-    }-    return idx;-}--/* add a private field variable in the current scope */-static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,-                                   JSAtom name, JSVarKindEnum var_kind)-{-    JSContext *ctx = s->ctx;-    JSVarDef *vd;-    int idx;--    idx = add_scope_var(ctx, fd, name, var_kind);-    if (idx < 0)-        return idx;-    vd = &fd->vars[idx];-    vd->is_lexical = 1;-    vd->is_const = 1;-    return idx;-}--static __exception int js_parse_expr(JSParseState *s);-static __exception int js_parse_function_decl(JSParseState *s,-                                              JSParseFunctionEnum func_type,-                                              JSFunctionKindEnum func_kind,-                                              JSAtom func_name, const uint8_t *ptr,-                                              int start_line);-static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);-static __exception int js_parse_function_decl2(JSParseState *s,-                                               JSParseFunctionEnum func_type,-                                               JSFunctionKindEnum func_kind,-                                               JSAtom func_name,-                                               const uint8_t *ptr,-                                               int function_line_num,-                                               JSParseExportEnum export_flag,-                                               JSFunctionDef **pfd);-static __exception int js_parse_assign_expr(JSParseState *s, int in_accepted);-static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag);-static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,-                             JSAtom label_name,-                             int label_break, int label_cont,-                             int drop_count);-static void pop_break_entry(JSFunctionDef *fd);-static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m,-                                       JSAtom local_name, JSAtom export_name,-                                       JSExportTypeEnum export_type);--/* Note: all the fields are already sealed except length */-static int seal_template_obj(JSContext *ctx, JSValueConst obj)-{-    JSObject *p;-    JSShapeProperty *prs;--    p = JS_VALUE_GET_OBJ(obj);-    prs = find_own_property1(p, JS_ATOM_length);-    if (prs) {-        if (js_update_property_flags(ctx, p, &prs,-                                     prs->flags & ~(JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)))-            return -1;-    }-    p->extensible = FALSE;-    return 0;-}--static __exception int js_parse_template(JSParseState *s, int call, int *argc)-{-    JSContext *ctx = s->ctx;-    JSValue raw_array, template_object;-    JSToken cooked;-    int depth, ret;--    raw_array = JS_UNDEFINED; /* avoid warning */-    template_object = JS_UNDEFINED; /* avoid warning */-    if (call) {-        /* Create a template object: an array of cooked strings */-        /* Create an array of raw strings and store it to the raw property */-        template_object = JS_NewArray(ctx);-        if (JS_IsException(template_object))-            return -1;-        //        pool_idx = s->cur_func->cpool_count;-        ret = emit_push_const(s, template_object, 0);-        JS_FreeValue(ctx, template_object);-        if (ret)-            return -1;-        raw_array = JS_NewArray(ctx);-        if (JS_IsException(raw_array))-            return -1;-        if (JS_DefinePropertyValue(ctx, template_object, JS_ATOM_raw,-                                   raw_array, JS_PROP_THROW) < 0) {-            return -1;-        }-    }--    depth = 0;-    while (s->token.val == TOK_TEMPLATE) {-        const uint8_t *p = s->token.ptr + 1;-        cooked = s->token;-        if (call) {-            if (JS_DefinePropertyValueUint32(ctx, raw_array, depth,-                                             JS_DupValue(ctx, s->token.u.str.str),-                                             JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) {-                return -1;-            }-            /* re-parse the string with escape sequences but do not throw a-               syntax error if it contains invalid sequences-             */-            if (js_parse_string(s, '`', FALSE, p, &cooked, &p)) {-                cooked.u.str.str = JS_UNDEFINED;-            }-            if (JS_DefinePropertyValueUint32(ctx, template_object, depth,-                                             cooked.u.str.str,-                                             JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) {-                return -1;-            }-        } else {-            JSString *str;-            /* re-parse the string with escape sequences and throw a-               syntax error if it contains invalid sequences-             */-            JS_FreeValue(ctx, s->token.u.str.str);-            s->token.u.str.str = JS_UNDEFINED;-            if (js_parse_string(s, '`', TRUE, p, &cooked, &p))-                return -1;-            str = JS_VALUE_GET_STRING(cooked.u.str.str);-            if (str->len != 0 || depth == 0) {-                ret = emit_push_const(s, cooked.u.str.str, 1);-                JS_FreeValue(s->ctx, cooked.u.str.str);-                if (ret)-                    return -1;-                if (depth == 0) {-                    if (s->token.u.str.sep == '`')-                        goto done1;-                    emit_op(s, OP_get_field2);-                    emit_atom(s, JS_ATOM_concat);-                }-                depth++;-            } else {-                JS_FreeValue(s->ctx, cooked.u.str.str);-            }-        }-        if (s->token.u.str.sep == '`')-            goto done;-        if (next_token(s))-            return -1;-        if (js_parse_expr(s))-            return -1;-        depth++;-        if (s->token.val != '}') {-            return js_parse_error(s, "expected '}' after template expression");-        }-        /* XXX: should convert to string at this stage? */-        free_token(s, &s->token);-        /* Resume TOK_TEMPLATE parsing (s->token.line_num and-         * s->token.ptr are OK) */-        s->got_lf = FALSE;-        s->last_line_num = s->token.line_num;-        if (js_parse_template_part(s, s->buf_ptr))-            return -1;-    }-    return js_parse_expect(s, TOK_TEMPLATE);-- done:-    if (call) {-        /* Seal the objects */-        seal_template_obj(ctx, raw_array);-        seal_template_obj(ctx, template_object);-        *argc = depth + 1;-    } else {-        emit_op(s, OP_call_method);-        emit_u16(s, depth - 1);-    }- done1:-    return next_token(s);-}---#define PROP_TYPE_IDENT 0-#define PROP_TYPE_VAR   1-#define PROP_TYPE_GET   2-#define PROP_TYPE_SET   3-#define PROP_TYPE_STAR  4-#define PROP_TYPE_ASYNC 5-#define PROP_TYPE_ASYNC_STAR 6--#define PROP_TYPE_PRIVATE (1 << 4)--static BOOL token_is_ident(int tok)-{-    /* Accept keywords and reserved words as property names */-    return (tok == TOK_IDENT ||-            (tok >= TOK_FIRST_KEYWORD &&-             tok <= TOK_LAST_KEYWORD));-}--/* if the property is an expression, name = JS_ATOM_NULL */-static int __exception js_parse_property_name(JSParseState *s,-                                              JSAtom *pname,-                                              BOOL allow_method, BOOL allow_var,-                                              BOOL allow_private)-{-    int is_private = 0;-    BOOL is_non_reserved_ident;-    JSAtom name;-    int prop_type;-    -    prop_type = PROP_TYPE_IDENT;-    if (allow_method) {-        if (token_is_pseudo_keyword(s, JS_ATOM_get)-        ||  token_is_pseudo_keyword(s, JS_ATOM_set)) {-            /* get x(), set x() */-            name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-            if (next_token(s))-                goto fail1;-            if (s->token.val == ':' || s->token.val == ',' ||-                s->token.val == '}' || s->token.val == '(') {-                is_non_reserved_ident = TRUE;-                goto ident_found;-            }-            prop_type = PROP_TYPE_GET + (name == JS_ATOM_set);-            JS_FreeAtom(s->ctx, name);-        } else if (s->token.val == '*') {-            if (next_token(s))-                goto fail;-            prop_type = PROP_TYPE_STAR;-        } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&-                   peek_token(s, TRUE) != '\n') {-            name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-            if (next_token(s))-                goto fail1;-            if (s->token.val == ':' || s->token.val == ',' ||-                s->token.val == '}' || s->token.val == '(') {-                is_non_reserved_ident = TRUE;-                goto ident_found;-            }-            JS_FreeAtom(s->ctx, name);-            if (s->token.val == '*') {-                if (next_token(s))-                    goto fail;-                prop_type = PROP_TYPE_ASYNC_STAR;-            } else {-                prop_type = PROP_TYPE_ASYNC;-            }-        }-    }--    if (token_is_ident(s->token.val)) {-        /* variable can only be a non-reserved identifier */-        is_non_reserved_ident =-            (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved);-        /* keywords and reserved words have a valid atom */-        name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-        if (next_token(s))-            goto fail1;-    ident_found:-        if (is_non_reserved_ident &&-            prop_type == PROP_TYPE_IDENT && allow_var) {-            if (!(s->token.val == ':' ||-                  (s->token.val == '(' && allow_method))) {-                prop_type = PROP_TYPE_VAR;-            }-        }-    } else if (s->token.val == TOK_STRING) {-        name = JS_ValueToAtom(s->ctx, s->token.u.str.str);-        if (name == JS_ATOM_NULL)-            goto fail;-        if (next_token(s))-            goto fail1;-    } else if (s->token.val == TOK_NUMBER) {-        JSValue val;-        val = s->token.u.num.val;-#ifdef CONFIG_BIGNUM-        if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            val = s->ctx->rt->bigfloat_ops.-                mul_pow10_to_float64(s->ctx, &p->num,-                                     s->token.u.num.exponent);-            if (JS_IsException(val))-                goto fail;-            name = JS_ValueToAtom(s->ctx, val);-            JS_FreeValue(s->ctx, val);-        } else-#endif-        {-            name = JS_ValueToAtom(s->ctx, val);-        }-        if (name == JS_ATOM_NULL)-            goto fail;-        if (next_token(s))-            goto fail1;-    } else if (s->token.val == '[') {-        if (next_token(s))-            goto fail;-        if (js_parse_expr(s))-            goto fail;-        if (js_parse_expect(s, ']'))-            goto fail;-        name = JS_ATOM_NULL;-    } else if (s->token.val == TOK_PRIVATE_NAME && allow_private) {-        name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-        if (next_token(s))-            goto fail1;-        is_private = PROP_TYPE_PRIVATE;-    } else {-        goto invalid_prop;-    }-    if (prop_type != PROP_TYPE_IDENT && prop_type != PROP_TYPE_VAR &&-        s->token.val != '(') {-        JS_FreeAtom(s->ctx, name);-    invalid_prop:-        js_parse_error(s, "invalid property name");-        goto fail;-    }-    *pname = name;-    return prop_type | is_private;- fail1:-    JS_FreeAtom(s->ctx, name);- fail:-    *pname = JS_ATOM_NULL;-    return -1;-}--typedef struct JSParsePos {-    int last_line_num;-    int line_num;-    BOOL got_lf;-    const uint8_t *ptr;-} JSParsePos;--static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)-{-    sp->last_line_num = s->last_line_num;-    sp->line_num = s->token.line_num;-    sp->ptr = s->token.ptr;-    sp->got_lf = s->got_lf;-    return 0;-}--static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)-{-    s->token.line_num = sp->last_line_num;-    s->line_num = sp->line_num;-    s->buf_ptr = sp->ptr;-    s->got_lf = sp->got_lf;-    return next_token(s);-}--/* return TRUE if a regexp literal is allowed after this token */-static BOOL is_regexp_allowed(int tok)-{-    switch (tok) {-    case TOK_NUMBER:-    case TOK_STRING:-    case TOK_REGEXP:-    case TOK_DEC:-    case TOK_INC:-    case TOK_NULL:-    case TOK_FALSE:-    case TOK_TRUE:-    case TOK_THIS:-    case ')':-    case ']':-    case '}': /* XXX: regexp may occur after */-    case TOK_IDENT:-        return FALSE;-    default:-        return TRUE;-    }-}--#define SKIP_HAS_SEMI      (1 << 0)-#define SKIP_HAS_ELLIPSIS  (1 << 1)--/* XXX: improve speed with early bailout */-/* XXX: no longer works if regexps are present. Could use previous-   regexp parsing heuristics to handle most cases */-static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_terminator)-{-    char state[256];-    size_t level = 0;-    JSParsePos pos;-    int last_tok, tok = TOK_EOF;-    int c, tok_len, bits = 0;--    /* protect from underflow */-    state[level++] = 0;--    js_parse_get_pos(s, &pos);-    last_tok = 0;-    for (;;) {-        switch(s->token.val) {-        case '(':-        case '[':-        case '{':-            if (level >= sizeof(state))-                goto done;-            state[level++] = s->token.val;-            break;-        case ')':-            if (state[--level] != '(')-                goto done;-            break;-        case ']':-            if (state[--level] != '[')-                goto done;-            break;-        case '}':-            c = state[--level];-            if (c == '`') {-                /* continue the parsing of the template */-                free_token(s, &s->token);-                /* Resume TOK_TEMPLATE parsing (s->token.line_num and-                 * s->token.ptr are OK) */-                s->got_lf = FALSE;-                s->last_line_num = s->token.line_num;-                if (js_parse_template_part(s, s->buf_ptr))-                    goto done;-                goto handle_template;-            } else if (c != '{') {-                goto done;-            }-            break;-        case TOK_TEMPLATE:-        handle_template:-            if (s->token.u.str.sep != '`') {-                /* '${' inside the template : closing '}' and continue-                   parsing the template */-                if (level >= sizeof(state))-                    goto done;-                state[level++] = '`';-            } -            break;-        case TOK_EOF:-            goto done;-        case ';':-            if (level == 2) {-                bits |= SKIP_HAS_SEMI;-            }-            break;-        case TOK_ELLIPSIS:-            if (level == 2) {-                bits |= SKIP_HAS_ELLIPSIS;-            }-            break;--        case TOK_DIV_ASSIGN:-            tok_len = 2;-            goto parse_regexp;-        case '/':-            tok_len = 1;-        parse_regexp:-            if (is_regexp_allowed(last_tok)) {-                s->buf_ptr -= tok_len;-                if (js_parse_regexp(s)) {-                    /* XXX: should clear the exception */-                    goto done;-                }-            }-            break;-        }-        /* last_tok is only used to recognize regexps */-        if (s->token.val == TOK_IDENT &&-            (token_is_pseudo_keyword(s, JS_ATOM_of) ||-             token_is_pseudo_keyword(s, JS_ATOM_yield))) {-            last_tok = TOK_OF;-        } else {-            last_tok = s->token.val;-        }-        if (next_token(s)) {-            /* XXX: should clear the exception generated by next_token() */-            break;-        }-        if (level <= 1) {-            tok = s->token.val;-            if (token_is_pseudo_keyword(s, JS_ATOM_of))-                tok = TOK_OF;-            if (no_line_terminator && s->last_line_num != s->token.line_num)-                tok = '\n';-            break;-        }-    }- done:-    if (pbits) {-        *pbits = bits;-    }-    if (js_parse_seek_token(s, &pos))-        return -1;-    return tok;-}--static void set_object_name(JSParseState *s, JSAtom name)-{-    JSFunctionDef *fd = s->cur_func;-    int opcode;--    opcode = get_prev_opcode(fd);-    if (opcode == OP_set_name) {-        /* XXX: should free atom after OP_set_name? */-        fd->byte_code.size = fd->last_opcode_pos;-        fd->last_opcode_pos = -1;-        emit_op(s, OP_set_name);-        emit_atom(s, name);-    } else if (opcode == OP_set_class_name) {-        int define_class_pos;-        JSAtom atom;-        define_class_pos = fd->last_opcode_pos + 1 --            get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        assert(fd->byte_code.buf[define_class_pos] == OP_define_class);-        /* for consistency we free the previous atom which is-           JS_ATOM_empty_string */-        atom = get_u32(fd->byte_code.buf + define_class_pos + 1);-        JS_FreeAtom(s->ctx, atom);-        put_u32(fd->byte_code.buf + define_class_pos + 1,-                JS_DupAtom(s->ctx, name));-        fd->last_opcode_pos = -1;-    }-}--static void set_object_name_computed(JSParseState *s)-{-    JSFunctionDef *fd = s->cur_func;-    int opcode;--    opcode = get_prev_opcode(fd);-    if (opcode == OP_set_name) {-        /* XXX: should free atom after OP_set_name? */-        fd->byte_code.size = fd->last_opcode_pos;-        fd->last_opcode_pos = -1;-        emit_op(s, OP_set_name_computed);-    } else if (opcode == OP_set_class_name) {-        int define_class_pos;-        define_class_pos = fd->last_opcode_pos + 1 --            get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        assert(fd->byte_code.buf[define_class_pos] == OP_define_class);-        fd->byte_code.buf[define_class_pos] = OP_define_class_computed;-        fd->last_opcode_pos = -1;-    }-}--static __exception int js_parse_object_literal(JSParseState *s)-{-    JSAtom name = JS_ATOM_NULL;-    const uint8_t *start_ptr;-    int start_line, prop_type;-    BOOL has_proto;--    if (next_token(s))-        goto fail;-    /* XXX: add an initial length that will be patched back */-    emit_op(s, OP_object);-    has_proto = FALSE;-    while (s->token.val != '}') {-        /* specific case for getter/setter */-        start_ptr = s->token.ptr;-        start_line = s->token.line_num;--        if (s->token.val == TOK_ELLIPSIS) {-            if (next_token(s))-                return -1;-            if (js_parse_assign_expr(s, TRUE))-                return -1;-            emit_op(s, OP_null);  /* dummy excludeList */-            emit_op(s, OP_copy_data_properties);-            emit_u8(s, 2 | (1 << 2) | (0 << 5));-            emit_op(s, OP_drop); /* pop excludeList */-            emit_op(s, OP_drop); /* pop src object */-            goto next;-        }--        prop_type = js_parse_property_name(s, &name, TRUE, TRUE, FALSE);-        if (prop_type < 0)-            goto fail;--        if (prop_type == PROP_TYPE_VAR) {-            /* shortcut for x: x */-            emit_op(s, OP_scope_get_var);-            emit_atom(s, name);-            emit_u16(s, s->cur_func->scope_level);-            emit_op(s, OP_define_field);-            emit_atom(s, name);-        } else if (s->token.val == '(') {-            BOOL is_getset = (prop_type == PROP_TYPE_GET ||-                              prop_type == PROP_TYPE_SET);-            JSParseFunctionEnum func_type;-            JSFunctionKindEnum func_kind;-            int op_flags;--            func_kind = JS_FUNC_NORMAL;-            if (is_getset) {-                func_type = JS_PARSE_FUNC_GETTER + prop_type - PROP_TYPE_GET;-            } else {-                func_type = JS_PARSE_FUNC_METHOD;-                if (prop_type == PROP_TYPE_STAR)-                    func_kind = JS_FUNC_GENERATOR;-                else if (prop_type == PROP_TYPE_ASYNC)-                    func_kind = JS_FUNC_ASYNC;-                else if (prop_type == PROP_TYPE_ASYNC_STAR)-                    func_kind = JS_FUNC_ASYNC_GENERATOR;-            }-            if (js_parse_function_decl(s, func_type, func_kind, JS_ATOM_NULL,-                                       start_ptr, start_line))-                goto fail;-            if (name == JS_ATOM_NULL) {-                emit_op(s, OP_define_method_computed);-            } else {-                emit_op(s, OP_define_method);-                emit_atom(s, name);-            }-            if (is_getset) {-                op_flags = OP_DEFINE_METHOD_GETTER +-                    prop_type - PROP_TYPE_GET;-            } else {-                op_flags = OP_DEFINE_METHOD_METHOD;-            }-            emit_u8(s, op_flags | OP_DEFINE_METHOD_ENUMERABLE);-        } else {-            if (js_parse_expect(s, ':'))-                goto fail;-            if (js_parse_assign_expr(s, TRUE))-                goto fail;-            if (name == JS_ATOM_NULL) {-                set_object_name_computed(s);-                emit_op(s, OP_define_array_el);-                emit_op(s, OP_drop);-            } else if (name == JS_ATOM___proto__) {-                if (has_proto) {-                    js_parse_error(s, "duplicate __proto__ property name");-                    goto fail;-                }-                emit_op(s, OP_set_proto);-                has_proto = TRUE;-            } else {-                set_object_name(s, name);-                emit_op(s, OP_define_field);-                emit_atom(s, name);-            }-        }-        JS_FreeAtom(s->ctx, name);-    next:-        name = JS_ATOM_NULL;-        if (s->token.val != ',')-            break;-        if (next_token(s))-            goto fail;-    }-    if (js_parse_expect(s, '}'))-        goto fail;-    return 0;- fail:-    JS_FreeAtom(s->ctx, name);-    return -1;-}--static __exception int js_parse_postfix_expr(JSParseState *s,-                                             BOOL accept_lparen);--/* XXX: is there is nicer solution ? */-static __exception int js_parse_class_default_ctor(JSParseState *s,-                                                   BOOL has_super,-                                                   JSFunctionDef **pfd)-{-    JSParsePos pos;-    const char *str;-    int ret, line_num;-    JSParseFunctionEnum func_type;-    const uint8_t *saved_buf_end;-    -    js_parse_get_pos(s, &pos);-    if (has_super) {-        str = "(...a){super(...a);}";-        func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;-    } else {-        str = "(){}";-        func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;-    }-    line_num = s->token.line_num;-    saved_buf_end = s->buf_end;-    s->buf_ptr = (uint8_t *)str;-    s->buf_end = (uint8_t *)(str + strlen(str));-    ret = next_token(s);-    if (!ret) {-        ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL,-                                      JS_ATOM_NULL, (uint8_t *)str,-                                      line_num, JS_PARSE_EXPORT_NONE, pfd);-    }-    s->buf_end = saved_buf_end;-    ret |= js_parse_seek_token(s, &pos);-    return ret;-}--/* find field in the current scope */-static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd,-                                    JSAtom name, int scope_level)-{-    int idx;-    idx = fd->scopes[scope_level].first;-    while (idx != -1) {-        if (fd->vars[idx].scope_level != scope_level)-            break;-        if (fd->vars[idx].var_name == name)-            return idx;-        idx = fd->vars[idx].scope_next;-    }-    return -1;-}--/* initialize the class fields, called by the constructor. Note:-   super() can be called in an arrow function, so <this> and-   <class_fields_init> can be variable references */-static void emit_class_field_init(JSParseState *s)-{-    int label_next;-    -    emit_op(s, OP_scope_get_var);-    emit_atom(s, JS_ATOM_class_fields_init);-    emit_u16(s, s->cur_func->scope_level);--    /* no need to call the class field initializer if not defined */-    emit_op(s, OP_dup);-    label_next = emit_goto(s, OP_if_false, -1);-    -    emit_op(s, OP_scope_get_var);-    emit_atom(s, JS_ATOM_this);-    emit_u16(s, 0);-    -    emit_op(s, OP_swap);-    -    emit_op(s, OP_call_method);-    emit_u16(s, 0);--    emit_label(s, label_next);-    emit_op(s, OP_drop);-}--/* build a private setter function name from the private getter name */-static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)-{-    return js_atom_concat_str(ctx, name, "<set>");-}--typedef struct {-    JSFunctionDef *fields_init_fd;-    int computed_fields_count;-    BOOL has_brand;-    int brand_push_pos;-} ClassFieldsDef;--static __exception int emit_class_init_start(JSParseState *s,-                                             ClassFieldsDef *cf)-{-    int label_add_brand;-    -    cf->fields_init_fd = js_parse_function_class_fields_init(s);-    if (!cf->fields_init_fd)-        return -1;--    s->cur_func = cf->fields_init_fd;-    -    /* XXX: would be better to add the code only if needed, maybe in a-       later pass */-    emit_op(s, OP_push_false); /* will be patched later */-    cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos;-    label_add_brand = emit_goto(s, OP_if_false, -1);-    -    emit_op(s, OP_scope_get_var);-    emit_atom(s, JS_ATOM_this);-    emit_u16(s, 0);-    -    emit_op(s, OP_scope_get_var);-    emit_atom(s, JS_ATOM_home_object);-    emit_u16(s, 0);-    -    emit_op(s, OP_add_brand);-    -    emit_label(s, label_add_brand);--    s->cur_func = s->cur_func->parent;-    return 0;-}--static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf)-{-    if (!cf->has_brand) {-        /* define the brand field in 'this' of the initializer */-        if (!cf->fields_init_fd) {-            if (emit_class_init_start(s, cf))-                return -1;-        }-        /* patch the start of the function to enable the OP_add_brand code */-        cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;-        -        cf->has_brand = TRUE;-    }-    return 0;-}--static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)-{-    int cpool_idx;-        -    s->cur_func = cf->fields_init_fd;-    emit_op(s, OP_return_undef);-    s->cur_func = s->cur_func->parent;-    -    cpool_idx = cpool_add(s, JS_NULL);-    cf->fields_init_fd->parent_cpool_idx = cpool_idx;-    emit_op(s, OP_fclosure);-    emit_u32(s, cpool_idx);-    emit_op(s, OP_set_home_object);-}---static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,-                                      JSParseExportEnum export_flag)-{-    JSContext *ctx = s->ctx;-    JSFunctionDef *fd = s->cur_func;-    JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1;-    JSAtom class_var_name = JS_ATOM_NULL;-    JSFunctionDef *method_fd, *ctor_fd;-    int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset;-    int class_flags = 0, i, define_class_offset;-    BOOL is_static, is_private;-    const uint8_t *class_start_ptr = s->token.ptr;-    const uint8_t *start_ptr;-    ClassFieldsDef class_fields[2];-        -    /* classes are parsed and executed in strict mode */-    saved_js_mode = fd->js_mode;-    fd->js_mode |= JS_MODE_STRICT;-    if (next_token(s))-        goto fail;-    if (s->token.val == TOK_IDENT) {-        if (s->token.u.ident.is_reserved) {-            js_parse_error_reserved_identifier(s);-            goto fail;-        }-        class_name = JS_DupAtom(ctx, s->token.u.ident.atom);-        if (next_token(s))-            goto fail;-    } else if (!is_class_expr && export_flag != JS_PARSE_EXPORT_DEFAULT) {-        js_parse_error(s, "class statement requires a name");-        goto fail;-    }-    if (!is_class_expr) {-        if (class_name == JS_ATOM_NULL)-            class_var_name = JS_ATOM__default_; /* export default */-        else-            class_var_name = class_name;-        class_var_name = JS_DupAtom(ctx, class_var_name);-    }--    push_scope(s);--    if (s->token.val == TOK_EXTENDS) {-        class_flags = JS_DEFINE_CLASS_HAS_HERITAGE;-        if (next_token(s))-            goto fail;-        /* XXX: the grammar only allows LeftHandSideExpression */-        if (js_parse_postfix_expr(s, TRUE))-            goto fail;-    } else {-        emit_op(s, OP_undefined);-    }--    /* add a 'const' definition for the class name */-    if (class_name != JS_ATOM_NULL) {-        class_name_var_idx = define_var(s, fd, class_name, JS_VAR_DEF_CONST);-        if (class_name_var_idx < 0)-            goto fail;-    }--    if (js_parse_expect(s, '{'))-        goto fail;--    /* this scope contains the private fields */-    push_scope(s);--    emit_op(s, OP_push_const);-    ctor_cpool_offset = fd->byte_code.size;-    emit_u32(s, 0); /* will be patched at the end of the class parsing */--    if (class_name == JS_ATOM_NULL) {-        if (class_var_name != JS_ATOM_NULL)-            class_name1 = JS_ATOM_default;-        else-            class_name1 = JS_ATOM_empty_string;-    } else {-        class_name1 = class_name;-    }-    -    emit_op(s, OP_define_class);-    emit_atom(s, class_name1);-    emit_u8(s, class_flags);-    define_class_offset = fd->last_opcode_pos;--    for(i = 0; i < 2; i++) {-        ClassFieldsDef *cf = &class_fields[i];-        cf->fields_init_fd = NULL;-        cf->computed_fields_count = 0;-        cf->has_brand = FALSE;-    }-    -    ctor_fd = NULL;-    while (s->token.val != '}') {-        if (s->token.val == ';') {-            if (next_token(s))-                goto fail;-            continue;-        }-        is_static = (s->token.val == TOK_STATIC);-        prop_type = -1;-        if (is_static) {-            if (next_token(s))-                goto fail;-            /* allow "static" field name */-            if (s->token.val == ';' || s->token.val == '=') {-                is_static = FALSE;-                name = JS_DupAtom(ctx, JS_ATOM_static);-                prop_type = PROP_TYPE_IDENT;-            }-        }-        if (is_static)-            emit_op(s, OP_swap);-        start_ptr = s->token.ptr;-        if (prop_type < 0) {-            prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE);-            if (prop_type < 0)-                goto fail;-        }-        is_private = prop_type & PROP_TYPE_PRIVATE;-        prop_type &= ~PROP_TYPE_PRIVATE;-        -        if ((name == JS_ATOM_constructor && !is_static &&-             prop_type != PROP_TYPE_IDENT) ||-            (name == JS_ATOM_prototype && is_static) ||-            name == JS_ATOM_hash_constructor) {-            js_parse_error(s, "invalid method name");-            goto fail;-        }-        if (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET) {-            BOOL is_set = prop_type - PROP_TYPE_GET;-            JSFunctionDef *method_fd;--            if (is_private) {-                int idx, var_kind;-                idx = find_private_class_field(ctx, fd, name, fd->scope_level);-                if (idx >= 0) {-                    var_kind = fd->vars[idx].var_kind;-                    if (var_kind == JS_VAR_PRIVATE_FIELD ||-                        var_kind == JS_VAR_PRIVATE_METHOD ||-                        var_kind == JS_VAR_PRIVATE_GETTER_SETTER ||-                        var_kind == (JS_VAR_PRIVATE_GETTER + is_set)) {-                        goto private_field_already_defined;-                    }-                    fd->vars[idx].var_kind = JS_VAR_PRIVATE_GETTER_SETTER;-                } else {-                    if (add_private_class_field(s, fd, name,-                                                JS_VAR_PRIVATE_GETTER + is_set) < 0)-                        goto fail;-                }-                if (add_brand(s, &class_fields[is_static]) < 0)-                    goto fail;-            }--            if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,-                                        JS_FUNC_NORMAL, JS_ATOM_NULL,-                                        start_ptr, s->token.line_num,-                                        JS_PARSE_EXPORT_NONE, &method_fd))-                goto fail;-            if (is_private) {-                method_fd->need_home_object = TRUE; /* needed for brand check */-                emit_op(s, OP_set_home_object);-                /* XXX: missing function name */-                emit_op(s, OP_scope_put_var_init);-                if (is_set) {-                    JSAtom setter_name;-                    int ret;-                    -                    setter_name = get_private_setter_name(ctx, name);-                    if (setter_name == JS_ATOM_NULL)-                        goto fail;-                    emit_atom(s, setter_name);-                    ret = add_private_class_field(s, fd, setter_name,-                                                  JS_VAR_PRIVATE_SETTER);-                    JS_FreeAtom(ctx, setter_name);-                    if (ret < 0)-                        goto fail;-                } else {-                    emit_atom(s, name);-                }-                emit_u16(s, s->cur_func->scope_level);-            } else {-                if (name == JS_ATOM_NULL) {-                    emit_op(s, OP_define_method_computed);-                } else {-                    emit_op(s, OP_define_method);-                    emit_atom(s, name);-                }-                emit_u8(s, OP_DEFINE_METHOD_GETTER + is_set);-            }-        } else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') {-            ClassFieldsDef *cf = &class_fields[is_static];-            JSAtom field_var_name = JS_ATOM_NULL;-            -            /* class field */--            /* XXX: spec: not consistent with method name checks */-            if (name == JS_ATOM_constructor || name == JS_ATOM_prototype) {-                js_parse_error(s, "invalid field name");-                goto fail;-            }-            -            if (is_private) {-                if (find_private_class_field(ctx, fd, name,-                                             fd->scope_level) >= 0) {-                    goto private_field_already_defined;-                }-                if (add_private_class_field(s, fd, name,-                                            JS_VAR_PRIVATE_FIELD) < 0)-                    goto fail;-                emit_op(s, OP_private_symbol);-                emit_atom(s, name);-                emit_op(s, OP_scope_put_var_init);-                emit_atom(s, name);-                emit_u16(s, s->cur_func->scope_level);-            }--            if (!cf->fields_init_fd) {-                if (emit_class_init_start(s, cf))-                    goto fail;-            }-            if (name == JS_ATOM_NULL ) {-                /* save the computed field name into a variable */-                field_var_name = js_atom_concat_num(ctx, JS_ATOM_computed_field + is_static, cf->computed_fields_count);-                if (field_var_name == JS_ATOM_NULL)-                    goto fail;-                if (define_var(s, fd, field_var_name, JS_VAR_DEF_CONST) < 0) {-                    JS_FreeAtom(ctx, field_var_name);-                    goto fail;-                }-                emit_op(s, OP_to_propkey);-                emit_op(s, OP_scope_put_var_init);-                emit_atom(s, field_var_name);-                emit_u16(s, s->cur_func->scope_level);-            }-            s->cur_func = cf->fields_init_fd;-            emit_op(s, OP_scope_get_var);-            emit_atom(s, JS_ATOM_this);-            emit_u16(s, 0);--            if (name == JS_ATOM_NULL) {-                emit_op(s, OP_scope_get_var);-                emit_atom(s, field_var_name);-                emit_u16(s, s->cur_func->scope_level);-                cf->computed_fields_count++;-                JS_FreeAtom(ctx, field_var_name);-            } else if (is_private) {-                emit_op(s, OP_scope_get_var);-                emit_atom(s, name);-                emit_u16(s, s->cur_func->scope_level);-            }-            -            if (s->token.val == '=') {-                if (next_token(s))-                    goto fail;-                if (js_parse_assign_expr(s, TRUE))-                    goto fail;-            } else {-                emit_op(s, OP_undefined);-            }-            if (is_private) {-                set_object_name_computed(s);-                emit_op(s, OP_define_private_field);-            } else if (name == JS_ATOM_NULL) {-                set_object_name_computed(s);-                emit_op(s, OP_define_array_el);-                emit_op(s, OP_drop);-            } else {-                set_object_name(s, name);-                emit_op(s, OP_define_field);-                emit_atom(s, name);-            }-            s->cur_func = s->cur_func->parent;-            if (js_parse_expect_semi(s))-                goto fail;-        } else {-            JSParseFunctionEnum func_type;-            JSFunctionKindEnum func_kind;-            -            func_type = JS_PARSE_FUNC_METHOD;-            func_kind = JS_FUNC_NORMAL;-            if (prop_type == PROP_TYPE_STAR) {-                func_kind = JS_FUNC_GENERATOR;-            } else if (prop_type == PROP_TYPE_ASYNC) {-                func_kind = JS_FUNC_ASYNC;-            } else if (prop_type == PROP_TYPE_ASYNC_STAR) {-                func_kind = JS_FUNC_ASYNC_GENERATOR;-            } else if (name == JS_ATOM_constructor && !is_static) {-                if (ctor_fd) {-                    js_parse_error(s, "property constructor appears more than once");-                    goto fail;-                }-                if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE)-                    func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;-                else-                    func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;-            }-            if (is_private) {-                if (add_brand(s, &class_fields[is_static]) < 0)-                    goto fail;-            }-            if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))-                goto fail;-            if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR ||-                func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {-                ctor_fd = method_fd;-            } else if (is_private) {-                method_fd->need_home_object = TRUE; /* needed for brand check */-                if (find_private_class_field(ctx, fd, name,-                                             fd->scope_level) >= 0) {-                private_field_already_defined:-                    js_parse_error(s, "private class field is already defined");-                    goto fail;-                }-                if (add_private_class_field(s, fd, name,-                                            JS_VAR_PRIVATE_METHOD) < 0)-                    goto fail;-                emit_op(s, OP_set_home_object);-                emit_op(s, OP_set_name);-                emit_atom(s, name);-                emit_op(s, OP_scope_put_var_init);-                emit_atom(s, name);-                emit_u16(s, s->cur_func->scope_level);-            } else {-                if (name == JS_ATOM_NULL) {-                    emit_op(s, OP_define_method_computed);-                } else {-                    emit_op(s, OP_define_method);-                    emit_atom(s, name);-                }-                emit_u8(s, OP_DEFINE_METHOD_METHOD);-            }-        }-        if (is_static)-            emit_op(s, OP_swap);-        JS_FreeAtom(ctx, name);-        name = JS_ATOM_NULL;-    }--    if (s->token.val != '}') {-        js_parse_error(s, "expecting '%c'", '}');-        goto fail;-    }--    if (!ctor_fd) {-        if (js_parse_class_default_ctor(s, class_flags & JS_DEFINE_CLASS_HAS_HERITAGE, &ctor_fd))-            goto fail;-    }-    /* patch the constant pool index for the constructor */-    put_u32(fd->byte_code.buf + ctor_cpool_offset, ctor_fd->parent_cpool_idx);--    /* store the class source code in the constructor. */-    if (!(fd->js_mode & JS_MODE_STRIP)) {-        js_free(ctx, ctor_fd->source);-        ctor_fd->source_len = s->buf_ptr - class_start_ptr;-        ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr,-                                     ctor_fd->source_len);-        if (!ctor_fd->source)-            goto fail;-    }--    /* consume the '}' */-    if (next_token(s))-        goto fail;--    /* store the function to initialize the fields to that it can be-       referenced by the constructor */-    {-        ClassFieldsDef *cf = &class_fields[0];-        int var_idx;-        -        var_idx = define_var(s, fd, JS_ATOM_class_fields_init,-                             JS_VAR_DEF_CONST);-        if (var_idx < 0)-            goto fail;-        if (cf->fields_init_fd) {-            emit_class_init_end(s, cf);-        } else {-            emit_op(s, OP_undefined);-        }-        emit_op(s, OP_scope_put_var_init);-        emit_atom(s, JS_ATOM_class_fields_init);-        emit_u16(s, s->cur_func->scope_level);-    }--    /* drop the prototype */-    emit_op(s, OP_drop);--    /* initialize the static fields */-    if (class_fields[1].fields_init_fd != NULL) {-        ClassFieldsDef *cf = &class_fields[1];-        emit_op(s, OP_dup);-        emit_class_init_end(s, cf);-        emit_op(s, OP_call_method);-        emit_u16(s, 0);-        emit_op(s, OP_drop);-    }-    -    if (class_name != JS_ATOM_NULL) {-        /* store the class name in the scoped class name variable (it-           is independent from the class statement variable-           definition) */-        emit_op(s, OP_dup);-        emit_op(s, OP_scope_put_var_init);-        emit_atom(s, class_name);-        emit_u16(s, fd->scope_level);-    }-    pop_scope(s);-    pop_scope(s);--    /* the class statements have a block level scope */-    if (class_var_name != JS_ATOM_NULL) {-        if (define_var(s, fd, class_var_name, JS_VAR_DEF_LET) < 0)-            goto fail;-        emit_op(s, OP_scope_put_var_init);-        emit_atom(s, class_var_name);-        emit_u16(s, fd->scope_level);-    } else {-        if (class_name == JS_ATOM_NULL) {-            /* cannot use OP_set_name because the name of the class-               must be defined before the static initializers are-               executed */-            emit_op(s, OP_set_class_name);-            emit_u32(s, fd->last_opcode_pos + 1 - define_class_offset);-        }-    }--    if (export_flag != JS_PARSE_EXPORT_NONE) {-        if (!add_export_entry(s, fd->module,-                              class_var_name,-                              export_flag == JS_PARSE_EXPORT_NAMED ? class_var_name : JS_ATOM_default,-                              JS_EXPORT_TYPE_LOCAL))-            goto fail;-    }--    JS_FreeAtom(ctx, class_name);-    JS_FreeAtom(ctx, class_var_name);-    fd->js_mode = saved_js_mode;-    return 0;- fail:-    JS_FreeAtom(ctx, name);-    JS_FreeAtom(ctx, class_name);-    JS_FreeAtom(ctx, class_var_name);-    fd->js_mode = saved_js_mode;-    return -1;-}--static __exception int js_parse_array_literal(JSParseState *s)-{-    uint32_t idx;-    BOOL need_length;--    if (next_token(s))-        return -1;-    /* small regular arrays are created on the stack */-    idx = 0;-    while (s->token.val != ']' && idx < 32) {-        if (s->token.val == ',' || s->token.val == TOK_ELLIPSIS)-            break;-        if (js_parse_assign_expr(s, TRUE))-            return -1;-        idx++;-        /* accept trailing comma */-        if (s->token.val == ',') {-            if (next_token(s))-                return -1;-        } else-        if (s->token.val != ']')-            goto done;-    }-    emit_op(s, OP_array_from);-    emit_u16(s, idx);--    /* larger arrays and holes are handled with explicit indices */-    need_length = FALSE;-    while (s->token.val != ']' && idx < 0x7fffffff) {-        if (s->token.val == TOK_ELLIPSIS)-            break;-        need_length = TRUE;-        if (s->token.val != ',') {-            if (js_parse_assign_expr(s, TRUE))-                return -1;-            emit_op(s, OP_define_field);-            emit_u32(s, __JS_AtomFromUInt32(idx));-            need_length = FALSE;-        }-        idx++;-        /* accept trailing comma */-        if (s->token.val == ',') {-            if (next_token(s))-                return -1;-        }-    }-    if (s->token.val == ']') {-        if (need_length) {-            /* Set the length: Cannot use OP_define_field because-               length is not configurable */-            emit_op(s, OP_dup);-            emit_op(s, OP_push_i32);-            emit_u32(s, idx);-            emit_op(s, OP_put_field);-            emit_atom(s, JS_ATOM_length);-        }-        goto done;-    }--    /* huge arrays and spread elements require a dynamic index on the stack */-    emit_op(s, OP_push_i32);-    emit_u32(s, idx);--    /* stack has array, index */-    while (s->token.val != ']') {-        if (s->token.val == TOK_ELLIPSIS) {-            if (next_token(s))-                return -1;-            if (js_parse_assign_expr(s, TRUE))-                return -1;-#if 1-            emit_op(s, OP_append);-#else-            int label_next, label_done;-            label_next = new_label(s);-            label_done = new_label(s);-            /* enumerate object */-            emit_op(s, OP_for_of_start);-            emit_op(s, OP_rot5l);-            emit_op(s, OP_rot5l);-            emit_label(s, label_next);-            /* on stack: enum_rec array idx */-            emit_op(s, OP_for_of_next);-            emit_u8(s, 2);-            emit_goto(s, OP_if_true, label_done);-            /* append element */-            /* enum_rec array idx val -> enum_rec array new_idx */-            emit_op(s, OP_define_array_el);-            emit_op(s, OP_inc);-            emit_goto(s, OP_goto, label_next);-            emit_label(s, label_done);-            /* close enumeration */-            emit_op(s, OP_drop); /* drop undef val */-            emit_op(s, OP_nip1); /* drop enum_rec */-            emit_op(s, OP_nip1);-            emit_op(s, OP_nip1);-#endif-        } else {-            need_length = TRUE;-            if (s->token.val != ',') {-                if (js_parse_assign_expr(s, TRUE))-                    return -1;-                /* a idx val */-                emit_op(s, OP_define_array_el);-                need_length = FALSE;-            }-            emit_op(s, OP_inc);-        }-        if (s->token.val != ',')-            break;-        if (next_token(s))-            return -1;-    }-    if (need_length) {-        /* Set the length: cannot use OP_define_field because-           length is not configurable */-        emit_op(s, OP_dup1);    /* array length - array array length */-        emit_op(s, OP_put_field);-        emit_atom(s, JS_ATOM_length);-    } else {-        emit_op(s, OP_drop);    /* array length - array */-    }-done:-    return js_parse_expect(s, ']');-}--/* XXX: remove */-static BOOL has_with_scope(JSFunctionDef *s, int scope_level)-{-    /* check if scope chain contains a with statement */-    while (s) {-        int scope_idx = s->scopes[scope_level].first;-        while (scope_idx >= 0) {-            JSVarDef *vd = &s->vars[scope_idx];--            if (vd->var_name == JS_ATOM__with_)-                return TRUE;-            scope_idx = vd->scope_next;-        }-        /* check parent scopes */-        scope_level = s->parent_scope_level;-        s = s->parent;-    }-    return FALSE;-}--static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,-                                  JSAtom *pname, int *plabel, int *pdepth, BOOL keep,-                                  int tok)-{-    JSFunctionDef *fd;-    int opcode, scope, label, depth;-    JSAtom name;--    /* we check the last opcode to get the lvalue type */-    fd = s->cur_func;-    scope = 0;-    name = JS_ATOM_NULL;-    label = -1;-    depth = 0;-    switch(opcode = get_prev_opcode(fd)) {-    case OP_scope_get_var:-        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);-        if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) &&-            (fd->js_mode & JS_MODE_STRICT)) {-            return js_parse_error(s, "invalid lvalue in strict mode");-        }-        if (name == JS_ATOM_this || name == JS_ATOM_new_target)-            goto invalid_lvalue;-        depth = 2;  /* will generate OP_get_ref_value */-        break;-    case OP_get_field:-        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        depth = 1;-        break;-    case OP_scope_get_private_field:-        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);-        depth = 1;-        break;-    case OP_get_array_el:-        depth = 2;-        break;-    case OP_get_super_value:-        depth = 3;-        break;-    default:-    invalid_lvalue:-        if (tok == TOK_FOR) {-            return js_parse_error(s, "invalid for in/of left hand-side");-        } else if (tok == TOK_INC || tok == TOK_DEC) {-            return js_parse_error(s, "invalid increment/decrement operand");-        } else if (tok == '[' || tok == '{') {-            return js_parse_error(s, "invalid destructuring target");-        } else {-            return js_parse_error(s, "invalid assignment left-hand side");-        }-    }-    /* remove the last opcode */-    fd->byte_code.size = fd->last_opcode_pos;-    fd->last_opcode_pos = -1;--    if (keep) {-        /* get the value but keep the object/fields on the stack */-        switch(opcode) {-        case OP_scope_get_var:-            label = new_label(s);-            emit_op(s, OP_scope_make_ref);-            emit_atom(s, name);-            emit_u32(s, label);-            emit_u16(s, scope);-            update_label(fd, label, 1);-            emit_op(s, OP_get_ref_value);-            opcode = OP_get_ref_value;-            break;-        case OP_get_field:-            emit_op(s, OP_get_field2);-            emit_atom(s, name);-            break;-        case OP_scope_get_private_field:-            emit_op(s, OP_scope_get_private_field2);-            emit_atom(s, name);-            emit_u16(s, scope);-            break;-        case OP_get_array_el:-            /* XXX: replace by a single opcode ? */-            emit_op(s, OP_to_propkey2);-            emit_op(s, OP_dup2);-            emit_op(s, OP_get_array_el);-            break;-        case OP_get_super_value:-            emit_op(s, OP_to_propkey);-            emit_op(s, OP_dup3);-            emit_op(s, OP_get_super_value);-            break;-        default:-            abort();-        }-    } else {-        switch(opcode) {-        case OP_scope_get_var:-            label = new_label(s);-            emit_op(s, OP_scope_make_ref);-            emit_atom(s, name);-            emit_u32(s, label);-            emit_u16(s, scope);-            update_label(fd, label, 1);-            opcode = OP_get_ref_value;-            break;-        case OP_get_array_el:-            emit_op(s, OP_to_propkey2);-            break;-        case OP_get_super_value:-            emit_op(s, OP_to_propkey);-            break;-        }-    }--    *popcode = opcode;-    *pscope = scope;-    /* name has refcount for OP_get_field and OP_get_ref_value,-       and JS_ATOM_NULL for other opcodes */-    *pname = name;-    *plabel = label;-    if (pdepth)-        *pdepth = depth;-    return 0;-}--typedef enum {-    PUT_LVALUE_NOKEEP, /* [depth] v -> */-    PUT_LVALUE_NOKEEP_DEPTH, /* [depth] v -> , keep depth (currently-                                just disable optimizations) */-    PUT_LVALUE_KEEP_TOP,  /* [depth] v -> v */-    PUT_LVALUE_KEEP_SECOND, /* [depth] v0 v -> v0 */-    PUT_LVALUE_NOKEEP_BOTTOM, /* v [depth] -> */-} PutLValueEnum;--/* name has a live reference. 'is_let' is only used with opcode =-   OP_scope_get_var which is never generated by get_lvalue(). */-static void put_lvalue(JSParseState *s, int opcode, int scope,-                       JSAtom name, int label, PutLValueEnum special,-                       BOOL is_let)-{-    switch(opcode) {-    case OP_get_field:-    case OP_scope_get_private_field:-        /* depth = 1 */-        switch(special) {-        case PUT_LVALUE_NOKEEP:-        case PUT_LVALUE_NOKEEP_DEPTH:-            break;-        case PUT_LVALUE_KEEP_TOP:-            emit_op(s, OP_insert2); /* obj v -> v obj v */-            break;-        case PUT_LVALUE_KEEP_SECOND:-            emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */-            break;-        case PUT_LVALUE_NOKEEP_BOTTOM:-            emit_op(s, OP_swap);-            break;-        default:-            abort();-        }-        break;-    case OP_get_array_el:-    case OP_get_ref_value:-        /* depth = 2 */-        if (opcode == OP_get_ref_value) {-            JS_FreeAtom(s->ctx, name);-            emit_label(s, label);-        }-        switch(special) {-        case PUT_LVALUE_NOKEEP:-            emit_op(s, OP_nop); /* will trigger optimization */-            break;-        case PUT_LVALUE_NOKEEP_DEPTH:-            break;-        case PUT_LVALUE_KEEP_TOP:-            emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */-            break;-        case PUT_LVALUE_KEEP_SECOND:-            emit_op(s, OP_perm4); /* obj prop v0 v -> v0 obj prop v */-            break;-        case PUT_LVALUE_NOKEEP_BOTTOM:-            emit_op(s, OP_rot3l);-            break;-        default:-            abort();-        }-        break;-    case OP_get_super_value:-        /* depth = 3 */-        switch(special) {-        case PUT_LVALUE_NOKEEP:-        case PUT_LVALUE_NOKEEP_DEPTH:-            break;-        case PUT_LVALUE_KEEP_TOP:-            emit_op(s, OP_insert4); /* this obj prop v -> v this obj prop v */-            break;-        case PUT_LVALUE_KEEP_SECOND:-            emit_op(s, OP_perm5); /* this obj prop v0 v -> v0 this obj prop v */-            break;-        case PUT_LVALUE_NOKEEP_BOTTOM:-            emit_op(s, OP_rot4l);-            break;-        default:-            abort();-        }-        break;-    default:-        break;-    }-    -    switch(opcode) {-    case OP_scope_get_var:  /* val -- */-        assert(special == PUT_LVALUE_NOKEEP ||-               special == PUT_LVALUE_NOKEEP_DEPTH);-        emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var);-        emit_u32(s, name);  /* has refcount */-        emit_u16(s, scope);-        break;-    case OP_get_field:-        emit_op(s, OP_put_field);-        emit_u32(s, name);  /* name has refcount */-        break;-    case OP_scope_get_private_field:-        emit_op(s, OP_scope_put_private_field);-        emit_u32(s, name);  /* name has refcount */-        emit_u16(s, scope);-        break;-    case OP_get_array_el:-        emit_op(s, OP_put_array_el);-        break;-    case OP_get_ref_value:-        emit_op(s, OP_put_ref_value);-        break;-    case OP_get_super_value:-        emit_op(s, OP_put_super_value);-        break;-    default:-        abort();-    }-}--static __exception int js_parse_expr_paren(JSParseState *s)-{-    if (js_parse_expect(s, '('))-        return -1;-    if (js_parse_expr(s))-        return -1;-    if (js_parse_expect(s, ')'))-        return -1;-    return 0;-}--static int js_unsupported_keyword(JSParseState *s, JSAtom atom)-{-    char buf[ATOM_GET_STR_BUF_SIZE];-    return js_parse_error(s, "unsupported keyword: %s",-                          JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));-}--static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)-{-    JSFunctionDef *fd = s->cur_func;-    JSVarDefEnum var_def_type;-    -    if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {-        return js_parse_error(s, "yield is a reserved identifier");-    }-    if ((name == JS_ATOM_arguments || name == JS_ATOM_eval)-    &&  (fd->js_mode & JS_MODE_STRICT)) {-        return js_parse_error(s, "invalid variable name in strict mode");-    }-    if ((name == JS_ATOM_let || name == JS_ATOM_undefined)-    &&  (tok == TOK_LET || tok == TOK_CONST)) {-        return js_parse_error(s, "invalid lexical variable name");-    }-    switch(tok) {-    case TOK_LET:-        var_def_type = JS_VAR_DEF_LET;-        break;-    case TOK_CONST:-        var_def_type = JS_VAR_DEF_CONST;-        break;-    case TOK_VAR:-        var_def_type = JS_VAR_DEF_VAR;-        break;-    case TOK_CATCH:-        var_def_type = JS_VAR_DEF_CATCH;-        break;-    default:-        abort();-    }-    if (define_var(s, fd, name, var_def_type) < 0)-        return -1;-    return 0;-}--static void js_emit_spread_code(JSParseState *s, int depth)-{-    int label_rest_next, label_rest_done;--    /* XXX: could check if enum object is an actual array and optimize-       slice extraction. enumeration record and target array are in a-       different order from OP_append case. */-    /* enum_rec xxx -- enum_rec xxx array 0 */-    emit_op(s, OP_array_from);-    emit_u16(s, 0);-    emit_op(s, OP_push_i32);-    emit_u32(s, 0);-    emit_label(s, label_rest_next = new_label(s));-    emit_op(s, OP_for_of_next);-    emit_u8(s, 2 + depth);-    label_rest_done = emit_goto(s, OP_if_true, -1);-    /* array idx val -- array idx */-    emit_op(s, OP_define_array_el);-    emit_op(s, OP_inc);-    emit_goto(s, OP_goto, label_rest_next);-    emit_label(s, label_rest_done);-    /* enum_rec xxx array idx undef -- enum_rec xxx array */-    emit_op(s, OP_drop);-    emit_op(s, OP_drop);-}--static int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name)-{-    /* Check for duplicate parameter names */-    JSFunctionDef *fd = s->cur_func;-    int i;-    for (i = 0; i < fd->arg_count; i++) {-        if (fd->args[i].var_name == name)-            goto duplicate;-    }-    for (i = 0; i < fd->var_count; i++) {-        if (fd->vars[i].var_name == name)-            goto duplicate;-    }-    return 0;--duplicate:-    return js_parse_error(s, "duplicate parameter names not allowed in this context");-}--static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)-{-    JSAtom name;--    if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)-    ||  ((s->cur_func->js_mode & JS_MODE_STRICT) &&-         (s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) {-        js_parse_error(s, "invalid destructuring target");-        return JS_ATOM_NULL;-    }-    name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-    if (is_arg && js_parse_check_duplicate_parameter(s, name))-        goto fail;-    if (next_token(s))-        goto fail;--    return name;-fail:-    JS_FreeAtom(s->ctx, name);-    return JS_ATOM_NULL;-}--static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,-                                        int hasval, int has_ellipsis,-                                        BOOL allow_initializer)-{-    int label_parse, label_assign, label_done, label_lvalue, depth_lvalue;-    int start_addr, assign_addr;-    JSAtom prop_name, var_name;-    int opcode, scope, tok1, skip_bits;--    if (has_ellipsis < 0) {-        /* pre-parse destructuration target for spread detection */-        js_parse_skip_parens_token(s, &skip_bits, FALSE);-        has_ellipsis = skip_bits & SKIP_HAS_ELLIPSIS;-    }--    label_parse = new_label(s);-    label_assign = new_label(s);--    start_addr = s->cur_func->byte_code.size;-    if (hasval) {-        /* consume value from the stack */-        emit_op(s, OP_dup);-        emit_op(s, OP_undefined);-        emit_op(s, OP_strict_eq);-        emit_goto(s, OP_if_true, label_parse);-        emit_label(s, label_assign);-    } else {-        emit_goto(s, OP_goto, label_parse);-        emit_label(s, label_assign);-        /* leave value on the stack */-        emit_op(s, OP_dup);-    }-    assign_addr = s->cur_func->byte_code.size;-    if (s->token.val == '{') {-        if (next_token(s))-            return -1;-        /* throw an exception if the value cannot be converted to an object */-        emit_op(s, OP_to_object);-        if (has_ellipsis) {-            /* add excludeList on stack just below src object */-            emit_op(s, OP_object);-            emit_op(s, OP_swap);-        }-        while (s->token.val != '}') {-            int prop_type;-            if (s->token.val == TOK_ELLIPSIS) {-                if (!has_ellipsis) {-                    JS_ThrowInternalError(s->ctx, "unexpected ellipsis token");-                    return -1;-                }-                if (next_token(s))-                    return -1;-                if (tok) {-                    var_name = js_parse_destructuring_var(s, tok, is_arg);-                    if (var_name == JS_ATOM_NULL)-                        return -1;-                    opcode = OP_scope_get_var;-                    scope = s->cur_func->scope_level;-                    label_lvalue = -1;-                    depth_lvalue = 0;-                } else {-                    if (js_parse_postfix_expr(s, TRUE))-                        return -1;--                    if (get_lvalue(s, &opcode, &scope, &var_name,-                                   &label_lvalue, &depth_lvalue, FALSE, '{'))-                        return -1;-                }-                if (s->token.val != '}') {-                    js_parse_error(s, "assignment rest property must be last");-                    goto var_error;-                }-                emit_op(s, OP_object);  /* target */-                emit_op(s, OP_copy_data_properties);-                emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5));-                goto set_val;-            }-            prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE, FALSE);-            if (prop_type < 0)-                return -1;-            var_name = JS_ATOM_NULL;-            opcode = OP_scope_get_var;-            scope = s->cur_func->scope_level;-            label_lvalue = -1;-            depth_lvalue = 0;-            if (prop_type == PROP_TYPE_IDENT) {-                if (next_token(s))-                    goto prop_error;-                if ((s->token.val == '[' || s->token.val == '{')-                    &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||-                         tok1 == '=' || tok1 == '}')) {-                    if (prop_name == JS_ATOM_NULL) {-                        /* computed property name on stack */-                        if (has_ellipsis) {-                            /* define the property in excludeList */-                            emit_op(s, OP_to_propkey); /* avoid calling ToString twice */-                            emit_op(s, OP_perm3); /* TOS: src excludeList prop */-                            emit_op(s, OP_null); /* TOS: src excludeList prop null */-                            emit_op(s, OP_define_array_el); /* TOS: src excludeList prop */-                            emit_op(s, OP_perm3); /* TOS: excludeList src prop */-                        }-                        /* get the computed property from the source object */-                        emit_op(s, OP_get_array_el2);-                    } else {-                        /* named property */-                        if (has_ellipsis) {-                            /* define the property in excludeList */-                            emit_op(s, OP_swap); /* TOS: src excludeList */-                            emit_op(s, OP_null); /* TOS: src excludeList null */-                            emit_op(s, OP_define_field); /* TOS: src excludeList */-                            emit_atom(s, prop_name);-                            emit_op(s, OP_swap); /* TOS: excludeList src */-                        }-                        /* get the named property from the source object */-                        emit_op(s, OP_get_field2);-                        emit_u32(s, prop_name);-                    }-                    if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE))-                        return -1;-                    if (s->token.val == '}')-                        break;-                    /* accept a trailing comma before the '}' */-                    if (js_parse_expect(s, ','))-                        return -1;-                    continue;-                }-                if (prop_name == JS_ATOM_NULL) {-                    emit_op(s, OP_to_propkey2);-                    if (has_ellipsis) {-                        /* define the property in excludeList */-                        emit_op(s, OP_perm3);-                        emit_op(s, OP_null);-                        emit_op(s, OP_define_array_el);-                        emit_op(s, OP_perm3);-                    }-                    /* source prop -- source source prop */-                    emit_op(s, OP_dup1);-                } else {-                    if (has_ellipsis) {-                        /* define the property in excludeList */-                        emit_op(s, OP_swap);-                        emit_op(s, OP_null);-                        emit_op(s, OP_define_field);-                        emit_atom(s, prop_name);-                        emit_op(s, OP_swap);-                    }-                    /* source -- source source */-                    emit_op(s, OP_dup);-                }-                if (tok) {-                    var_name = js_parse_destructuring_var(s, tok, is_arg);-                    if (var_name == JS_ATOM_NULL)-                        goto prop_error;-                } else {-                    if (js_parse_postfix_expr(s, TRUE))-                        goto prop_error;-                lvalue:-                    if (get_lvalue(s, &opcode, &scope, &var_name,-                                   &label_lvalue, &depth_lvalue, FALSE, '{'))-                        goto prop_error;-                    /* swap ref and lvalue object if any */-                    if (prop_name == JS_ATOM_NULL) {-                        switch(depth_lvalue) {-                        case 1:-                            /* source prop x -> x source prop */-                            emit_op(s, OP_rot3r);-                            break;-                        case 2:-                            /* source prop x y -> x y source prop */-                            emit_op(s, OP_swap2);   /* t p2 s p1 */-                            break;-                        case 3:-                            /* source prop x y z -> x y z source prop */-                            emit_op(s, OP_rot5l);-                            emit_op(s, OP_rot5l);-                            break;-                        }-                    } else {-                        switch(depth_lvalue) {-                        case 1:-                            /* source x -> x source */-                            emit_op(s, OP_swap);-                            break;-                        case 2:-                            /* source x y -> x y source */-                            emit_op(s, OP_rot3l);-                            break;-                        case 3:-                            /* source x y z -> x y z source */-                            emit_op(s, OP_rot4l);-                            break;-                        }-                    }-                }-                if (prop_name == JS_ATOM_NULL) {-                    /* computed property name on stack */-                    /* XXX: should have OP_get_array_el2x with depth */-                    /* source prop -- val */-                    emit_op(s, OP_get_array_el);-                } else {-                    /* named property */-                    /* XXX: should have OP_get_field2x with depth */-                    /* source -- val */-                    emit_op(s, OP_get_field);-                    emit_u32(s, prop_name);-                }-            } else {-                /* prop_type = PROP_TYPE_VAR, cannot be a computed property */-                if (is_arg && js_parse_check_duplicate_parameter(s, prop_name))-                    goto prop_error;-                if ((s->cur_func->js_mode & JS_MODE_STRICT) &&-                    (prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) {-                    js_parse_error(s, "invalid destructuring target");-                    goto prop_error;-                }-                if (has_ellipsis) {-                    /* define the property in excludeList */-                    emit_op(s, OP_swap);-                    emit_op(s, OP_null);-                    emit_op(s, OP_define_field);-                    emit_atom(s, prop_name);-                    emit_op(s, OP_swap);-                }-                if (!tok || tok == TOK_VAR) {-                    /* generate reference */-                    /* source -- source source */-                    emit_op(s, OP_dup);-                    emit_op(s, OP_scope_get_var);-                    emit_atom(s, prop_name);-                    emit_u16(s, s->cur_func->scope_level);-                    goto lvalue;-                }-                var_name = JS_DupAtom(s->ctx, prop_name);-                /* source -- source val */-                emit_op(s, OP_get_field2);-                emit_u32(s, prop_name);-            }-        set_val:-            if (tok) {-                if (js_define_var(s, var_name, tok))-                    goto var_error;-                scope = s->cur_func->scope_level;-            }-            if (s->token.val == '=') {  /* handle optional default value */-                int label_hasval;-                emit_op(s, OP_dup);-                emit_op(s, OP_undefined);-                emit_op(s, OP_strict_eq);-                label_hasval = emit_goto(s, OP_if_false, -1);-                if (next_token(s))-                    goto var_error;-                emit_op(s, OP_drop);-                if (js_parse_assign_expr(s, TRUE))-                    goto var_error;-                if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)-                    set_object_name(s, var_name);-                emit_label(s, label_hasval);-            }-            /* store value into lvalue object */-            put_lvalue(s, opcode, scope, var_name, label_lvalue,-                       PUT_LVALUE_NOKEEP_DEPTH,-                       (tok == TOK_CONST || tok == TOK_LET));-            if (s->token.val == '}')-                break;-            /* accept a trailing comma before the '}' */-            if (js_parse_expect(s, ','))-                return -1;-        }-        /* drop the source object */-        emit_op(s, OP_drop);-        if (has_ellipsis) {-            emit_op(s, OP_drop); /* pop excludeList */-        }-        if (next_token(s))-            return -1;-    } else if (s->token.val == '[') {-        BOOL has_spread;-        int enum_depth;-        BlockEnv block_env;--        if (next_token(s))-            return -1;-        /* the block environment is only needed in generators in case-           'yield' triggers a 'return' */-        push_break_entry(s->cur_func, &block_env,-                         JS_ATOM_NULL, -1, -1, 2);-        block_env.has_iterator = TRUE;-        emit_op(s, OP_for_of_start);-        has_spread = FALSE;-        while (s->token.val != ']') {-            /* get the next value */-            if (s->token.val == TOK_ELLIPSIS) {-                if (next_token(s))-                    return -1;-                if (s->token.val == ',' || s->token.val == ']')-                    return js_parse_error(s, "missing binding pattern...");-                has_spread = TRUE;-            }-            if (s->token.val == ',') {-                /* do nothing, skip the value, has_spread is false */-                emit_op(s, OP_for_of_next);-                emit_u8(s, 0);-                emit_op(s, OP_drop);-                emit_op(s, OP_drop);-            } else if ((s->token.val == '[' || s->token.val == '{')-                   &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||-                        tok1 == '=' || tok1 == ']')) {-                if (has_spread) {-                    if (tok1 == '=')-                        return js_parse_error(s, "rest element cannot have a default value");-                    js_emit_spread_code(s, 0);-                } else {-                    emit_op(s, OP_for_of_next);-                    emit_u8(s, 0);-                    emit_op(s, OP_drop);-                }-                if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))-                    return -1;-            } else {-                var_name = JS_ATOM_NULL;-                enum_depth = 0;-                if (tok) {-                    var_name = js_parse_destructuring_var(s, tok, is_arg);-                    if (var_name == JS_ATOM_NULL)-                        goto var_error;-                    if (js_define_var(s, var_name, tok))-                        goto var_error;-                    opcode = OP_scope_get_var;-                    scope = s->cur_func->scope_level;-                } else {-                    if (js_parse_postfix_expr(s, TRUE))-                        return -1;-                    if (get_lvalue(s, &opcode, &scope, &var_name,-                                   &label_lvalue, &enum_depth, FALSE, '[')) {-                        return -1;-                    }-                }-                if (has_spread) {-                    js_emit_spread_code(s, enum_depth);-                } else {-                    emit_op(s, OP_for_of_next);-                    emit_u8(s, enum_depth);-                    emit_op(s, OP_drop);-                }-                if (s->token.val == '=' && !has_spread) {-                    /* handle optional default value */-                    int label_hasval;-                    emit_op(s, OP_dup);-                    emit_op(s, OP_undefined);-                    emit_op(s, OP_strict_eq);-                    label_hasval = emit_goto(s, OP_if_false, -1);-                    if (next_token(s))-                        goto var_error;-                    emit_op(s, OP_drop);-                    if (js_parse_assign_expr(s, TRUE))-                        goto var_error;-                    if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)-                        set_object_name(s, var_name);-                    emit_label(s, label_hasval);-                }-                /* store value into lvalue object */-                put_lvalue(s, opcode, scope, var_name,-                           label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,-                           (tok == TOK_CONST || tok == TOK_LET));-            }-            if (s->token.val == ']')-                break;-            if (has_spread)-                return js_parse_error(s, "rest element must be the last one");-            /* accept a trailing comma before the ']' */-            if (js_parse_expect(s, ','))-                return -1;-        }-        /* close iterator object:-           if completed, enum_obj has been replaced by undefined */-        emit_op(s, OP_iterator_close);-        pop_break_entry(s->cur_func);-        if (next_token(s))-            return -1;-    } else {-        return js_parse_error(s, "invalid assignment syntax");-    }-    if (s->token.val == '=' && allow_initializer) {-        label_done = emit_goto(s, OP_goto, -1);-        if (next_token(s))-            return -1;-        emit_label(s, label_parse);-        if (hasval)-            emit_op(s, OP_drop);-        if (js_parse_assign_expr(s, TRUE))-            return -1;-        emit_goto(s, OP_goto, label_assign);-        emit_label(s, label_done);-    } else {-        /* normally hasval is true except if-           js_parse_skip_parens_token() was wrong in the parsing */-        //        assert(hasval);-        if (!hasval) {-            js_parse_error(s, "too complicated destructuring expression");-            return -1;-        }-        /* remove test and decrement label ref count */-        memset(s->cur_func->byte_code.buf + start_addr, OP_nop,-               assign_addr - start_addr);-        s->cur_func->label_slots[label_parse].ref_count--;-    }-    return 0;-- prop_error:-    JS_FreeAtom(s->ctx, prop_name);- var_error:-    JS_FreeAtom(s->ctx, var_name);-    return -1;-}--typedef enum FuncCallType {-    FUNC_CALL_NORMAL,-    FUNC_CALL_NEW,-    FUNC_CALL_SUPER_CTOR,-    FUNC_CALL_TEMPLATE,-} FuncCallType;--static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,-                                int drop_count)-{-    int label_next, i;-    if (*poptional_chaining_label < 0)-        *poptional_chaining_label = new_label(s);-   /* XXX: could be more efficient with a specific opcode */-    emit_op(s, OP_dup);-    emit_op(s, OP_is_undefined_or_null);-    label_next = emit_goto(s, OP_if_false, -1);-    for(i = 0; i < drop_count; i++)-        emit_op(s, OP_drop);-    emit_op(s, OP_undefined);-    emit_goto(s, OP_goto, *poptional_chaining_label);-    emit_label(s, label_next);-}--static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen)-{-    FuncCallType call_type;-    int optional_chaining_label;-    -    call_type = FUNC_CALL_NORMAL;-    switch(s->token.val) {-    case TOK_NUMBER:-        {-            JSValue val;-            val = s->token.u.num.val;--            if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {-                emit_op(s, OP_push_i32);-                emit_u32(s, JS_VALUE_GET_INT(val));-            } else-#ifdef CONFIG_BIGNUM-            if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {-                slimb_t e;-                int ret;--                /* need a runtime conversion */-                /* XXX: could add a cache and/or do it once at-                   the start of the function */-                if (emit_push_const(s, val, 0) < 0)-                    return -1;-                e = s->token.u.num.exponent;-                if (e == (int32_t)e) {-                    emit_op(s, OP_push_i32);-                    emit_u32(s, e);-                } else {-                    val = JS_NewBigInt64_1(s->ctx, e);-                    if (JS_IsException(val))-                        return -1;-                    ret = emit_push_const(s, val, 0);-                    JS_FreeValue(s->ctx, val);-                    if (ret < 0)-                        return -1;-                }-                emit_op(s, OP_mul_pow10);-            } else-#endif-            {-                if (emit_push_const(s, val, 0) < 0)-                    return -1;-            }-        }-        if (next_token(s))-            return -1;-        break;-    case TOK_TEMPLATE:-        if (js_parse_template(s, 0, NULL))-            return -1;-        break;-    case TOK_STRING:-        if (emit_push_const(s, s->token.u.str.str, 1))-            return -1;-        if (next_token(s))-            return -1;-        break;-        -    case TOK_DIV_ASSIGN:-        s->buf_ptr -= 2;-        goto parse_regexp;-    case '/':-        s->buf_ptr--;-    parse_regexp:-        {-            JSValue str;-            int ret, backtrace_flags;-            if (!s->ctx->compile_regexp)-                return js_parse_error(s, "RegExp are not supported");-            /* the previous token is '/' or '/=', so no need to free */-            if (js_parse_regexp(s))-                return -1;-            ret = emit_push_const(s, s->token.u.regexp.body, 0);-            str = s->ctx->compile_regexp(s->ctx, s->token.u.regexp.body,-                                         s->token.u.regexp.flags);-            if (JS_IsException(str)) {-                /* add the line number info */-                backtrace_flags = 0;-                if (s->cur_func && s->cur_func->backtrace_barrier)-                    backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;-                build_backtrace(s->ctx, s->ctx->rt->current_exception,-                                s->filename, s->token.line_num,-                                backtrace_flags);-                return -1;-            }-            ret = emit_push_const(s, str, 0);-            JS_FreeValue(s->ctx, str);-            if (ret)-                return -1;-            /* we use a specific opcode to be sure the correct-               function is called (otherwise the bytecode would have-               to be verified by the RegExp constructor) */-            emit_op(s, OP_regexp);-            if (next_token(s))-                return -1;-        }-        break;-    case '(':-        if (js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {-            if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,-                                       JS_FUNC_NORMAL, JS_ATOM_NULL,-                                       s->token.ptr, s->token.line_num))-                return -1;-        } else {-            if (js_parse_expr_paren(s))-                return -1;-        }-        break;-    case TOK_FUNCTION:-        if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,-                                   JS_FUNC_NORMAL, JS_ATOM_NULL,-                                   s->token.ptr, s->token.line_num))-            return -1;-        break;-    case TOK_CLASS:-        if (js_parse_class(s, TRUE, JS_PARSE_EXPORT_NONE))-            return -1;-        break;-    case TOK_NULL:-        if (next_token(s))-            return -1;-        emit_op(s, OP_null);-        break;-    case TOK_THIS:-        if (next_token(s))-            return -1;-        emit_op(s, OP_scope_get_var);-        emit_atom(s, JS_ATOM_this);-        emit_u16(s, 0);-        break;-    case TOK_FALSE:-        if (next_token(s))-            return -1;-        emit_op(s, OP_push_false);-        break;-    case TOK_TRUE:-        if (next_token(s))-            return -1;-        emit_op(s, OP_push_true);-        break;-    case TOK_IDENT:-        {-            JSAtom name;-            if (s->token.u.ident.is_reserved) {-                return js_parse_error_reserved_identifier(s);-            }-            if (peek_token(s, TRUE) == TOK_ARROW) {-                if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,-                                           JS_FUNC_NORMAL, JS_ATOM_NULL,-                                           s->token.ptr, s->token.line_num))-                    return -1;-            } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&-                       peek_token(s, TRUE) != '\n') {-                const uint8_t *source_ptr;-                int source_line_num;--                source_ptr = s->token.ptr;-                source_line_num = s->token.line_num;-                if (next_token(s))-                    return -1;-                if (s->token.val == TOK_FUNCTION) {-                    if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,-                                               JS_FUNC_ASYNC, JS_ATOM_NULL,-                                               source_ptr, source_line_num))-                        return -1;-                } else if ((s->token.val == '(' &&-                            js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||-                           (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&-                            peek_token(s, TRUE) == TOK_ARROW)) {-                    if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,-                                               JS_FUNC_ASYNC, JS_ATOM_NULL,-                                               source_ptr, source_line_num))-                        return -1;-                } else {-                    name = JS_DupAtom(s->ctx, JS_ATOM_async);-                    goto do_get_var;-                }-            } else {-                if (s->token.u.ident.atom == JS_ATOM_arguments &&-                    !s->cur_func->arguments_allowed) {-                    js_parse_error(s, "'arguments' identifier is not allowed in class field initializer");-                    return -1;-                }-                name = JS_DupAtom(s->ctx, s->token.u.ident.atom);-                if (next_token(s))  /* update line number before emitting code */-                    return -1;-            do_get_var:-                emit_op(s, OP_scope_get_var);-                emit_u32(s, name);-                emit_u16(s, s->cur_func->scope_level);-            }-        }-        break;-    case '{':-    case '[':-        {-            int skip_bits;-            if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {-                if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))-                    return -1;-            } else {-                if (s->token.val == '{') {-                    if (js_parse_object_literal(s))-                        return -1;-                } else {-                    if (js_parse_array_literal(s))-                        return -1;-                }-            }-        }-        break;-    case TOK_NEW:-        if (next_token(s))-            return -1;-        if (s->token.val == '.') {-            if (next_token(s))-                return -1;-            if (!token_is_pseudo_keyword(s, JS_ATOM_target))-                return js_parse_error(s, "expecting target");-            if (!s->cur_func->new_target_allowed)-                return js_parse_error(s, "new.target only allowed within functions");-            if (next_token(s))-                return -1;-            emit_op(s, OP_scope_get_var);-            emit_atom(s, JS_ATOM_new_target);-            emit_u16(s, 0);-        } else {-            if (js_parse_postfix_expr(s, FALSE))-                return -1;-            accept_lparen = TRUE;-            if (s->token.val != '(') {-                /* new operator on an object */-                emit_op(s, OP_dup);-                emit_op(s, OP_call_constructor);-                emit_u16(s, 0);-            } else {-                call_type = FUNC_CALL_NEW;-            }-        }-        break;-    case TOK_SUPER:-        if (next_token(s))-            return -1;-        if (s->token.val == '(') {-            if (!s->cur_func->super_call_allowed)-                return js_parse_error(s, "super() is only valid in a derived class constructor");-            call_type = FUNC_CALL_SUPER_CTOR;-        } else if (s->token.val == '.' || s->token.val == '[') {-            if (!s->cur_func->super_allowed)-                return js_parse_error(s, "'super' is only valid in a method");-            emit_op(s, OP_scope_get_var);-            emit_atom(s, JS_ATOM_this);-            emit_u16(s, 0);-            emit_op(s, OP_scope_get_var);-            emit_atom(s, JS_ATOM_home_object);-            emit_u16(s, 0);-            emit_op(s, OP_get_super);-        } else {-            return js_parse_error(s, "invalid use of 'super'");-        }-        break;-    case TOK_IMPORT:-        if (next_token(s))-            return -1;-        if (s->token.val == '.') {-            if (next_token(s))-                return -1;-            if (!token_is_pseudo_keyword(s, JS_ATOM_meta))-                return js_parse_error(s, "meta expected");-            if (!s->is_module)-                return js_parse_error(s, "import.meta only valid in module code");-            if (next_token(s))-                return -1;-            emit_op(s, OP_special_object);-            emit_u8(s, OP_SPECIAL_OBJECT_IMPORT_META);-        } else {-            if (js_parse_expect(s, '('))-                return -1;-            if (!accept_lparen)-                return js_parse_error(s, "invalid use of 'import()'");-            if (js_parse_assign_expr(s, TRUE))-                return -1;-            if (js_parse_expect(s, ')'))-                return -1;-            emit_op(s, OP_import);-        }-        break;-    default:-        return js_parse_error(s, "unexpected token in expression: '%.*s'",-                              (int)(s->buf_ptr - s->token.ptr), s->token.ptr);-    }--    optional_chaining_label = -1;-    for(;;) {-        JSFunctionDef *fd = s->cur_func;-        BOOL has_optional_chain = FALSE;-        -        if (s->token.val == TOK_QUESTION_MARK_DOT) {-            /* optional chaining */-            if (next_token(s))-                return -1;-            has_optional_chain = TRUE;-            if (s->token.val == '(' && accept_lparen) {-                goto parse_func_call;-            } else if (s->token.val == '[') {-                goto parse_array_access;-            } else {-                goto parse_property;-            }-        } else if (s->token.val == TOK_TEMPLATE &&-                   call_type == FUNC_CALL_NORMAL) {-            if (optional_chaining_label >= 0) {-                return js_parse_error(s, "template literal cannot appear in an optional chain");-            }-            call_type = FUNC_CALL_TEMPLATE;-            goto parse_func_call2;-        } else if (s->token.val == '(' && accept_lparen) {-            int opcode, arg_count, drop_count;--            /* function call */-        parse_func_call:-            if (next_token(s))-                return -1;--            if (call_type == FUNC_CALL_NORMAL) {-            parse_func_call2:-                switch(opcode = get_prev_opcode(fd)) {-                case OP_get_field:-                    /* keep the object on the stack */-                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;-                    drop_count = 2;-                    break;-                case OP_scope_get_private_field:-                    /* keep the object on the stack */-                    fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_private_field2;-                    drop_count = 2;-                    break;-                case OP_get_array_el:-                    /* keep the object on the stack */-                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;-                    drop_count = 2;-                    break;-                case OP_scope_get_var:-                    {-                        JSAtom name;-                        int scope;-                        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-                        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);-                        if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL && !has_optional_chain) {-                            /* direct 'eval' */-                            opcode = OP_eval;-                        } else {-                            /* verify if function name resolves to a simple-                               get_loc/get_arg: a function call inside a `with`-                               statement can resolve to a method call of the-                               `with` context object-                             */-                            /* XXX: always generate the OP_scope_get_ref-                               and remove it in variable resolution-                               pass ? */-                            if (has_with_scope(fd, scope)) {-                                opcode = OP_scope_get_ref;-                                fd->byte_code.buf[fd->last_opcode_pos] = opcode;-                            }-                        }-                        drop_count = 1;-                    }-                    break;-                case OP_get_super_value:-                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el;-                    /* on stack: this func_obj */-                    opcode = OP_get_array_el;-                    drop_count = 2;-                    break;-                default:-                    opcode = OP_invalid;-                    drop_count = 1;-                    break;-                }-                if (has_optional_chain) {-                    optional_chain_test(s, &optional_chaining_label,-                                        drop_count);-                }-            } else {-                opcode = OP_invalid;-            }--            if (call_type == FUNC_CALL_TEMPLATE) {-                if (js_parse_template(s, 1, &arg_count))-                    return -1;-                goto emit_func_call;-            } else if (call_type == FUNC_CALL_SUPER_CTOR) {-                emit_op(s, OP_scope_get_var);-                emit_atom(s, JS_ATOM_this_active_func);-                emit_u16(s, 0);--                emit_op(s, OP_get_super);--                emit_op(s, OP_scope_get_var);-                emit_atom(s, JS_ATOM_new_target);-                emit_u16(s, 0);-            } else if (call_type == FUNC_CALL_NEW) {-                emit_op(s, OP_dup); /* new.target = function */-            }--            /* parse arguments */-            arg_count = 0;-            while (s->token.val != ')') {-                if (arg_count >= 65535) {-                    return js_parse_error(s, "Too many call arguments");-                }-                if (s->token.val == TOK_ELLIPSIS)-                    break;-                if (js_parse_assign_expr(s, TRUE))-                    return -1;-                arg_count++;-                if (s->token.val == ')')-                    break;-                /* accept a trailing comma before the ')' */-                if (js_parse_expect(s, ','))-                    return -1;-            }-            if (s->token.val == TOK_ELLIPSIS) {-                emit_op(s, OP_array_from);-                emit_u16(s, arg_count);-                emit_op(s, OP_push_i32);-                emit_u32(s, arg_count);--                /* on stack: array idx */-                while (s->token.val != ')') {-                    if (s->token.val == TOK_ELLIPSIS) {-                        if (next_token(s))-                            return -1;-                        if (js_parse_assign_expr(s, TRUE))-                            return -1;-#if 1-                        /* XXX: could pass is_last indicator? */-                        emit_op(s, OP_append);-#else-                        int label_next, label_done;-                        label_next = new_label(s);-                        label_done = new_label(s);-                        /* push enumerate object below array/idx pair */-                        emit_op(s, OP_for_of_start);-                        emit_op(s, OP_rot5l);-                        emit_op(s, OP_rot5l);-                        emit_label(s, label_next);-                        /* on stack: enum_rec array idx */-                        emit_op(s, OP_for_of_next);-                        emit_u8(s, 2);-                        emit_goto(s, OP_if_true, label_done);-                        /* append element */-                        /* enum_rec array idx val -> enum_rec array new_idx */-                        emit_op(s, OP_define_array_el);-                        emit_op(s, OP_inc);-                        emit_goto(s, OP_goto, label_next);-                        emit_label(s, label_done);-                        /* close enumeration, drop enum_rec and idx */-                        emit_op(s, OP_drop); /* drop undef */-                        emit_op(s, OP_nip1); /* drop enum_rec */-                        emit_op(s, OP_nip1);-                        emit_op(s, OP_nip1);-#endif-                    } else {-                        if (js_parse_assign_expr(s, TRUE))-                            return -1;-                        /* array idx val */-                        emit_op(s, OP_define_array_el);-                        emit_op(s, OP_inc);-                    }-                    if (s->token.val == ')')-                        break;-                    /* accept a trailing comma before the ')' */-                    if (js_parse_expect(s, ','))-                        return -1;-                }-                if (next_token(s))-                    return -1;-                /* drop the index */-                emit_op(s, OP_drop);--                /* apply function call */-                switch(opcode) {-                case OP_get_field:-                case OP_scope_get_private_field:-                case OP_get_array_el:-                case OP_scope_get_ref:-                    /* obj func array -> func obj array */-                    emit_op(s, OP_perm3);-                    emit_op(s, OP_apply);-                    emit_u16(s, call_type == FUNC_CALL_NEW);-                    break;-                case OP_eval:-                    emit_op(s, OP_apply_eval);-                    emit_u16(s, fd->scope_level);-                    fd->has_eval_call = TRUE;-                    break;-                default:-                    if (call_type == FUNC_CALL_SUPER_CTOR) {-                        emit_op(s, OP_apply);-                        emit_u16(s, 1);-                        /* set the 'this' value */-                        emit_op(s, OP_dup);-                        emit_op(s, OP_scope_put_var_init);-                        emit_atom(s, JS_ATOM_this);-                        emit_u16(s, 0);--                        emit_class_field_init(s);-                    } else if (call_type == FUNC_CALL_NEW) {-                        /* obj func array -> func obj array */-                        emit_op(s, OP_perm3);-                        emit_op(s, OP_apply);-                        emit_u16(s, 1);-                    } else {-                        /* func array -> func undef array */-                        emit_op(s, OP_undefined);-                        emit_op(s, OP_swap);-                        emit_op(s, OP_apply);-                        emit_u16(s, 0);-                    }-                    break;-                }-            } else {-                if (next_token(s))-                    return -1;-            emit_func_call:-                switch(opcode) {-                case OP_get_field:-                case OP_scope_get_private_field:-                case OP_get_array_el:-                case OP_scope_get_ref:-                    emit_op(s, OP_call_method);-                    emit_u16(s, arg_count);-                    break;-                case OP_eval:-                    emit_op(s, OP_eval);-                    emit_u16(s, arg_count);-                    emit_u16(s, fd->scope_level);-                    fd->has_eval_call = TRUE;-                    break;-                default:-                    if (call_type == FUNC_CALL_SUPER_CTOR) {-                        emit_op(s, OP_call_constructor);-                        emit_u16(s, arg_count);--                        /* set the 'this' value */-                        emit_op(s, OP_dup);-                        emit_op(s, OP_scope_put_var_init);-                        emit_atom(s, JS_ATOM_this);-                        emit_u16(s, 0);--                        emit_class_field_init(s);-                    } else if (call_type == FUNC_CALL_NEW) {-                        emit_op(s, OP_call_constructor);-                        emit_u16(s, arg_count);-                    } else {-                        emit_op(s, OP_call);-                        emit_u16(s, arg_count);-                    }-                    break;-                }-            }-            call_type = FUNC_CALL_NORMAL;-        } else if (s->token.val == '.') {-            if (next_token(s))-                return -1;-            if (s->token.val == TOK_PRIVATE_NAME) {-                /* private class field */-                if (get_prev_opcode(fd) == OP_get_super) {-                    return js_parse_error(s, "private class field forbidden after super");-                }-                emit_op(s, OP_scope_get_private_field);-                emit_atom(s, s->token.u.ident.atom);-                emit_u16(s, s->cur_func->scope_level);-            } else {-            parse_property:-                if (!token_is_ident(s->token.val)) {-                    return js_parse_error(s, "expecting field name");-                }-                if (get_prev_opcode(fd) == OP_get_super) {-                    JSValue val;-                    int ret;-                    val = JS_AtomToValue(s->ctx, s->token.u.ident.atom);-                    ret = emit_push_const(s, val, 1);-                    JS_FreeValue(s->ctx, val);-                    if (ret)-                        return -1;-                    emit_op(s, OP_get_super_value);-                } else {-                    if (has_optional_chain) {-                        optional_chain_test(s, &optional_chaining_label, 1);-                    }-                    emit_op(s, OP_get_field);-                    emit_atom(s, s->token.u.ident.atom);-                }-            }-            if (next_token(s))-                return -1;-        } else if (s->token.val == '[') {-            int prev_op;--        parse_array_access:-            prev_op = get_prev_opcode(fd);-            if (has_optional_chain) {-                optional_chain_test(s, &optional_chaining_label, 1);-            }-            if (next_token(s))-                return -1;-            if (js_parse_expr(s))-                return -1;-            if (js_parse_expect(s, ']'))-                return -1;-            if (prev_op == OP_get_super) {-                emit_op(s, OP_get_super_value);-            } else {-                emit_op(s, OP_get_array_el);-            }-        } else {-            break;-        }-    }-    if (optional_chaining_label >= 0)-        emit_label(s, optional_chaining_label);-    return 0;-}--static __exception int js_parse_delete(JSParseState *s)-{-    JSFunctionDef *fd = s->cur_func;-    JSAtom name;-    int opcode;--    if (next_token(s))-        return -1;-    if (js_parse_unary(s, -1))-        return -1;-    switch(opcode = get_prev_opcode(fd)) {-    case OP_get_field:-        {-            JSValue val;-            int ret;--            name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-            fd->byte_code.size = fd->last_opcode_pos;-            fd->last_opcode_pos = -1;-            val = JS_AtomToValue(s->ctx, name);-            ret = emit_push_const(s, val, 1);-            JS_FreeValue(s->ctx, val);-            JS_FreeAtom(s->ctx, name);-            if (ret)-                return ret;-        }-        goto do_delete;-    case OP_get_array_el:-        fd->byte_code.size = fd->last_opcode_pos;-        fd->last_opcode_pos = -1;-    do_delete:-        emit_op(s, OP_delete);-        break;-    case OP_scope_get_var:-        /* 'delete this': this is not a reference */-        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);-        if (name == JS_ATOM_this || name == JS_ATOM_new_target)-            goto ret_true;-        if (fd->js_mode & JS_MODE_STRICT) {-            return js_parse_error(s, "cannot delete a direct reference in strict mode");-        } else {-            fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var;-        }-        break;-    case OP_scope_get_private_field:-        return js_parse_error(s, "cannot delete a private class field");-    case OP_get_super_value:-        emit_op(s, OP_throw_var);-        emit_atom(s, JS_ATOM_NULL);-        emit_u8(s, JS_THROW_VAR_DELETE_SUPER);-        break;-    default:-    ret_true:-        emit_op(s, OP_drop);-        emit_op(s, OP_push_true);-        break;-    }-    return 0;-}--static __exception int js_parse_unary(JSParseState *s, int exponentiation_flag)-{-    int op;--    switch(s->token.val) {-    case '+':-    case '-':-    case '!':-    case '~':-    case TOK_VOID:-        op = s->token.val;-        if (next_token(s))-            return -1;-        if (js_parse_unary(s, -1))-            return -1;-        switch(op) {-        case '-':-            emit_op(s, OP_neg);-            break;-        case '+':-            emit_op(s, OP_plus);-            break;-        case '!':-            emit_op(s, OP_lnot);-            break;-        case '~':-            emit_op(s, OP_not);-            break;-        case TOK_VOID:-            emit_op(s, OP_drop);-            emit_op(s, OP_undefined);-            break;-        default:-            abort();-        }-        exponentiation_flag = 0;-        break;-    case TOK_DEC:-    case TOK_INC:-        {-            int opcode, op, scope, label;-            JSAtom name;-            op = s->token.val;-            if (next_token(s))-                return -1;-            /* XXX: should parse LeftHandSideExpression */-            if (js_parse_unary(s, 0))-                return -1;-            if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))-                return -1;-            emit_op(s, OP_dec + op - TOK_DEC);-            put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP,-                       FALSE);-        }-        break;-    case TOK_TYPEOF:-        {-            JSFunctionDef *fd;-            if (next_token(s))-                return -1;-            if (js_parse_unary(s, -1))-                return -1;-            /* reference access should not return an exception, so we-               patch the get_var */-            fd = s->cur_func;-            if (get_prev_opcode(fd) == OP_scope_get_var) {-                fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_var_undef;-            }-            emit_op(s, OP_typeof);-            exponentiation_flag = 0;-        }-        break;-    case TOK_DELETE:-        if (js_parse_delete(s))-            return -1;-        exponentiation_flag = 0;-        break;-    case TOK_AWAIT:-        if (!(s->cur_func->func_kind & JS_FUNC_ASYNC))-            return js_parse_error(s, "unexpected 'await' keyword");-        if (!s->cur_func->in_function_body)-            return js_parse_error(s, "await in default expression");-        if (next_token(s))-            return -1;-        if (js_parse_unary(s, -1))-            return -1;-        emit_op(s, OP_await);-        exponentiation_flag = 0;-        break;-    default:-        if (js_parse_postfix_expr(s, TRUE))-            return -1;-        if (!s->got_lf &&-            (s->token.val == TOK_DEC || s->token.val == TOK_INC)) {-            int opcode, op, scope, label;-            JSAtom name;-            op = s->token.val;-            if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))-                return -1;-            emit_op(s, OP_post_dec + op - TOK_DEC);-            put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND,-                       FALSE);-            if (next_token(s))-                return -1;        -        }-        break;-    }-    if (exponentiation_flag) {-#ifdef CONFIG_BIGNUM-        if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) {-            /* Extended exponentiation syntax rules: we extend the ES7-               grammar in order to have more intuitive semantics:-               -2**2 evaluates to -4. */-            if (!(s->cur_func->js_mode & JS_MODE_MATH)) {-                if (exponentiation_flag < 0) {-                    JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");-                    return -1;-                }-            }-            if (next_token(s))-                return -1;-            if (js_parse_unary(s, 1))-                return -1;-            emit_op(s, OP_pow);-        }-#else-        if (s->token.val == TOK_POW) {-            /* Strict ES7 exponentiation syntax rules: To solve-               conficting semantics between different implementations-               regarding the precedence of prefix operators and the-               postifx exponential, ES7 specifies that -2**2 is a-               syntax error. */-            if (exponentiation_flag < 0) {-                JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");-                return -1;-            }-            if (next_token(s))-                return -1;-            if (js_parse_unary(s, 1))-                return -1;-            emit_op(s, OP_pow);-        }-#endif-    }-    return 0;-}--static __exception int js_parse_expr_binary(JSParseState *s, int level,-                                            BOOL in_accepted)-{-    int op, opcode;--    if (level == 0) {-        return js_parse_unary(s, 1);-    }-    if (js_parse_expr_binary(s, level - 1, in_accepted))-        return -1;-    for(;;) {-        op = s->token.val;-        switch(level) {-        case 1:-            switch(op) {-            case '*':-                opcode = OP_mul;-                break;-            case '/':-                opcode = OP_div;-                break;-            case '%':-#ifdef CONFIG_BIGNUM-                if (s->cur_func->js_mode & JS_MODE_MATH)-                    opcode = OP_math_mod;-                else-#endif-                    opcode = OP_mod;-                break;-            default:-                return 0;-            }-            break;-        case 2:-            switch(op) {-            case '+':-                opcode = OP_add;-                break;-            case '-':-                opcode = OP_sub;-                break;-            default:-                return 0;-            }-            break;-        case 3:-            switch(op) {-            case TOK_SHL:-                opcode = OP_shl;-                break;-            case TOK_SAR:-                opcode = OP_sar;-                break;-            case TOK_SHR:-                opcode = OP_shr;-                break;-            default:-                return 0;-            }-            break;-        case 4:-            switch(op) {-            case '<':-                opcode = OP_lt;-                break;-            case '>':-                opcode = OP_gt;-                break;-            case TOK_LTE:-                opcode = OP_lte;-                break;-            case TOK_GTE:-                opcode = OP_gte;-                break;-            case TOK_INSTANCEOF:-                opcode = OP_instanceof;-                break;-            case TOK_IN:-                if (in_accepted) {-                    opcode = OP_in;-                } else {-                    return 0;-                }-                break;-            default:-                return 0;-            }-            break;-        case 5:-            switch(op) {-            case TOK_EQ:-                opcode = OP_eq;-                break;-            case TOK_NEQ:-                opcode = OP_neq;-                break;-            case TOK_STRICT_EQ:-                opcode = OP_strict_eq;-                break;-            case TOK_STRICT_NEQ:-                opcode = OP_strict_neq;-                break;-            default:-                return 0;-            }-            break;-        case 6:-            switch(op) {-            case '&':-                opcode = OP_and;-                break;-            default:-                return 0;-            }-            break;-        case 7:-            switch(op) {-            case '^':-                opcode = OP_xor;-                break;-            default:-                return 0;-            }-            break;-        case 8:-            switch(op) {-            case '|':-                opcode = OP_or;-                break;-            default:-                return 0;-            }-            break;-        default:-            abort();-        }-        if (next_token(s))-            return -1;-        if (js_parse_expr_binary(s, level - 1, in_accepted))-            return -1;-        emit_op(s, opcode);-    }-    return 0;-}--static __exception int js_parse_logical_and_or(JSParseState *s, int op,-                                               BOOL in_accepted)-{-    int label1;--    if (op == TOK_LAND) {-        if (js_parse_expr_binary(s, 8, in_accepted))-            return -1;-    } else {-        if (js_parse_logical_and_or(s, TOK_LAND, in_accepted))-            return -1;-    }-    if (s->token.val == op) {-        label1 = new_label(s);--        for(;;) {-            if (next_token(s))-                return -1;-            emit_op(s, OP_dup);-            emit_goto(s, op == TOK_LAND ? OP_if_false : OP_if_true, label1);-            emit_op(s, OP_drop);--            if (op == TOK_LAND) {-                if (js_parse_expr_binary(s, 8, in_accepted))-                    return -1;-            } else {-                if (js_parse_logical_and_or(s, TOK_LAND, in_accepted))-                    return -1;-            }-            if (s->token.val != op) {-                if (s->token.val == TOK_DOUBLE_QUESTION_MARK)-                    return js_parse_error(s, "cannot mix ?? with && or ||");-                break;-            }-        }--        emit_label(s, label1);-    }-    return 0;-}--static __exception int js_parse_coalesce_expr(JSParseState *s, BOOL in_accepted)-{-    int label1;-    -    if (js_parse_logical_and_or(s, TOK_LOR, in_accepted))-        return -1;-    if (s->token.val == TOK_DOUBLE_QUESTION_MARK) {-        label1 = new_label(s);-        for(;;) {-            if (next_token(s))-                return -1;-            -            emit_op(s, OP_dup);-            emit_op(s, OP_is_undefined_or_null);-            emit_goto(s, OP_if_false, label1);-            emit_op(s, OP_drop);-            -            if (js_parse_expr_binary(s, 8, in_accepted))-                return -1;-            if (s->token.val != TOK_DOUBLE_QUESTION_MARK)-                break;-        }-        emit_label(s, label1);-    }-    return 0;-}--static __exception int js_parse_cond_expr(JSParseState *s, BOOL in_accepted)-{-    int label1, label2;--    if (js_parse_coalesce_expr(s, in_accepted))-        return -1;-    if (s->token.val == '?') {-        if (next_token(s))-            return -1;-        label1 = emit_goto(s, OP_if_false, -1);--        if (js_parse_assign_expr(s, TRUE))-            return -1;-        if (js_parse_expect(s, ':'))-            return -1;--        label2 = emit_goto(s, OP_goto, -1);--        emit_label(s, label1);--        if (js_parse_assign_expr(s, in_accepted))-            return -1;--        emit_label(s, label2);-    }-    return 0;-}--static void emit_return(JSParseState *s, BOOL hasval);--static __exception int js_parse_assign_expr(JSParseState *s, BOOL in_accepted)-{-    int opcode, op, scope;-    JSAtom name0 = JS_ATOM_NULL;-    JSAtom name;--    if (s->token.val == TOK_YIELD) {-        BOOL is_star = FALSE;-        if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR))-            return js_parse_error(s, "unexpected 'yield' keyword");-        if (!s->cur_func->in_function_body)-            return js_parse_error(s, "yield in default expression");-        if (next_token(s))-            return -1;-        /* XXX: is there a better method to detect 'yield' without-           parameters ? */-        if (s->token.val != ';' && s->token.val != ')' &&-            s->token.val != ']' && s->token.val != '}' &&-            s->token.val != ',' && s->token.val != ':' && !s->got_lf) {-            if (s->token.val == '*') {-                is_star = TRUE;-                if (next_token(s))-                    return -1;-            }-            if (js_parse_assign_expr(s, in_accepted))-                return -1;-        } else {-            emit_op(s, OP_undefined);-        }-        if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {-            int label_loop, label_return, label_next;-            int label_return1, label_yield, label_throw, label_throw1;-            int label_throw2;--            if (is_star) {-                label_loop = new_label(s);-                label_yield = new_label(s);--                emit_op(s, OP_for_await_of_start);--                /* remove the catch offset (XXX: could avoid pushing back-                   undefined) */-                emit_op(s, OP_drop);-                emit_op(s, OP_undefined);--                emit_op(s, OP_undefined); /* initial value */--                emit_label(s, label_loop);-                emit_op(s, OP_async_iterator_next);-                emit_op(s, OP_await);-                emit_op(s, OP_iterator_get_value_done);-                label_next = emit_goto(s, OP_if_true, -1); /* end of loop */-                emit_op(s, OP_await);-                emit_label(s, label_yield);-                emit_op(s, OP_async_yield_star);-                emit_op(s, OP_dup);-                label_return = emit_goto(s, OP_if_true, -1);-                emit_op(s, OP_drop);-                emit_goto(s, OP_goto, label_loop);--                emit_label(s, label_return);-                emit_op(s, OP_push_i32);-                emit_u32(s, 2);-                emit_op(s, OP_strict_eq);-                label_throw = emit_goto(s, OP_if_true, -1);--                /* return handling */-                emit_op(s, OP_await);-                emit_op(s, OP_async_iterator_get);-                emit_u8(s, 0);-                label_return1 = emit_goto(s, OP_if_true, -1);-                emit_op(s, OP_await);-                emit_op(s, OP_iterator_get_value_done);-                /* XXX: the spec does not indicate that an await should be-                   performed in case done = true, but the tests assume it */-                emit_goto(s, OP_if_false, label_yield);--                emit_label(s, label_return1);-                emit_op(s, OP_nip);-                emit_op(s, OP_nip);-                emit_op(s, OP_nip);-                emit_return(s, TRUE);--                /* throw handling */-                emit_label(s, label_throw);-                emit_op(s, OP_async_iterator_get);-                emit_u8(s, 1);-                label_throw1 = emit_goto(s, OP_if_true, -1);-                emit_op(s, OP_await);-                emit_op(s, OP_iterator_get_value_done);-                emit_goto(s, OP_if_false, label_yield);-                /* XXX: the spec does not indicate that an await should be-                   performed in case done = true, but the tests assume it */-                emit_op(s, OP_await);-                emit_goto(s, OP_goto, label_next);-                /* close the iterator and throw a type error exception */-                emit_label(s, label_throw1);-                emit_op(s, OP_async_iterator_get);-                emit_u8(s, 0);-                label_throw2 = emit_goto(s, OP_if_true, -1);-                emit_op(s, OP_await);-                emit_label(s, label_throw2);-                emit_op(s, OP_async_iterator_get);-                emit_u8(s, 2); /* throw the type error exception */-                emit_op(s, OP_drop); /* never reached */--                emit_label(s, label_next);-                emit_op(s, OP_nip); /* keep the value associated with-                                       done = true */-                emit_op(s, OP_nip);-                emit_op(s, OP_nip);-            } else {-                emit_op(s, OP_await);-                emit_op(s, OP_yield);-                label_next = emit_goto(s, OP_if_false, -1);-                emit_return(s, TRUE);-                emit_label(s, label_next);-            }-        } else {-            int label_next;-            if (is_star) {-                emit_op(s, OP_for_of_start);-                emit_op(s, OP_drop);    /* drop the catch offset */-                emit_op(s, OP_yield_star);-            } else {-                emit_op(s, OP_yield);-            }-            label_next = emit_goto(s, OP_if_false, -1);-            emit_return(s, TRUE);-            emit_label(s, label_next);-        }-        return 0;-    }-    if (s->token.val == TOK_IDENT) {-        /* name0 is used to check for OP_set_name pattern, not duplicated */-        name0 = s->token.u.ident.atom;-    }-    if (js_parse_cond_expr(s, in_accepted))-        return -1;--    op = s->token.val;-    if (op == '=' || (op >= TOK_MUL_ASSIGN && op <= TOK_POW_ASSIGN)) {-        int label;-        if (next_token(s))-            return -1;-        if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)-            return -1;--        if (js_parse_assign_expr(s, in_accepted)) {-            JS_FreeAtom(s->ctx, name);-            return -1;-        }--        if (op == '=') {-            if (opcode == OP_get_ref_value && name == name0) {-                set_object_name(s, name);-            }-        } else {-            static const uint8_t assign_opcodes[] = {-                OP_mul, OP_div, OP_mod, OP_add, OP_sub,-                OP_shl, OP_sar, OP_shr, OP_and, OP_xor, OP_or,-#ifdef CONFIG_BIGNUM-                OP_pow,-#endif-                OP_pow,-            };-            op = assign_opcodes[op - TOK_MUL_ASSIGN];-#ifdef CONFIG_BIGNUM-            if (s->cur_func->js_mode & JS_MODE_MATH) {-                if (op == OP_mod)-                    op = OP_math_mod;-            }-#endif-            emit_op(s, op);-        }-        put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);-    } else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) {-        int label, label1, depth_lvalue, label2;-        -        if (next_token(s))-            return -1;-        if (get_lvalue(s, &opcode, &scope, &name, &label,-                       &depth_lvalue, TRUE, op) < 0)-            return -1;--        emit_op(s, OP_dup);-        if (op == TOK_DOUBLE_QUESTION_MARK_ASSIGN)-            emit_op(s, OP_is_undefined_or_null);-        label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false,-                           -1);-        emit_op(s, OP_drop);-        -        if (js_parse_assign_expr(s, in_accepted)) {-            JS_FreeAtom(s->ctx, name);-            return -1;-        }--        if (opcode == OP_get_ref_value && name == name0) {-            set_object_name(s, name);-        }-        -        switch(depth_lvalue) {-        case 1:-            emit_op(s, OP_insert2);-            break;-        case 2:-            emit_op(s, OP_insert3);-            break;-        case 3:-            emit_op(s, OP_insert4);-            break;-        default:-            abort();-        }--        /* XXX: we disable the OP_put_ref_value optimization by not-           using put_lvalue() otherwise depth_lvalue is not correct */-        put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH,-                   FALSE);-        label2 = emit_goto(s, OP_goto, -1);-        -        emit_label(s, label1);--        /* remove the lvalue stack entries */-        while (depth_lvalue != 0) {-            emit_op(s, OP_nip);-            depth_lvalue--;-        }--        emit_label(s, label2);-    }-    return 0;-}--static __exception int js_parse_expr2(JSParseState *s, BOOL in_accepted)-{-    BOOL comma = FALSE;-    for(;;) {-        if (js_parse_assign_expr(s, in_accepted))-            return -1;-        if (comma) {-            /* prevent get_lvalue from using the last expression-               as an lvalue. This also prevents the conversion of-               of get_var to get_ref for method lookup in function-               call inside `with` statement.-             */-            s->cur_func->last_opcode_pos = -1;-        }-        if (s->token.val != ',')-            break;-        comma = TRUE;-        if (next_token(s))-            return -1;-        emit_op(s, OP_drop);-    }-    return 0;-}--static __exception int js_parse_expr(JSParseState *s)-{-    return js_parse_expr2(s, TRUE);-}--static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,-                             JSAtom label_name,-                             int label_break, int label_cont,-                             int drop_count)-{-    be->prev = fd->top_break;-    fd->top_break = be;-    be->label_name = label_name;-    be->label_break = label_break;-    be->label_cont = label_cont;-    be->drop_count = drop_count;-    be->label_finally = -1;-    be->scope_level = fd->scope_level;-    be->has_iterator = FALSE;-}--static void pop_break_entry(JSFunctionDef *fd)-{-    BlockEnv *be;-    be = fd->top_break;-    fd->top_break = be->prev;-}--static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)-{-    BlockEnv *top;-    int i, scope_level;--    scope_level = s->cur_func->scope_level;-    top = s->cur_func->top_break;-    while (top != NULL) {-        close_scopes(s, scope_level, top->scope_level);-        scope_level = top->scope_level;-        if (is_cont &&-            top->label_cont != -1 &&-            (name == JS_ATOM_NULL || top->label_name == name)) {-            /* continue stays inside the same block */-            emit_goto(s, OP_goto, top->label_cont);-            return 0;-        }-        if (!is_cont &&-            top->label_break != -1 &&-            (name == JS_ATOM_NULL || top->label_name == name)) {-            emit_goto(s, OP_goto, top->label_break);-            return 0;-        }-        i = 0;-        if (top->has_iterator) {-            emit_op(s, OP_iterator_close);-            i += 3;-        }-        for(; i < top->drop_count; i++)-            emit_op(s, OP_drop);-        if (top->label_finally != -1) {-            /* must push dummy value to keep same stack depth */-            emit_op(s, OP_undefined);-            emit_goto(s, OP_gosub, top->label_finally);-            emit_op(s, OP_drop);-        }-        top = top->prev;-    }-    if (name == JS_ATOM_NULL) {-        if (is_cont)-            return js_parse_error(s, "continue must be inside loop");-        else-            return js_parse_error(s, "break must be inside loop or switch");-    } else {-        return js_parse_error(s, "break/continue label not found");-    }-}--/* execute the finally blocks before return */-static void emit_return(JSParseState *s, BOOL hasval)-{-    BlockEnv *top;-    int drop_count;--    drop_count = 0;-    top = s->cur_func->top_break;-    while (top != NULL) {-        /* XXX: emit the appropriate OP_leave_scope opcodes? Probably not-           required as all local variables will be closed upon returning-           from JS_CallInternal, but not in the same order. */-        if (top->has_iterator) {-            /* with 'yield', the exact number of OP_drop to emit is-               unknown, so we use a specific operation to look for-               the catch offset */-            if (!hasval) {-                emit_op(s, OP_undefined);-                hasval = TRUE;-            }-            emit_op(s, OP_iterator_close_return);-            if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {-                int label_next;-                emit_op(s, OP_async_iterator_close);-                label_next = emit_goto(s, OP_if_true, -1);-                emit_op(s, OP_await);-                emit_label(s, label_next);-                emit_op(s, OP_drop);-            } else {-                emit_op(s, OP_iterator_close);-            }-            drop_count = -3;-        }-        drop_count += top->drop_count;-        if (top->label_finally != -1) {-            while(drop_count) {-                /* must keep the stack top if hasval */-                emit_op(s, hasval ? OP_nip : OP_drop);-                drop_count--;-            }-            if (!hasval) {-                /* must push return value to keep same stack size */-                emit_op(s, OP_undefined);-                hasval = TRUE;-            }-            emit_goto(s, OP_gosub, top->label_finally);-        }-        top = top->prev;-    }-    if (s->cur_func->is_derived_class_constructor) {-        int label_return;--        /* 'this' can be uninitialized, so it may be accessed only if-           the derived class constructor does not return an object */-        if (hasval) {-            emit_op(s, OP_check_ctor_return);-            label_return = emit_goto(s, OP_if_false, -1);-            emit_op(s, OP_drop);-        } else {-            label_return = -1;-        }--        /* XXX: if this is not initialized, should throw the-           ReferenceError in the caller realm */-        emit_op(s, OP_scope_get_var);-        emit_atom(s, JS_ATOM_this);-        emit_u16(s, 0);--        emit_label(s, label_return);-        emit_op(s, OP_return);-    } else if (s->cur_func->func_kind != JS_FUNC_NORMAL) {-        if (!hasval) {-            emit_op(s, OP_undefined);-        } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {-            emit_op(s, OP_await);-        }-        emit_op(s, OP_return_async);-    } else {-        emit_op(s, hasval ? OP_return : OP_return_undef);-    }-}--#define DECL_MASK_FUNC  (1 << 0) /* allow normal function declaration */-/* ored with DECL_MASK_FUNC if function declarations are allowed with a label */-#define DECL_MASK_FUNC_WITH_LABEL (1 << 1)-#define DECL_MASK_OTHER (1 << 2) /* all other declarations */-#define DECL_MASK_ALL   (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)--static __exception int js_parse_statement_or_decl(JSParseState *s,-                                                  int decl_mask);--static __exception int js_parse_statement(JSParseState *s)-{-    return js_parse_statement_or_decl(s, 0);-}--static __exception int js_parse_block(JSParseState *s)-{-    if (js_parse_expect(s, '{'))-        return -1;-    if (s->token.val != '}') {-        push_scope(s);-        for(;;) {-            if (js_parse_statement_or_decl(s, DECL_MASK_ALL))-                return -1;-            if (s->token.val == '}')-                break;-        }-        pop_scope(s);-    }-    if (next_token(s))-        return -1;-    return 0;-}--static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,-                                    BOOL export_flag)-{-    JSContext *ctx = s->ctx;-    JSFunctionDef *fd = s->cur_func;-    JSAtom name = JS_ATOM_NULL;--    for (;;) {-        if (s->token.val == TOK_IDENT) {-            if (s->token.u.ident.is_reserved) {-                return js_parse_error_reserved_identifier(s);-            }-            name = JS_DupAtom(ctx, s->token.u.ident.atom);-            if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_CONST)) {-                js_parse_error(s, "'let' is not a valid lexical identifier");-                goto var_error;-            }-            if (next_token(s))-                goto var_error;-            if (js_define_var(s, name, tok))-                goto var_error;-            if (export_flag) {-                if (!add_export_entry(s, s->cur_func->module, name, name,-                                      JS_EXPORT_TYPE_LOCAL))-                    goto var_error;-            }--            if (s->token.val == '=') {-                if (next_token(s))-                    goto var_error;-                if (tok == TOK_VAR) {-                    /* Must make a reference for proper `with` semantics */-                    int opcode, scope, label;-                    JSAtom name1;--                    emit_op(s, OP_scope_get_var);-                    emit_atom(s, name);-                    emit_u16(s, fd->scope_level);-                    if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)-                        goto var_error;-                    if (js_parse_assign_expr(s, in_accepted)) {-                        JS_FreeAtom(ctx, name1);-                        goto var_error;-                    }-                    set_object_name(s, name);-                    put_lvalue(s, opcode, scope, name1, label,-                               PUT_LVALUE_NOKEEP, FALSE);-                } else {-                    if (js_parse_assign_expr(s, in_accepted))-                        goto var_error;-                    set_object_name(s, name);-                    emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?-                        OP_scope_put_var_init : OP_scope_put_var);-                    emit_atom(s, name);-                    emit_u16(s, fd->scope_level);-                }-            } else {-                if (tok == TOK_CONST) {-                    js_parse_error(s, "missing initializer for const variable");-                    goto var_error;-                }-                if (tok == TOK_LET) {-                    /* initialize lexical variable upon entering its scope */-                    emit_op(s, OP_undefined);-                    emit_op(s, OP_scope_put_var_init);-                    emit_atom(s, name);-                    emit_u16(s, fd->scope_level);-                }-            }-            JS_FreeAtom(ctx, name);-        } else {-            int skip_bits;-            if ((s->token.val == '[' || s->token.val == '{')-            &&  js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {-                emit_op(s, OP_undefined);-                if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))-                    return -1;-            } else {-                return js_parse_error(s, "variable name expected");-            }-        }-        if (s->token.val != ',')-            break;-        if (next_token(s))-            return -1;-    }-    return 0;-- var_error:-    JS_FreeAtom(ctx, name);-    return -1;-}--/* test if the current token is a label. Use simplistic look-ahead scanner */-static BOOL is_label(JSParseState *s)-{-    return (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&-            peek_token(s, FALSE) == ':');-}--/* test if the current token is a let keyword. Use simplistic look-ahead scanner */-static int is_let(JSParseState *s, int decl_mask)-{-    int res = FALSE;--    if (token_is_pseudo_keyword(s, JS_ATOM_let)) {-#if 1-        JSParsePos pos;-        js_parse_get_pos(s, &pos);-        for (;;) {-            if (next_token(s)) {-                res = -1;-                break;-            }-            if (s->token.val == '[') {-                /* let [ is a syntax restriction:-                   it never introduces an ExpressionStatement */-                res = TRUE;-                break;-            }-            if (s->token.val == '{' ||-                (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) ||-                s->token.val == TOK_LET ||-                s->token.val == TOK_YIELD ||-                s->token.val == TOK_AWAIT) {-                /* Check for possible ASI if not scanning for Declaration */-                /* XXX: should also check that `{` introduces a BindingPattern,-                   but Firefox does not and rejects eval("let=1;let\n{if(1)2;}") */-                if (s->last_line_num == s->token.line_num || (decl_mask & DECL_MASK_OTHER)) {-                    res = TRUE;-                    break;-                }-                break;-            }-            break;-        }-        if (js_parse_seek_token(s, &pos)) {-            res = -1;-        }-#else-        int tok = peek_token(s, TRUE);-        if (tok == '{' || tok == TOK_IDENT || peek_token(s, FALSE) == '[') {-            res = TRUE;-        }-#endif-    }-    return res;-}--/* XXX: handle IteratorClose when exiting the loop before the-   enumeration is done */-static __exception int js_parse_for_in_of(JSParseState *s, int label_name,-                                          BOOL is_async)-{-    JSContext *ctx = s->ctx;-    JSFunctionDef *fd = s->cur_func;-    JSAtom var_name;-    BOOL has_initializer, is_for_of, has_destructuring;-    int tok, tok1, opcode, scope, block_scope_level;-    int label_next, label_expr, label_cont, label_body, label_break;-    int pos_next, pos_expr;-    BlockEnv break_entry;--    has_initializer = FALSE;-    has_destructuring = FALSE;-    is_for_of = FALSE;-    block_scope_level = fd->scope_level;-    label_cont = new_label(s);-    label_body = new_label(s);-    label_break = new_label(s);-    label_next = new_label(s);--    /* create scope for the lexical variables declared in the enumeration-       expressions. XXX: Not completely correct because of weird capturing-       semantics in `for (i of o) a.push(function(){return i})` */-    push_scope(s);--    /* local for_in scope starts here so individual elements-       can be closed in statement. */-    push_break_entry(s->cur_func, &break_entry,-                     label_name, label_break, label_cont, 1);-    break_entry.scope_level = block_scope_level;--    label_expr = emit_goto(s, OP_goto, -1);--    pos_next = s->cur_func->byte_code.size;-    emit_label(s, label_next);--    tok = s->token.val;-    switch (is_let(s, DECL_MASK_OTHER)) {-    case TRUE:-        tok = TOK_LET;-        break;-    case FALSE:-        break;-    default:-        return -1;-    }-    if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {-        if (next_token(s))-            return -1;--        if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {-            if (s->token.val == '[' || s->token.val == '{') {-                if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE))-                    return -1;-                has_destructuring = TRUE;-            } else {-                return js_parse_error(s, "variable name expected");-            }-            var_name = JS_ATOM_NULL;-        } else {-            var_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            if (next_token(s)) {-                JS_FreeAtom(s->ctx, var_name);-                return -1;-            }-            if (js_define_var(s, var_name, tok)) {-                JS_FreeAtom(s->ctx, var_name);-                return -1;-            }-            emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?-                    OP_scope_put_var_init : OP_scope_put_var);-            emit_atom(s, var_name);-            emit_u16(s, fd->scope_level);-        }-    } else {-        int skip_bits;-        if ((s->token.val == '[' || s->token.val == '{')-        &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {-            if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))-                return -1;-        } else {-            int lvalue_label;-            if (js_parse_postfix_expr(s, TRUE))-                return -1;-            if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,-                           NULL, FALSE, TOK_FOR))-                return -1;-            put_lvalue(s, opcode, scope, var_name, lvalue_label,-                       PUT_LVALUE_NOKEEP_BOTTOM, FALSE);-        }-        var_name = JS_ATOM_NULL;-    }-    emit_goto(s, OP_goto, label_body);--    pos_expr = s->cur_func->byte_code.size;-    emit_label(s, label_expr);-    if (s->token.val == '=') {-        /* XXX: potential scoping issue if inside `with` statement */-        has_initializer = TRUE;-        /* parse and evaluate initializer prior to evaluating the-           object (only used with "for in" with a non lexical variable-           in non strict mode */-        if (next_token(s) || js_parse_assign_expr(s, FALSE)) {-            JS_FreeAtom(ctx, var_name);-            return -1;-        }-        if (var_name != JS_ATOM_NULL) {-            emit_op(s, OP_scope_put_var);-            emit_atom(s, var_name);-            emit_u16(s, fd->scope_level);-        }-    }-    JS_FreeAtom(ctx, var_name);--    if (token_is_pseudo_keyword(s, JS_ATOM_of)) {-        break_entry.has_iterator = is_for_of = TRUE;-        break_entry.drop_count += 2;-        if (has_initializer)-            goto initializer_error;-    } else if (s->token.val == TOK_IN) {-        if (is_async)-            return js_parse_error(s, "'for await' loop should be used with 'of'");-        if (has_initializer &&-            (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) ||-             has_destructuring)) {-        initializer_error:-            return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer",-                                  is_for_of ? "of" : "in");-        }-    } else {-        return js_parse_error(s, "expected 'of' or 'in' in for control expression");-    }-    if (next_token(s))-        return -1;-    if (is_for_of) {-        if (js_parse_assign_expr(s, TRUE))-            return -1;-    } else {-        if (js_parse_expr(s))-            return -1;-    }-    /* close the scope after having evaluated the expression so that-       the TDZ values are in the closures */-    close_scopes(s, s->cur_func->scope_level, block_scope_level);-    if (is_for_of) {-        if (is_async)-            emit_op(s, OP_for_await_of_start);-        else-            emit_op(s, OP_for_of_start);-        /* on stack: enum_rec */-    } else {-        emit_op(s, OP_for_in_start);-        /* on stack: enum_obj */-    }-    emit_goto(s, OP_goto, label_cont);--    if (js_parse_expect(s, ')'))-        return -1;--    if (OPTIMIZE) {-        /* move the `next` code here */-        DynBuf *bc = &s->cur_func->byte_code;-        int chunk_size = pos_expr - pos_next;-        int offset = bc->size - pos_next;-        int i;-        dbuf_realloc(bc, bc->size + chunk_size);-        dbuf_put(bc, bc->buf + pos_next, chunk_size);-        memset(bc->buf + pos_next, OP_nop, chunk_size);-        /* `next` part ends with a goto */-        s->cur_func->last_opcode_pos = bc->size - 5;-        /* relocate labels */-        for (i = label_cont; i < s->cur_func->label_count; i++) {-            LabelSlot *ls = &s->cur_func->label_slots[i];-            if (ls->pos >= pos_next && ls->pos < pos_expr)-                ls->pos += offset;-        }-    }--    emit_label(s, label_body);-    if (js_parse_statement(s))-        return -1;--    close_scopes(s, s->cur_func->scope_level, block_scope_level);--    emit_label(s, label_cont);-    if (is_for_of) {-        if (is_async) {-            /* call the next method */-            emit_op(s, OP_for_await_of_next);-            /* get the result of the promise */-            emit_op(s, OP_await);-            /* unwrap the value and done values */-            emit_op(s, OP_iterator_get_value_done);-        } else {-            emit_op(s, OP_for_of_next);-            emit_u8(s, 0);-        }-    } else {-        emit_op(s, OP_for_in_next);-    }-    /* on stack: enum_rec / enum_obj value bool */-    emit_goto(s, OP_if_false, label_next);-    /* drop the undefined value from for_xx_next */-    emit_op(s, OP_drop);--    emit_label(s, label_break);-    if (is_for_of) {-        /* close and drop enum_rec */-        emit_op(s, OP_iterator_close);-    } else {-        emit_op(s, OP_drop);-    }-    pop_break_entry(s->cur_func);-    pop_scope(s);-    return 0;-}--static void set_eval_ret_undefined(JSParseState *s)-{-    if (s->cur_func->eval_ret_idx >= 0) {-        emit_op(s, OP_undefined);-        emit_op(s, OP_put_loc);-        emit_u16(s, s->cur_func->eval_ret_idx);-    }-}--static __exception int js_parse_statement_or_decl(JSParseState *s,-                                                  int decl_mask)-{-    JSContext *ctx = s->ctx;-    JSAtom label_name;-    int tok;--    /* specific label handling */-    /* XXX: support multiple labels on loop statements */-    label_name = JS_ATOM_NULL;-    if (is_label(s)) {-        BlockEnv *be;--        label_name = JS_DupAtom(ctx, s->token.u.ident.atom);--        for (be = s->cur_func->top_break; be; be = be->prev) {-            if (be->label_name == label_name) {-                js_parse_error(s, "duplicate label name");-                goto fail;-            }-        }--        if (next_token(s))-            goto fail;-        if (js_parse_expect(s, ':'))-            goto fail;-        if (s->token.val != TOK_FOR-        &&  s->token.val != TOK_DO-        &&  s->token.val != TOK_WHILE) {-            /* labelled regular statement */-            int label_break, mask;-            BlockEnv break_entry;--            label_break = new_label(s);-            push_break_entry(s->cur_func, &break_entry,-                             label_name, label_break, -1, 0);-            if (!(s->cur_func->js_mode & JS_MODE_STRICT) &&-                (decl_mask & DECL_MASK_FUNC_WITH_LABEL)) {-                mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL;-            } else {-                mask = 0;-            }-            if (js_parse_statement_or_decl(s, mask))-                goto fail;-            emit_label(s, label_break);-            pop_break_entry(s->cur_func);-            goto done;-        }-    }--    switch(tok = s->token.val) {-    case '{':-        if (js_parse_block(s))-            goto fail;-        break;-    case TOK_RETURN:-        if (s->cur_func->is_eval) {-            js_parse_error(s, "return not in a function");-            goto fail;-        }-        if (next_token(s))-            goto fail;-        if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {-            if (js_parse_expr(s))-                goto fail;-            emit_return(s, TRUE);-        } else {-            emit_return(s, FALSE);-        }-        if (js_parse_expect_semi(s))-            goto fail;-        break;-    case TOK_THROW:-        if (next_token(s))-            goto fail;-        if (s->got_lf) {-            js_parse_error(s, "line terminator not allowed after throw");-            goto fail;-        }-        if (js_parse_expr(s))-            goto fail;-        emit_op(s, OP_throw);-        if (js_parse_expect_semi(s))-            goto fail;-        break;-    case TOK_LET:-    case TOK_CONST:-    haslet:-        if (!(decl_mask & DECL_MASK_OTHER)) {-            js_parse_error(s, "lexical declarations can't appear in single-statement context");-            goto fail;-        }-        /* fall thru */-    case TOK_VAR:-        if (next_token(s))-            goto fail;-        if (js_parse_var(s, TRUE, tok, FALSE))-            goto fail;-        if (js_parse_expect_semi(s))-            goto fail;-        break;-    case TOK_IF:-        {-            int label1, label2, mask;-            if (next_token(s))-                goto fail;-            /* create a new scope for `let f;if(1) function f(){}` */-            push_scope(s);-            set_eval_ret_undefined(s);-            if (js_parse_expr_paren(s))-                goto fail;-            label1 = emit_goto(s, OP_if_false, -1);-            if (s->cur_func->js_mode & JS_MODE_STRICT)-                mask = 0;-            else-                mask = DECL_MASK_FUNC; /* Annex B.3.4 */--            if (js_parse_statement_or_decl(s, mask))-                goto fail;--            if (s->token.val == TOK_ELSE) {-                label2 = emit_goto(s, OP_goto, -1);-                if (next_token(s))-                    goto fail;--                emit_label(s, label1);-                if (js_parse_statement_or_decl(s, mask))-                    goto fail;--                label1 = label2;-            }-            emit_label(s, label1);-            pop_scope(s);-        }-        break;-    case TOK_WHILE:-        {-            int label_cont, label_break;-            BlockEnv break_entry;--            label_cont = new_label(s);-            label_break = new_label(s);--            push_break_entry(s->cur_func, &break_entry,-                             label_name, label_break, label_cont, 0);--            if (next_token(s))-                goto fail;--            set_eval_ret_undefined(s);--            emit_label(s, label_cont);-            if (js_parse_expr_paren(s))-                goto fail;-            emit_goto(s, OP_if_false, label_break);--            if (js_parse_statement(s))-                goto fail;-            emit_goto(s, OP_goto, label_cont);--            emit_label(s, label_break);--            pop_break_entry(s->cur_func);-        }-        break;-    case TOK_DO:-        {-            int label_cont, label_break, label1;-            BlockEnv break_entry;--            label_cont = new_label(s);-            label_break = new_label(s);-            label1 = new_label(s);--            push_break_entry(s->cur_func, &break_entry,-                             label_name, label_break, label_cont, 0);--            if (next_token(s))-                goto fail;--            emit_label(s, label1);--            set_eval_ret_undefined(s);--            if (js_parse_statement(s))-                goto fail;--            emit_label(s, label_cont);-            if (js_parse_expect(s, TOK_WHILE))-                goto fail;-            if (js_parse_expr_paren(s))-                goto fail;-            /* Insert semicolon if missing */-            if (s->token.val == ';') {-                if (next_token(s))-                    goto fail;-            }-            emit_goto(s, OP_if_true, label1);--            emit_label(s, label_break);--            pop_break_entry(s->cur_func);-        }-        break;-    case TOK_FOR:-        {-            int label_cont, label_break, label_body, label_test;-            int pos_cont, pos_body, block_scope_level;-            BlockEnv break_entry;-            int tok, bits;-            BOOL is_async;--            if (next_token(s))-                goto fail;--            set_eval_ret_undefined(s);-            bits = 0;-            is_async = FALSE;-            if (s->token.val == '(') {-                js_parse_skip_parens_token(s, &bits, FALSE);-            } else if (s->token.val == TOK_AWAIT) {-                if (!(s->cur_func->func_kind & JS_FUNC_ASYNC)) {-                    js_parse_error(s, "for await is only valid in asynchronous functions");-                    goto fail;-                }-                is_async = TRUE;-                if (next_token(s))-                    goto fail;-            }-            if (js_parse_expect(s, '('))-                goto fail;--            if (!(bits & SKIP_HAS_SEMI)) {-                /* parse for/in or for/of */-                if (js_parse_for_in_of(s, label_name, is_async))-                    goto fail;-                break;-            }-            block_scope_level = s->cur_func->scope_level;--            /* create scope for the lexical variables declared in the initial,-               test and increment expressions */-            push_scope(s);-            /* initial expression */-            tok = s->token.val;-            if (tok != ';') {-                switch (is_let(s, DECL_MASK_OTHER)) {-                case TRUE:-                    tok = TOK_LET;-                    break;-                case FALSE:-                    break;-                default:-                    goto fail;-                }-                if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {-                    if (next_token(s))-                        goto fail;-                    if (js_parse_var(s, FALSE, tok, FALSE))-                        goto fail;-                } else {-                    if (js_parse_expr2(s, FALSE))-                        goto fail;-                    emit_op(s, OP_drop);-                }--                /* close the closures before the first iteration */-                close_scopes(s, s->cur_func->scope_level, block_scope_level);-            }-            if (js_parse_expect(s, ';'))-                goto fail;--            label_test = new_label(s);-            label_cont = new_label(s);-            label_body = new_label(s);-            label_break = new_label(s);--            push_break_entry(s->cur_func, &break_entry,-                             label_name, label_break, label_cont, 0);--            /* test expression */-            if (s->token.val == ';') {-                /* no test expression */-                label_test = label_body;-            } else {-                emit_label(s, label_test);-                if (js_parse_expr(s))-                    goto fail;-                emit_goto(s, OP_if_false, label_break);-            }-            if (js_parse_expect(s, ';'))-                goto fail;--            if (s->token.val == ')') {-                /* no end expression */-                break_entry.label_cont = label_cont = label_test;-                pos_cont = 0; /* avoid warning */-            } else {-                /* skip the end expression */-                emit_goto(s, OP_goto, label_body);--                pos_cont = s->cur_func->byte_code.size;-                emit_label(s, label_cont);-                if (js_parse_expr(s))-                    goto fail;-                emit_op(s, OP_drop);-                if (label_test != label_body)-                    emit_goto(s, OP_goto, label_test);-            }-            if (js_parse_expect(s, ')'))-                goto fail;--            pos_body = s->cur_func->byte_code.size;-            emit_label(s, label_body);-            if (js_parse_statement(s))-                goto fail;--            /* close the closures before the next iteration */-            /* XXX: check continue case */-            close_scopes(s, s->cur_func->scope_level, block_scope_level);--            if (OPTIMIZE && label_test != label_body && label_cont != label_test) {-                /* move the increment code here */-                DynBuf *bc = &s->cur_func->byte_code;-                int chunk_size = pos_body - pos_cont;-                int offset = bc->size - pos_cont;-                int i;-                dbuf_realloc(bc, bc->size + chunk_size);-                dbuf_put(bc, bc->buf + pos_cont, chunk_size);-                memset(bc->buf + pos_cont, OP_nop, chunk_size);-                /* increment part ends with a goto */-                s->cur_func->last_opcode_pos = bc->size - 5;-                /* relocate labels */-                for (i = label_cont; i < s->cur_func->label_count; i++) {-                    LabelSlot *ls = &s->cur_func->label_slots[i];-                    if (ls->pos >= pos_cont && ls->pos < pos_body)-                        ls->pos += offset;-                }-            } else {-                emit_goto(s, OP_goto, label_cont);-            }--            emit_label(s, label_break);--            pop_break_entry(s->cur_func);-            pop_scope(s);-        }-        break;-    case TOK_BREAK:-    case TOK_CONTINUE:-        {-            int is_cont = s->token.val - TOK_BREAK;-            int label;--            if (next_token(s))-                goto fail;-            if (!s->got_lf && s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)-                label = s->token.u.ident.atom;-            else-                label = JS_ATOM_NULL;-            if (emit_break(s, label, is_cont))-                goto fail;-            if (label != JS_ATOM_NULL) {-                if (next_token(s))-                    goto fail;-            }-            if (js_parse_expect_semi(s))-                goto fail;-        }-        break;-    case TOK_SWITCH:-        {-            int label_case, label_break, label1;-            int default_label_pos;-            BlockEnv break_entry;--            if (next_token(s))-                goto fail;--            set_eval_ret_undefined(s);-            if (js_parse_expr_paren(s))-                goto fail;--            push_scope(s);-            label_break = new_label(s);-            push_break_entry(s->cur_func, &break_entry,-                             label_name, label_break, -1, 1);--            if (js_parse_expect(s, '{'))-                goto fail;--            default_label_pos = -1;-            label_case = -1;-            while (s->token.val != '}') {-                if (s->token.val == TOK_CASE) {-                    label1 = -1;-                    if (label_case >= 0) {-                        /* skip the case if needed */-                        label1 = emit_goto(s, OP_goto, -1);-                    }-                    emit_label(s, label_case);-                    label_case = -1;-                    for (;;) {-                        /* parse a sequence of case clauses */-                        if (next_token(s))-                            goto fail;-                        emit_op(s, OP_dup);-                        if (js_parse_expr(s))-                            goto fail;-                        if (js_parse_expect(s, ':'))-                            goto fail;-                        emit_op(s, OP_strict_eq);-                        if (s->token.val == TOK_CASE) {-                            label1 = emit_goto(s, OP_if_true, label1);-                        } else {-                            label_case = emit_goto(s, OP_if_false, -1);-                            emit_label(s, label1);-                            break;-                        }-                    }-                } else if (s->token.val == TOK_DEFAULT) {-                    if (next_token(s))-                        goto fail;-                    if (js_parse_expect(s, ':'))-                        goto fail;-                    if (default_label_pos >= 0) {-                        js_parse_error(s, "duplicate default");-                        goto fail;-                    }-                    if (label_case < 0) {-                        /* falling thru direct from switch expression */-                        label_case = emit_goto(s, OP_goto, -1);-                    }-                    /* Emit a dummy label opcode. Label will be patched after-                       the end of the switch body. Do not use emit_label(s, 0)-                       because it would clobber label 0 address, preventing-                       proper optimizer operation.-                     */-                    emit_op(s, OP_label);-                    emit_u32(s, 0);-                    default_label_pos = s->cur_func->byte_code.size - 4;-                } else {-                    if (label_case < 0) {-                        /* falling thru direct from switch expression */-                        js_parse_error(s, "invalid switch statement");-                        goto fail;-                    }-                    if (js_parse_statement_or_decl(s, DECL_MASK_ALL))-                        goto fail;-                }-            }-            if (js_parse_expect(s, '}'))-                goto fail;-            if (default_label_pos >= 0) {-                /* Ugly patch for the the `default` label, shameful and risky */-                put_u32(s->cur_func->byte_code.buf + default_label_pos,-                        label_case);-                s->cur_func->label_slots[label_case].pos = default_label_pos + 4;-            } else {-                emit_label(s, label_case);-            }-            emit_label(s, label_break);-            emit_op(s, OP_drop); /* drop the switch expression */--            pop_break_entry(s->cur_func);-            pop_scope(s);-        }-        break;-    case TOK_TRY:-        {-            int label_catch, label_catch2, label_finally, label_end;-            JSAtom name;-            BlockEnv block_env;--            set_eval_ret_undefined(s);-            if (next_token(s))-                goto fail;-            label_catch = new_label(s);-            label_catch2 = new_label(s);-            label_finally = new_label(s);-            label_end = new_label(s);--            emit_goto(s, OP_catch, label_catch);--            push_break_entry(s->cur_func, &block_env,-                             JS_ATOM_NULL, -1, -1, 1);-            block_env.label_finally = label_finally;--            if (js_parse_block(s))-                goto fail;--            pop_break_entry(s->cur_func);--            if (js_is_live_code(s)) {-                /* drop the catch offset */-                emit_op(s, OP_drop);-                /* must push dummy value to keep same stack size */-                emit_op(s, OP_undefined);-                emit_goto(s, OP_gosub, label_finally);-                emit_op(s, OP_drop);--                emit_goto(s, OP_goto, label_end);-            }--            if (s->token.val == TOK_CATCH) {-                if (next_token(s))-                    goto fail;--                push_scope(s);  /* catch variable */-                emit_label(s, label_catch);--                if (s->token.val == '{') {-                    /* support optional-catch-binding feature */-                    emit_op(s, OP_drop);    /* pop the exception object */-                } else {-                    if (js_parse_expect(s, '('))-                        goto fail;-                    if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {-                        if (s->token.val == '[' || s->token.val == '{') {-                            /* XXX: TOK_LET is not completely correct */-                            if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE))-                                goto fail;-                        } else {-                            js_parse_error(s, "identifier expected");-                            goto fail;-                        }-                    } else {-                        name = JS_DupAtom(ctx, s->token.u.ident.atom);-                        if (next_token(s)-                        ||  js_define_var(s, name, TOK_CATCH) < 0) {-                            JS_FreeAtom(ctx, name);-                            goto fail;-                        }-                        /* store the exception value in the catch variable */-                        emit_op(s, OP_scope_put_var);-                        emit_u32(s, name);-                        emit_u16(s, s->cur_func->scope_level);-                    }-                    if (js_parse_expect(s, ')'))-                        goto fail;-                }-                /* XXX: should keep the address to nop it out if there is no finally block */-                emit_goto(s, OP_catch, label_catch2);--                push_scope(s);  /* catch block */-                push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL,-                                 -1, -1, 1);-                block_env.label_finally = label_finally;--                if (js_parse_block(s))-                    goto fail;--                pop_break_entry(s->cur_func);-                pop_scope(s);  /* catch block */-                pop_scope(s);  /* catch variable */--                if (js_is_live_code(s)) {-                    /* drop the catch2 offset */-                    emit_op(s, OP_drop);-                    /* XXX: should keep the address to nop it out if there is no finally block */-                    /* must push dummy value to keep same stack size */-                    emit_op(s, OP_undefined);-                    emit_goto(s, OP_gosub, label_finally);-                    emit_op(s, OP_drop);-                    emit_goto(s, OP_goto, label_end);-                }-                /* catch exceptions thrown in the catch block to execute the-                 * finally clause and rethrow the exception */-                emit_label(s, label_catch2);-                /* catch value is at TOS, no need to push undefined */-                emit_goto(s, OP_gosub, label_finally);-                emit_op(s, OP_throw);--            } else if (s->token.val == TOK_FINALLY) {-                /* finally without catch : execute the finally clause-                 * and rethrow the exception */-                emit_label(s, label_catch);-                /* catch value is at TOS, no need to push undefined */-                emit_goto(s, OP_gosub, label_finally);-                emit_op(s, OP_throw);-            } else {-                js_parse_error(s, "expecting catch or finally");-                goto fail;-            }-            emit_label(s, label_finally);-            if (s->token.val == TOK_FINALLY) {-                int saved_eval_ret_idx;-                if (next_token(s))-                    goto fail;-                /* on the stack: ret_value gosub_ret_value */-                push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL,-                                 -1, -1, 2);-                saved_eval_ret_idx = s->cur_func->eval_ret_idx;-                s->cur_func->eval_ret_idx = -1;-                /* 'finally' does not update eval_ret */-                if (js_parse_block(s))-                    goto fail;-                s->cur_func->eval_ret_idx = saved_eval_ret_idx;-                pop_break_entry(s->cur_func);-            }-            emit_op(s, OP_ret);-            emit_label(s, label_end);-        }-        break;-    case ';':-        /* empty statement */-        if (next_token(s))-            goto fail;-        break;-    case TOK_WITH:-        if (s->cur_func->js_mode & JS_MODE_STRICT) {-            js_parse_error(s, "invalid keyword: with");-            goto fail;-        } else {-            int with_idx;--            if (next_token(s))-                goto fail;--            if (js_parse_expr_paren(s))-                goto fail;--            push_scope(s);-            with_idx = define_var(s, s->cur_func, JS_ATOM__with_,-                                  JS_VAR_DEF_WITH);-            if (with_idx < 0)-                goto fail;-            emit_op(s, OP_to_object);-            emit_op(s, OP_put_loc);-            emit_u16(s, with_idx);--            set_eval_ret_undefined(s);-            if (js_parse_statement(s))-                goto fail;--            /* Popping scope drops lexical context for the with object variable */-            pop_scope(s);-        }-        break;-    case TOK_FUNCTION:-        /* ES6 Annex B.3.2 and B.3.3 semantics */-        if (!(decl_mask & DECL_MASK_FUNC))-            goto func_decl_error;-        if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, FALSE) == '*')-            goto func_decl_error;-        goto parse_func_var;-    case TOK_IDENT:-        if (s->token.u.ident.is_reserved) {-            js_parse_error_reserved_identifier(s);-            goto fail;-        }-        /* Determine if `let` introduces a Declaration or an ExpressionStatement */-        switch (is_let(s, decl_mask)) {-        case TRUE:-            tok = TOK_LET;-            goto haslet;-        case FALSE:-            break;-        default:-            goto fail;-        }-        if (token_is_pseudo_keyword(s, JS_ATOM_async) &&-            peek_token(s, TRUE) == TOK_FUNCTION) {-            if (!(decl_mask & DECL_MASK_OTHER)) {-            func_decl_error:-                js_parse_error(s, "function declarations can't appear in single-statement context");-                goto fail;-            }-        parse_func_var:-            if (js_parse_function_decl(s, JS_PARSE_FUNC_VAR,-                                       JS_FUNC_NORMAL, JS_ATOM_NULL,-                                       s->token.ptr, s->token.line_num))-                goto fail;-            break;-        }-        goto hasexpr;--    case TOK_CLASS:-        if (!(decl_mask & DECL_MASK_OTHER)) {-            js_parse_error(s, "class declarations can't appear in single-statement context");-            goto fail;-        }-        if (js_parse_class(s, FALSE, JS_PARSE_EXPORT_NONE))-            return -1;-        break;--    case TOK_DEBUGGER:-        /* currently no debugger, so just skip the keyword */-        if (next_token(s))-            goto fail;-        if (js_parse_expect_semi(s))-            goto fail;-        break;-        -    case TOK_ENUM:-    case TOK_EXPORT:-    case TOK_EXTENDS:-        js_unsupported_keyword(s, s->token.u.ident.atom);-        goto fail;--    default:-    hasexpr:-        if (js_parse_expr(s))-            goto fail;-        if (s->cur_func->eval_ret_idx >= 0) {-            /* store the expression value so that it can be returned-               by eval() */-            emit_op(s, OP_put_loc);-            emit_u16(s, s->cur_func->eval_ret_idx);-        } else {-            emit_op(s, OP_drop); /* drop the result */-        }-        if (js_parse_expect_semi(s))-            goto fail;-        break;-    }-done:-    JS_FreeAtom(ctx, label_name);-    return 0;-fail:-    JS_FreeAtom(ctx, label_name);-    return -1;-}--/* 'name' is freed */-static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)-{-    JSModuleDef *m;-    m = js_mallocz(ctx, sizeof(*m));-    if (!m) {-        JS_FreeAtom(ctx, name);-        return NULL;-    }-    m->header.ref_count = 1;-    m->module_name = name;-    m->module_ns = JS_UNDEFINED;-    m->func_obj = JS_UNDEFINED;-    m->eval_exception = JS_UNDEFINED;-    m->meta_obj = JS_UNDEFINED;-    list_add_tail(&m->link, &ctx->loaded_modules);-    return m;-}--static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,-                               JS_MarkFunc *mark_func)-{-    int i;--    for(i = 0; i < m->export_entries_count; i++) {-        JSExportEntry *me = &m->export_entries[i];-        if (me->export_type == JS_EXPORT_TYPE_LOCAL &&-            me->u.local.var_ref) {-            mark_func(rt, &me->u.local.var_ref->header);-        }-    }--    JS_MarkValue(rt, m->module_ns, mark_func);-    JS_MarkValue(rt, m->func_obj, mark_func);-    JS_MarkValue(rt, m->eval_exception, mark_func);-    JS_MarkValue(rt, m->meta_obj, mark_func);-}--static void js_free_module_def(JSContext *ctx, JSModuleDef *m)-{-    int i;--    JS_FreeAtom(ctx, m->module_name);--    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        JS_FreeAtom(ctx, rme->module_name);-    }-    js_free(ctx, m->req_module_entries);--    for(i = 0; i < m->export_entries_count; i++) {-        JSExportEntry *me = &m->export_entries[i];-        if (me->export_type == JS_EXPORT_TYPE_LOCAL)-            free_var_ref(ctx->rt, me->u.local.var_ref);-        JS_FreeAtom(ctx, me->export_name);-        JS_FreeAtom(ctx, me->local_name);-    }-    js_free(ctx, m->export_entries);--    js_free(ctx, m->star_export_entries);--    for(i = 0; i < m->import_entries_count; i++) {-        JSImportEntry *mi = &m->import_entries[i];-        JS_FreeAtom(ctx, mi->import_name);-    }-    js_free(ctx, m->import_entries);--    JS_FreeValue(ctx, m->module_ns);-    JS_FreeValue(ctx, m->func_obj);-    JS_FreeValue(ctx, m->eval_exception);-    JS_FreeValue(ctx, m->meta_obj);-    list_del(&m->link);-    js_free(ctx, m);-}--static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,-                                JSAtom module_name)-{-    JSReqModuleEntry *rme;-    int i;--    /* no need to add the module request if it is already present */-    for(i = 0; i < m->req_module_entries_count; i++) {-        rme = &m->req_module_entries[i];-        if (rme->module_name == module_name)-            return i;-    }--    if (js_resize_array(ctx, (void **)&m->req_module_entries,-                        sizeof(JSReqModuleEntry),-                        &m->req_module_entries_size,-                        m->req_module_entries_count + 1))-        return -1;-    rme = &m->req_module_entries[m->req_module_entries_count++];-    rme->module_name = JS_DupAtom(ctx, module_name);-    rme->module = NULL;-    return i;-}--static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,-                                        JSAtom export_name)-{-    JSExportEntry *me;-    int i;-    for(i = 0; i < m->export_entries_count; i++) {-        me = &m->export_entries[i];-        if (me->export_name == export_name)-            return me;-    }-    return NULL;-}--static JSExportEntry *add_export_entry2(JSContext *ctx,-                                        JSParseState *s, JSModuleDef *m,-                                       JSAtom local_name, JSAtom export_name,-                                       JSExportTypeEnum export_type)-{-    JSExportEntry *me;--    if (find_export_entry(ctx, m, export_name)) {-        char buf1[ATOM_GET_STR_BUF_SIZE];-        if (s) {-            js_parse_error(s, "duplicate exported name '%s'",-                           JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name));-        } else {-            JS_ThrowSyntaxErrorAtom(ctx, "duplicate exported name '%s'", export_name);-        }-        return NULL;-    }--    if (js_resize_array(ctx, (void **)&m->export_entries,-                        sizeof(JSExportEntry),-                        &m->export_entries_size,-                        m->export_entries_count + 1))-        return NULL;-    me = &m->export_entries[m->export_entries_count++];-    memset(me, 0, sizeof(*me));-    me->local_name = JS_DupAtom(ctx, local_name);-    me->export_name = JS_DupAtom(ctx, export_name);-    me->export_type = export_type;-    return me;-}--static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m,-                                       JSAtom local_name, JSAtom export_name,-                                       JSExportTypeEnum export_type)-{-    return add_export_entry2(s->ctx, s, m, local_name, export_name,-                             export_type);-}--static int add_star_export_entry(JSContext *ctx, JSModuleDef *m,-                                 int req_module_idx)-{-    JSStarExportEntry *se;--    if (js_resize_array(ctx, (void **)&m->star_export_entries,-                        sizeof(JSStarExportEntry),-                        &m->star_export_entries_size,-                        m->star_export_entries_count + 1))-        return -1;-    se = &m->star_export_entries[m->star_export_entries_count++];-    se->req_module_idx = req_module_idx;-    return 0;-}--/* create a C module */-JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,-                           JSModuleInitFunc *func)-{-    JSModuleDef *m;-    JSAtom name;-    name = JS_NewAtom(ctx, name_str);-    if (name == JS_ATOM_NULL)-        return NULL;-    m = js_new_module_def(ctx, name);-    m->init_func = func;-    return m;-}--int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name)-{-    JSExportEntry *me;-    JSAtom name;-    name = JS_NewAtom(ctx, export_name);-    if (name == JS_ATOM_NULL)-        return -1;-    me = add_export_entry2(ctx, NULL, m, JS_ATOM_NULL, name,-                           JS_EXPORT_TYPE_LOCAL);-    JS_FreeAtom(ctx, name);-    if (!me)-        return -1;-    else-        return 0;-}--int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,-                       JSValue val)-{-    JSExportEntry *me;-    JSAtom name;-    name = JS_NewAtom(ctx, export_name);-    if (name == JS_ATOM_NULL)-        goto fail;-    me = find_export_entry(ctx, m, name);-    JS_FreeAtom(ctx, name);-    if (!me)-        goto fail;-    set_value(ctx, me->u.local.var_ref->pvalue, val);-    return 0;- fail:-    JS_FreeValue(ctx, val);-    return -1;-}--void JS_SetModuleLoaderFunc(JSRuntime *rt,-                            JSModuleNormalizeFunc *module_normalize,-                            JSModuleLoaderFunc *module_loader, void *opaque)-{-    rt->module_normalize_func = module_normalize;-    rt->module_loader_func = module_loader;-    rt->module_loader_opaque = opaque;-}--/* default module filename normalizer */-static char *js_default_module_normalize_name(JSContext *ctx,-                                              const char *base_name,-                                              const char *name)-{-    char *filename, *p;-    const char *r;-    int len;--    if (name[0] != '.') {-        /* if no initial dot, the module name is not modified */-        return js_strdup(ctx, name);-    }--    p = strrchr(base_name, '/');-    if (p)-        len = p - base_name;-    else-        len = 0;--    filename = js_malloc(ctx, len + strlen(name) + 1 + 1);-    if (!filename)-        return NULL;-    memcpy(filename, base_name, len);-    filename[len] = '\0';--    /* we only normalize the leading '..' or '.' */-    r = name;-    for(;;) {-        if (r[0] == '.' && r[1] == '/') {-            r += 2;-        } else if (r[0] == '.' && r[1] == '.' && r[2] == '/') {-            /* remove the last path element of filename, except if "."-               or ".." */-            if (filename[0] == '\0')-                break;-            p = strrchr(filename, '/');-            if (!p)-                p = filename;-            else-                p++;-            if (!strcmp(p, ".") || !strcmp(p, ".."))-                break;-            if (p > filename)-                p--;-            *p = '\0';-            r += 3;-        } else {-            break;-        }-    }-    if (filename[0] != '\0')-        strcat(filename, "/");-    strcat(filename, r);-    //    printf("normalize: %s %s -> %s\n", base_name, name, filename);-    return filename;-}--static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name)-{-    struct list_head *el;-    JSModuleDef *m;-    -    /* first look at the loaded modules */-    list_for_each(el, &ctx->loaded_modules) {-        m = list_entry(el, JSModuleDef, link);-        if (m->module_name == name)-            return m;-    }-    return NULL;-}--/* return NULL in case of exception (e.g. module could not be loaded) */-static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,-                                                    const char *base_cname,-                                                    const char *cname1)-{-    JSRuntime *rt = ctx->rt;-    JSModuleDef *m;-    char *cname;-    JSAtom module_name;--    if (!rt->module_normalize_func) {-        cname = js_default_module_normalize_name(ctx, base_cname, cname1);-    } else {-        cname = rt->module_normalize_func(ctx, base_cname, cname1,-                                          rt->module_loader_opaque);-    }-    if (!cname)-        return NULL;--    module_name = JS_NewAtom(ctx, cname);-    if (module_name == JS_ATOM_NULL) {-        js_free(ctx, cname);-        return NULL;-    }--    /* first look at the loaded modules */-    m = js_find_loaded_module(ctx, module_name);-    if (m) {-        js_free(ctx, cname);-        JS_FreeAtom(ctx, module_name);-        return m;-    }--    JS_FreeAtom(ctx, module_name);--    /* load the module */-    if (!rt->module_loader_func) {-        /* XXX: use a syntax error ? */-        JS_ThrowReferenceError(ctx, "could not load module '%s'",-                               cname);-        js_free(ctx, cname);-        return NULL;-    }--    m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque);-    js_free(ctx, cname);-    return m;-}--static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,-                                                    JSAtom base_module_name,-                                                    JSAtom module_name1)-{-    const char *base_cname, *cname;-    JSModuleDef *m;-    -    base_cname = JS_AtomToCString(ctx, base_module_name);-    if (!base_cname)-        return NULL;-    cname = JS_AtomToCString(ctx, module_name1);-    if (!cname) {-        JS_FreeCString(ctx, base_cname);-        return NULL;-    }-    m = js_host_resolve_imported_module(ctx, base_cname, cname);-    JS_FreeCString(ctx, base_cname);-    JS_FreeCString(ctx, cname);-    return m;-}--typedef struct JSResolveEntry {-    JSModuleDef *module;-    JSAtom name;-} JSResolveEntry;--typedef struct JSResolveState {-    JSResolveEntry *array;-    int size;-    int count;-} JSResolveState;--static int find_resolve_entry(JSResolveState *s,-                              JSModuleDef *m, JSAtom name)-{-    int i;-    for(i = 0; i < s->count; i++) {-        JSResolveEntry *re = &s->array[i];-        if (re->module == m && re->name == name)-            return i;-    }-    return -1;-}--static int add_resolve_entry(JSContext *ctx, JSResolveState *s,-                             JSModuleDef *m, JSAtom name)-{-    JSResolveEntry *re;--    if (js_resize_array(ctx, (void **)&s->array,-                        sizeof(JSResolveEntry),-                        &s->size, s->count + 1))-        return -1;-    re = &s->array[s->count++];-    re->module = m;-    re->name = JS_DupAtom(ctx, name);-    return 0;-}--typedef enum JSResolveResultEnum {-    JS_RESOLVE_RES_EXCEPTION = -1, /* memory alloc error */-    JS_RESOLVE_RES_FOUND = 0,-    JS_RESOLVE_RES_NOT_FOUND,-    JS_RESOLVE_RES_CIRCULAR,-    JS_RESOLVE_RES_AMBIGUOUS,-} JSResolveResultEnum;--static JSResolveResultEnum js_resolve_export1(JSContext *ctx,-                                              JSModuleDef **pmodule,-                                              JSExportEntry **pme,-                                              JSModuleDef *m,-                                              JSAtom export_name,-                                              JSResolveState *s)-{-    JSExportEntry *me;--    *pmodule = NULL;-    *pme = NULL;-    if (find_resolve_entry(s, m, export_name) >= 0)-        return JS_RESOLVE_RES_CIRCULAR;-    if (add_resolve_entry(ctx, s, m, export_name) < 0)-        return JS_RESOLVE_RES_EXCEPTION;-    me = find_export_entry(ctx, m, export_name);-    if (me) {-        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-            /* local export */-            *pmodule = m;-            *pme = me;-            return JS_RESOLVE_RES_FOUND;-        } else {-            /* indirect export */-            JSModuleDef *m1;-            m1 = m->req_module_entries[me->u.req_module_idx].module;-            if (me->local_name == JS_ATOM__star_) {-                /* export ns from */-                *pmodule = m;-                *pme = me;-                return JS_RESOLVE_RES_FOUND;-            } else {-                return js_resolve_export1(ctx, pmodule, pme, m1,-                                          me->local_name, s);-            }-        }-    } else {-        if (export_name != JS_ATOM_default) {-            /* not found in direct or indirect exports: try star exports */-            int i;--            for(i = 0; i < m->star_export_entries_count; i++) {-                JSStarExportEntry *se = &m->star_export_entries[i];-                JSModuleDef *m1, *res_m;-                JSExportEntry *res_me;-                JSResolveResultEnum ret;--                m1 = m->req_module_entries[se->req_module_idx].module;-                ret = js_resolve_export1(ctx, &res_m, &res_me, m1,-                                         export_name, s);-                if (ret == JS_RESOLVE_RES_AMBIGUOUS ||-                    ret == JS_RESOLVE_RES_EXCEPTION) {-                    return ret;-                } else if (ret == JS_RESOLVE_RES_FOUND) {-                    if (*pme != NULL) {-                        if (*pmodule != res_m ||-                            res_me->local_name != (*pme)->local_name) {-                            *pmodule = NULL;-                            *pme = NULL;-                            return JS_RESOLVE_RES_AMBIGUOUS;-                        }-                    } else {-                        *pmodule = res_m;-                        *pme = res_me;-                    }-                }-            }-            if (*pme != NULL)-                return JS_RESOLVE_RES_FOUND;-        }-        return JS_RESOLVE_RES_NOT_FOUND;-    }-}--/* If the return value is JS_RESOLVE_RES_FOUND, return the module-  (*pmodule) and the corresponding local export entry-  (*pme). Otherwise return (NULL, NULL) */-static JSResolveResultEnum js_resolve_export(JSContext *ctx,-                                             JSModuleDef **pmodule,-                                             JSExportEntry **pme,-                                             JSModuleDef *m,-                                             JSAtom export_name)-{-    JSResolveState ss, *s = &ss;-    int i;-    JSResolveResultEnum ret;--    s->array = NULL;-    s->size = 0;-    s->count = 0;--    ret = js_resolve_export1(ctx, pmodule, pme, m, export_name, s);--    for(i = 0; i < s->count; i++)-        JS_FreeAtom(ctx, s->array[i].name);-    js_free(ctx, s->array);--    return ret;-}--static void js_resolve_export_throw_error(JSContext *ctx,-                                          JSResolveResultEnum res,-                                          JSModuleDef *m, JSAtom export_name)-{-    char buf1[ATOM_GET_STR_BUF_SIZE];-    char buf2[ATOM_GET_STR_BUF_SIZE];-    switch(res) {-    case JS_RESOLVE_RES_EXCEPTION:-        break;-    default:-    case JS_RESOLVE_RES_NOT_FOUND:-        JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'",-                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),-                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));-        break;-    case JS_RESOLVE_RES_CIRCULAR:-        JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'",-                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),-                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));-        break;-    case JS_RESOLVE_RES_AMBIGUOUS:-        JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous",-                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),-                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));-        break;-    }-}---typedef enum {-    EXPORTED_NAME_AMBIGUOUS,-    EXPORTED_NAME_NORMAL,-    EXPORTED_NAME_NS,-} ExportedNameEntryEnum;--typedef struct ExportedNameEntry {-    JSAtom export_name;-    ExportedNameEntryEnum export_type;-    union {-        JSExportEntry *me; /* using when the list is built */-        JSVarRef *var_ref; /* EXPORTED_NAME_NORMAL */-        JSModuleDef *module; /* for EXPORTED_NAME_NS */-    } u;-} ExportedNameEntry;--typedef struct GetExportNamesState {-    JSModuleDef **modules;-    int modules_size;-    int modules_count;--    ExportedNameEntry *exported_names;-    int exported_names_size;-    int exported_names_count;-} GetExportNamesState;--static int find_exported_name(GetExportNamesState *s, JSAtom name)-{-    int i;-    for(i = 0; i < s->exported_names_count; i++) {-        if (s->exported_names[i].export_name == name)-            return i;-    }-    return -1;-}--static __exception int get_exported_names(JSContext *ctx,-                                          GetExportNamesState *s,-                                          JSModuleDef *m, BOOL from_star)-{-    ExportedNameEntry *en;-    int i, j;--    /* check circular reference */-    for(i = 0; i < s->modules_count; i++) {-        if (s->modules[i] == m)-            return 0;-    }-    if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]),-                        &s->modules_size, s->modules_count + 1))-        return -1;-    s->modules[s->modules_count++] = m;--    for(i = 0; i < m->export_entries_count; i++) {-        JSExportEntry *me = &m->export_entries[i];-        if (from_star && me->export_name == JS_ATOM_default)-            continue;-        j = find_exported_name(s, me->export_name);-        if (j < 0) {-            if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]),-                                &s->exported_names_size,-                                s->exported_names_count + 1))-                return -1;-            en = &s->exported_names[s->exported_names_count++];-            en->export_name = me->export_name;-            /* avoid a second lookup for simple module exports */-            if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL)-                en->u.me = NULL;-            else-                en->u.me = me;-        } else {-            en = &s->exported_names[j];-            en->u.me = NULL;-        }-    }-    for(i = 0; i < m->star_export_entries_count; i++) {-        JSStarExportEntry *se = &m->star_export_entries[i];-        JSModuleDef *m1;-        m1 = m->req_module_entries[se->req_module_idx].module;-        if (get_exported_names(ctx, s, m1, TRUE))-            return -1;-    }-    return 0;-}--/* Unfortunately, the spec gives a different behavior from GetOwnProperty ! */-static int js_module_ns_has(JSContext *ctx, JSValueConst obj, JSAtom atom)-{-    return (find_own_property1(JS_VALUE_GET_OBJ(obj), atom) != NULL);-}--static const JSClassExoticMethods js_module_ns_exotic_methods = {-    .has_property = js_module_ns_has,-};--static int exported_names_cmp(const void *p1, const void *p2, void *opaque)-{-    JSContext *ctx = opaque;-    const ExportedNameEntry *me1 = p1;-    const ExportedNameEntry *me2 = p2;-    JSValue str1, str2;-    int ret;--    /* XXX: should avoid allocation memory in atom comparison */-    str1 = JS_AtomToString(ctx, me1->export_name);-    str2 = JS_AtomToString(ctx, me2->export_name);-    if (JS_IsException(str1) || JS_IsException(str2)) {-        /* XXX: raise an error ? */-        ret = 0;-    } else {-        ret = js_string_compare(ctx, JS_VALUE_GET_STRING(str1),-                                JS_VALUE_GET_STRING(str2));-    }-    JS_FreeValue(ctx, str1);-    JS_FreeValue(ctx, str2);-    return ret;-}--static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m);--static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,-                                 void *opaque)-{-    JSModuleDef *m = opaque;-    JSValue val, this_val = JS_MKPTR(JS_TAG_OBJECT, p);-    -    val = js_get_module_ns(ctx, m);-    if (JS_IsException(val))-        return -1;-    if (JS_DefinePropertyValue(ctx, this_val, atom, val,-                               JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)-        return -1;-    return 0;-}--static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)-{-    JSValue obj;-    JSObject *p;-    GetExportNamesState s_s, *s = &s_s;-    int i, ret;-    JSProperty *pr;--    obj = JS_NewObjectClass(ctx, JS_CLASS_MODULE_NS);-    if (JS_IsException(obj))-        return obj;-    p = JS_VALUE_GET_OBJ(obj);--    memset(s, 0, sizeof(*s));-    ret = get_exported_names(ctx, s, m, FALSE);-    js_free(ctx, s->modules);-    if (ret)-        goto fail;--    /* Resolve the exported names. The ambiguous exports are removed */-    for(i = 0; i < s->exported_names_count; i++) {-        ExportedNameEntry *en = &s->exported_names[i];-        JSResolveResultEnum res;-        JSExportEntry *res_me;-        JSModuleDef *res_m;--        if (en->u.me) {-            res_me = en->u.me; /* fast case: no resolution needed */-            res_m = m;-            res = JS_RESOLVE_RES_FOUND;-        } else {-            res = js_resolve_export(ctx, &res_m, &res_me, m,-                                    en->export_name);-        }-        if (res != JS_RESOLVE_RES_FOUND) {-            if (res != JS_RESOLVE_RES_AMBIGUOUS) {-                js_resolve_export_throw_error(ctx, res, m, en->export_name);-                goto fail;-            }-            en->export_type = EXPORTED_NAME_AMBIGUOUS;-        } else {-            if (res_me->local_name == JS_ATOM__star_) {-                en->export_type = EXPORTED_NAME_NS;-                en->u.module = res_m->req_module_entries[res_me->u.req_module_idx].module;-            } else {-                en->export_type = EXPORTED_NAME_NORMAL;-                if (res_me->u.local.var_ref) {-                    en->u.var_ref = res_me->u.local.var_ref;-                } else {-                    JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj);-                    p1 = JS_VALUE_GET_OBJ(res_m->func_obj);-                    en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];-                }-            }-        }-    }--    /* sort the exported names */-    rqsort(s->exported_names, s->exported_names_count,-           sizeof(s->exported_names[0]), exported_names_cmp, ctx);--    for(i = 0; i < s->exported_names_count; i++) {-        ExportedNameEntry *en = &s->exported_names[i];-        switch(en->export_type) {-        case EXPORTED_NAME_NORMAL:-            {-                JSVarRef *var_ref = en->u.var_ref;-                pr = add_property(ctx, p, en->export_name,-                                  JS_PROP_ENUMERABLE | JS_PROP_WRITABLE |-                                  JS_PROP_VARREF);-                if (!pr)-                    goto fail;-                var_ref->header.ref_count++;-                pr->u.var_ref = var_ref;-            }-            break;-        case EXPORTED_NAME_NS:-            /* the exported namespace must be created on demand */-            if (JS_DefineAutoInitProperty(ctx, obj,-                                          en->export_name,-                                          JS_AUTOINIT_ID_MODULE_NS,-                                          en->u.module, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)-                goto fail;-            break;-        default:-            break;-        }-    }--    js_free(ctx, s->exported_names);--    JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_toStringTag,-                           JS_AtomToString(ctx, JS_ATOM_Module),-                           0);--    p->extensible = FALSE;-    return obj;- fail:-    js_free(ctx, s->exported_names);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m)-{-    if (JS_IsUndefined(m->module_ns)) {-        JSValue val;-        val = js_build_module_ns(ctx, m);-        if (JS_IsException(val))-            return JS_EXCEPTION;-        m->module_ns = val;-    }-    return JS_DupValue(ctx, m->module_ns);-}--/* Load all the required modules for module 'm' */-static int js_resolve_module(JSContext *ctx, JSModuleDef *m)-{-    int i;-    JSModuleDef *m1;--    if (m->resolved)-        return 0;-#ifdef DUMP_MODULE_RESOLVE-    {-        char buf1[ATOM_GET_STR_BUF_SIZE];-        printf("resolving module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));-    }-#endif-    m->resolved = TRUE;-    /* resolve each requested module */-    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,-                                                  rme->module_name);-        if (!m1)-            return -1;-        rme->module = m1;-        /* already done in js_host_resolve_imported_module() except if-           the module was loaded with JS_EvalBinary() */-        if (js_resolve_module(ctx, m1) < 0)-            return -1;-    }-    return 0;-}--static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical)-{-    JSVarRef *var_ref;-    var_ref = js_malloc(ctx, sizeof(JSVarRef));-    if (!var_ref)-        return NULL;-    var_ref->header.ref_count = 1;-    if (is_lexical)-        var_ref->value = JS_UNINITIALIZED;-    else-        var_ref->value = JS_UNDEFINED;-    var_ref->pvalue = &var_ref->value;-    var_ref->is_detached = TRUE;-    add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);-    return var_ref;-}--/* Create the <eval> function associated with the module */-static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)-{-    JSFunctionBytecode *b;-    int i;-    JSVarRef **var_refs;-    JSValue func_obj, bfunc;-    JSObject *p;--    bfunc = m->func_obj;-    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,-                                      JS_CLASS_BYTECODE_FUNCTION);--    if (JS_IsException(func_obj))-        return -1;-    b = JS_VALUE_GET_PTR(bfunc);--    p = JS_VALUE_GET_OBJ(func_obj);-    p->u.func.function_bytecode = b;-    b->header.ref_count++;-    p->u.func.home_object = NULL;-    p->u.func.var_refs = NULL;-    if (b->closure_var_count) {-        var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count);-        if (!var_refs)-            goto fail;-        p->u.func.var_refs = var_refs;--        /* create the global variables. The other variables are-           imported from other modules */-        for(i = 0; i < b->closure_var_count; i++) {-            JSClosureVar *cv = &b->closure_var[i];-            JSVarRef *var_ref;-            if (cv->is_local) {-                var_ref = js_create_module_var(ctx, cv->is_lexical);-                if (!var_ref)-                    goto fail;-#ifdef DUMP_MODULE_RESOLVE-                printf("local %d: %p\n", i, var_ref);-#endif-                var_refs[i] = var_ref;-            }-        }-    }-    m->func_obj = func_obj;-    JS_FreeValue(ctx, bfunc);-    return 0;- fail:-    JS_FreeValue(ctx, func_obj);-    return -1;-}--/* must be done before js_instantiate_module() because of cyclic references */-static int js_create_module_function(JSContext *ctx, JSModuleDef *m)-{-    BOOL is_c_module;-    int i;-    JSVarRef *var_ref;-    -    if (m->func_created)-        return 0;--    is_c_module = (m->init_func != NULL);--    if (is_c_module) {-        /* initialize the exported variables */-        for(i = 0; i < m->export_entries_count; i++) {-            JSExportEntry *me = &m->export_entries[i];-            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-                var_ref = js_create_module_var(ctx, FALSE);-                if (!var_ref)-                    return -1;-                me->u.local.var_ref = var_ref;-            }-        }-    } else {-        if (js_create_module_bytecode_function(ctx, m))-            return -1;-    }-    m->func_created = TRUE;--    /* do it on the dependencies */-    -    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        if (js_create_module_function(ctx, rme->module) < 0)-            return -1;-    }--    return 0;-}    --    -/* Prepare a module to be executed by resolving all the imported-   variables. */-static int js_instantiate_module(JSContext *ctx, JSModuleDef *m)-{-    int i;-    JSImportEntry *mi;-    JSModuleDef *m1;-    JSVarRef **var_refs, *var_ref;-    JSObject *p;-    BOOL is_c_module;--    if (m->instantiated)-        return 0;-    m->instantiated = TRUE;--#ifdef DUMP_MODULE_RESOLVE-    {-        char buf1[ATOM_GET_STR_BUF_SIZE];-        printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));-    }-#endif--    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        if (js_instantiate_module(ctx, rme->module) < 0)-            goto fail;-    }--#ifdef DUMP_MODULE_RESOLVE-    {-        char buf1[ATOM_GET_STR_BUF_SIZE];-        printf("instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));-    }-#endif-    /* check the indirect exports */-    for(i = 0; i < m->export_entries_count; i++) {-        JSExportEntry *me = &m->export_entries[i];-        if (me->export_type == JS_EXPORT_TYPE_INDIRECT &&-            me->local_name != JS_ATOM__star_) {-            JSResolveResultEnum ret;-            JSExportEntry *res_me;-            JSModuleDef *res_m, *m1;-            m1 = m->req_module_entries[me->u.req_module_idx].module;-            ret = js_resolve_export(ctx, &res_m, &res_me, m1, me->local_name);-            if (ret != JS_RESOLVE_RES_FOUND) {-                js_resolve_export_throw_error(ctx, ret, m, me->export_name);-                goto fail;-            }-        }-    }--#ifdef DUMP_MODULE_RESOLVE-    {-        printf("exported bindings:\n");-        for(i = 0; i < m->export_entries_count; i++) {-            JSExportEntry *me = &m->export_entries[i];-            printf(" name="); print_atom(ctx, me->export_name);-            printf(" local="); print_atom(ctx, me->local_name);-            printf(" type=%d idx=%d\n", me->export_type, me->u.local.var_idx);-        }-    }-#endif--    is_c_module = (m->init_func != NULL);--    if (!is_c_module) {-        p = JS_VALUE_GET_OBJ(m->func_obj);-        var_refs = p->u.func.var_refs;--        for(i = 0; i < m->import_entries_count; i++) {-            mi = &m->import_entries[i];-#ifdef DUMP_MODULE_RESOLVE-            printf("import var_idx=%d name=", mi->var_idx);-            print_atom(ctx, mi->import_name);-            printf(": ");-#endif-            m1 = m->req_module_entries[mi->req_module_idx].module;-            if (mi->import_name == JS_ATOM__star_) {-                JSValue val;-                /* name space import */-                val = js_get_module_ns(ctx, m1);-                if (JS_IsException(val))-                    goto fail;-                set_value(ctx, &var_refs[mi->var_idx]->value, val);-#ifdef DUMP_MODULE_RESOLVE-                printf("namespace\n");-#endif-            } else {-                JSResolveResultEnum ret;-                JSExportEntry *res_me;-                JSModuleDef *res_m;-                JSObject *p1;--                ret = js_resolve_export(ctx, &res_m,-                                        &res_me, m1, mi->import_name);-                if (ret != JS_RESOLVE_RES_FOUND) {-                    js_resolve_export_throw_error(ctx, ret, m1, mi->import_name);-                    goto fail;-                }-                if (res_me->local_name == JS_ATOM__star_) {-                    JSValue val;-                    JSModuleDef *m2;-                    /* name space import from */-                    m2 = res_m->req_module_entries[res_me->u.req_module_idx].module;-                    val = js_get_module_ns(ctx, m2);-                    if (JS_IsException(val))-                        goto fail;-                    var_ref = js_create_module_var(ctx, TRUE);-                    if (!var_ref) {-                        JS_FreeValue(ctx, val);-                        goto fail;-                    }-                    set_value(ctx, &var_ref->value, val);-                    var_refs[mi->var_idx] = var_ref;-#ifdef DUMP_MODULE_RESOLVE-                    printf("namespace from\n");-#endif-                } else {-                    var_ref = res_me->u.local.var_ref;-                    if (!var_ref) {-                        p1 = JS_VALUE_GET_OBJ(res_m->func_obj);-                        var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];-                    }-                    var_ref->header.ref_count++;-                    var_refs[mi->var_idx] = var_ref;-#ifdef DUMP_MODULE_RESOLVE-                    printf("local export (var_ref=%p)\n", var_ref);-#endif-                }-            }-        }--        /* keep the exported variables in the module export entries (they-           are used when the eval function is deleted and cannot be-           initialized before in case imports are exported) */-        for(i = 0; i < m->export_entries_count; i++) {-            JSExportEntry *me = &m->export_entries[i];-            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-                var_ref = var_refs[me->u.local.var_idx];-                var_ref->header.ref_count++;-                me->u.local.var_ref = var_ref;-            }-        }-    }--#ifdef DUMP_MODULE_RESOLVE-    printf("done instantiate\n");-#endif-    return 0;- fail:-    return -1;-}--/* return JS_ATOM_NULL if the name cannot be found. Only works with-   not striped bytecode functions. */-JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)-{-    JSStackFrame *sf;-    JSFunctionBytecode *b;-    JSObject *p;-    /* XXX: currently we just use the filename of the englobing-       function. It does not work for eval(). Need to add a-       ScriptOrModule info in JSFunctionBytecode */-    sf = ctx->rt->current_stack_frame;-    if (!sf)-        return JS_ATOM_NULL;-    while (n_stack_levels-- > 0) {-        sf = sf->prev_frame;-        if (!sf)-            return JS_ATOM_NULL;-    }-    if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)-        return JS_ATOM_NULL;-    p = JS_VALUE_GET_OBJ(sf->cur_func);-    if (!js_class_has_bytecode(p->class_id))-        return JS_ATOM_NULL;-    b = p->u.func.function_bytecode;-    if (!b->has_debug)-        return JS_ATOM_NULL;-    return JS_DupAtom(ctx, b->debug.filename);-}--JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)-{-    return JS_DupAtom(ctx, m->module_name);-}--JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m)-{-    JSValue obj;-    /* allocate meta_obj only if requested to save memory */-    obj = m->meta_obj;-    if (JS_IsUndefined(obj)) {-        obj = JS_NewObjectProto(ctx, JS_NULL);-        if (JS_IsException(obj))-            return JS_EXCEPTION;-        m->meta_obj = obj;-    }-    return JS_DupValue(ctx, obj);-}--static JSValue js_import_meta(JSContext *ctx)-{-    JSAtom filename;-    JSModuleDef *m;-    -    filename = JS_GetScriptOrModuleName(ctx, 0);-    if (filename == JS_ATOM_NULL)-        goto fail;--    /* XXX: inefficient, need to add a module or script pointer in-       JSFunctionBytecode */-    m = js_find_loaded_module(ctx, filename);-    JS_FreeAtom(ctx, filename);-    if (!m) {-    fail:-        JS_ThrowTypeError(ctx, "import.meta not supported in this context");-        return JS_EXCEPTION;-    }-    return JS_GetImportMeta(ctx, m);-}--/* used by os.Worker() and import() */-JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,-                          const char *filename)-{-    JSModuleDef *m;-    JSValue ret, func_obj;-    -    m = js_host_resolve_imported_module(ctx, basename, filename);-    if (!m)-        return NULL;-    -    if (js_resolve_module(ctx, m) < 0) {-        js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);-        return NULL;-    }--    /* Evaluate the module code */-    func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));-    ret = JS_EvalFunction(ctx, func_obj);-    if (JS_IsException(ret))-        return NULL;-    JS_FreeValue(ctx, ret);-    return m;-}--static JSValue js_dynamic_import_job(JSContext *ctx,-                                     int argc, JSValueConst *argv)-{-    JSValueConst *resolving_funcs = argv;-    JSValueConst basename_val = argv[2];-    JSValueConst specifier = argv[3];-    JSModuleDef *m;-    const char *basename = NULL, *filename;-    JSValue ret, err, ns;--    if (!JS_IsString(basename_val)) {-        JS_ThrowTypeError(ctx, "no function filename for import()");-        goto exception;-    }-    basename = JS_ToCString(ctx, basename_val);-    if (!basename)-        goto exception;--    filename = JS_ToCString(ctx, specifier);-    if (!filename)-        goto exception;-                     -    m = JS_RunModule(ctx, basename, filename);-    JS_FreeCString(ctx, filename);-    if (!m)-        goto exception;--    /* return the module namespace */-    ns = js_get_module_ns(ctx, m);-    if (JS_IsException(ns))-        goto exception;--    ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,-                   1, (JSValueConst *)&ns);-    JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */-    JS_FreeValue(ctx, ns);-    JS_FreeCString(ctx, basename);-    return JS_UNDEFINED;- exception:--    err = JS_GetException(ctx);-    ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,-                   1, (JSValueConst *)&err);-    JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */-    JS_FreeValue(ctx, err);-    JS_FreeCString(ctx, basename);-    return JS_UNDEFINED;-}--static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)-{-    JSAtom basename;-    JSValue promise, resolving_funcs[2], basename_val;-    JSValueConst args[4];--    basename = JS_GetScriptOrModuleName(ctx, 0);-    if (basename == JS_ATOM_NULL)-        basename_val = JS_NULL;-    else-        basename_val = JS_AtomToValue(ctx, basename);-    JS_FreeAtom(ctx, basename);-    if (JS_IsException(basename_val))-        return basename_val;-    -    promise = JS_NewPromiseCapability(ctx, resolving_funcs);-    if (JS_IsException(promise)) {-        JS_FreeValue(ctx, basename_val);-        return promise;-    }--    args[0] = resolving_funcs[0];-    args[1] = resolving_funcs[1];-    args[2] = basename_val;-    args[3] = specifier;-    -    JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);--    JS_FreeValue(ctx, basename_val);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    return promise;-}--/* Run the <eval> function of the module and of all its requested-   modules. */-static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)-{-    JSModuleDef *m1;-    int i;-    JSValue ret_val;--    if (m->eval_mark)-        return JS_UNDEFINED; /* avoid cycles */--    if (m->evaluated) {-        /* if the module was already evaluated, rethrow the exception-           it raised */-        if (m->eval_has_exception) {-            return JS_Throw(ctx, JS_DupValue(ctx, m->eval_exception));-        } else {-            return JS_UNDEFINED;-        }-    }--    m->eval_mark = TRUE;--    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        m1 = rme->module;-        if (!m1->eval_mark) {-            ret_val = js_evaluate_module(ctx, m1);-            if (JS_IsException(ret_val)) {-                m->eval_mark = FALSE;-                return ret_val;-            }-            JS_FreeValue(ctx, ret_val);-        }-    }--    if (m->init_func) {-        /* C module init */-        if (m->init_func(ctx, m) < 0)-            ret_val = JS_EXCEPTION;-        else-            ret_val = JS_UNDEFINED;-    } else {-        ret_val = JS_CallFree(ctx, m->func_obj, JS_UNDEFINED, 0, NULL);-        m->func_obj = JS_UNDEFINED;-    }-    if (JS_IsException(ret_val)) {-        /* save the thrown exception value */-        m->eval_has_exception = TRUE;-        m->eval_exception = JS_DupValue(ctx, ctx->rt->current_exception);-    }-    m->eval_mark = FALSE;-    m->evaluated = TRUE;-    return ret_val;-}--static __exception JSAtom js_parse_from_clause(JSParseState *s)-{-    JSAtom module_name;-    if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {-        js_parse_error(s, "from clause expected");-        return JS_ATOM_NULL;-    }-    if (next_token(s))-        return JS_ATOM_NULL;-    if (s->token.val != TOK_STRING) {-        js_parse_error(s, "string expected");-        return JS_ATOM_NULL;-    }-    module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);-    if (module_name == JS_ATOM_NULL)-        return JS_ATOM_NULL;-    if (next_token(s)) {-        JS_FreeAtom(s->ctx, module_name);-        return JS_ATOM_NULL;-    }-    return module_name;-}--static __exception int js_parse_export(JSParseState *s)-{-    JSContext *ctx = s->ctx;-    JSModuleDef *m = s->cur_func->module;-    JSAtom local_name, export_name;-    int first_export, idx, i, tok;-    JSAtom module_name;-    JSExportEntry *me;--    if (next_token(s))-        return -1;--    tok = s->token.val;-    if (tok == TOK_CLASS) {-        return js_parse_class(s, FALSE, JS_PARSE_EXPORT_NAMED);-    } else if (tok == TOK_FUNCTION ||-               (token_is_pseudo_keyword(s, JS_ATOM_async) &&-                peek_token(s, TRUE) == TOK_FUNCTION)) {-        return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,-                                       JS_FUNC_NORMAL, JS_ATOM_NULL,-                                       s->token.ptr, s->token.line_num,-                                       JS_PARSE_EXPORT_NAMED, NULL);-    }--    if (next_token(s))-        return -1;--    switch(tok) {-    case '{':-        first_export = m->export_entries_count;-        while (s->token.val != '}') {-            if (!token_is_ident(s->token.val)) {-                js_parse_error(s, "identifier expected");-                return -1;-            }-            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            export_name = JS_ATOM_NULL;-            if (next_token(s))-                goto fail;-            if (token_is_pseudo_keyword(s, JS_ATOM_as)) {-                if (next_token(s))-                    goto fail;-                if (!token_is_ident(s->token.val)) {-                    js_parse_error(s, "identifier expected");-                    goto fail;-                }-                export_name = JS_DupAtom(ctx, s->token.u.ident.atom);-                if (next_token(s)) {-                fail:-                    JS_FreeAtom(ctx, local_name);-                fail1:-                    JS_FreeAtom(ctx, export_name);-                    return -1;-                }-            } else {-                export_name = JS_DupAtom(ctx, local_name);-            }-            me = add_export_entry(s, m, local_name, export_name,-                                  JS_EXPORT_TYPE_LOCAL);-            JS_FreeAtom(ctx, local_name);-            JS_FreeAtom(ctx, export_name);-            if (!me)-                return -1;-            if (s->token.val != ',')-                break;-            if (next_token(s))-                return -1;-        }-        if (js_parse_expect(s, '}'))-            return -1;-        if (token_is_pseudo_keyword(s, JS_ATOM_from)) {-            module_name = js_parse_from_clause(s);-            if (module_name == JS_ATOM_NULL)-                return -1;-            idx = add_req_module_entry(ctx, m, module_name);-            JS_FreeAtom(ctx, module_name);-            if (idx < 0)-                return -1;-            for(i = first_export; i < m->export_entries_count; i++) {-                me = &m->export_entries[i];-                me->export_type = JS_EXPORT_TYPE_INDIRECT;-                me->u.req_module_idx = idx;-            }-        }-        break;-    case '*':-        if (token_is_pseudo_keyword(s, JS_ATOM_as)) {-            /* export ns from */-            if (next_token(s))-                return -1;-            if (!token_is_ident(s->token.val)) {-                js_parse_error(s, "identifier expected");-                return -1;-            }-            export_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            if (next_token(s))-                goto fail1;-            module_name = js_parse_from_clause(s);-            if (module_name == JS_ATOM_NULL)-                goto fail1;-            idx = add_req_module_entry(ctx, m, module_name);-            JS_FreeAtom(ctx, module_name);-            if (idx < 0)-                goto fail1;-            me = add_export_entry(s, m, JS_ATOM__star_, export_name,-                                  JS_EXPORT_TYPE_INDIRECT);-            JS_FreeAtom(ctx, export_name);-            if (!me)-                return -1;-            me->u.req_module_idx = idx;-        } else {-            module_name = js_parse_from_clause(s);-            if (module_name == JS_ATOM_NULL)-                return -1;-            idx = add_req_module_entry(ctx, m, module_name);-            JS_FreeAtom(ctx, module_name);-            if (idx < 0)-                return -1;-            if (add_star_export_entry(ctx, m, idx) < 0)-                return -1;-        }-        break;-    case TOK_DEFAULT:-        if (s->token.val == TOK_CLASS) {-            return js_parse_class(s, FALSE, JS_PARSE_EXPORT_DEFAULT);-        } else if (s->token.val == TOK_FUNCTION ||-                   (token_is_pseudo_keyword(s, JS_ATOM_async) &&-                    peek_token(s, TRUE) == TOK_FUNCTION)) {-            return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,-                                           JS_FUNC_NORMAL, JS_ATOM_NULL,-                                           s->token.ptr, s->token.line_num,-                                           JS_PARSE_EXPORT_DEFAULT, NULL);-        } else {-            if (js_parse_assign_expr(s, TRUE))-                return -1;-        }-        /* set the name of anonymous functions */-        set_object_name(s, JS_ATOM_default);--        /* store the value in the _default_ global variable and export-           it */-        local_name = JS_ATOM__default_;-        if (define_var(s, s->cur_func, local_name, JS_VAR_DEF_LET) < 0)-            return -1;-        emit_op(s, OP_scope_put_var_init);-        emit_atom(s, local_name);-        emit_u16(s, 0);--        if (!add_export_entry(s, m, local_name, JS_ATOM_default,-                              JS_EXPORT_TYPE_LOCAL))-            return -1;-        break;-    case TOK_VAR:-    case TOK_LET:-    case TOK_CONST:-        return js_parse_var(s, TRUE, tok, TRUE);-    default:-        return js_parse_error(s, "invalid export syntax");-    }-    return js_parse_expect_semi(s);-}--static int add_closure_var(JSContext *ctx, JSFunctionDef *s,-                           BOOL is_local, BOOL is_arg,-                           int var_idx, JSAtom var_name,-                           BOOL is_const, BOOL is_lexical,-                           JSVarKindEnum var_kind);--static int add_import(JSParseState *s, JSModuleDef *m,-                      JSAtom local_name, JSAtom import_name)-{-    JSContext *ctx = s->ctx;-    int i, var_idx;-    JSImportEntry *mi;-    BOOL is_local;--    if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval)-        return js_parse_error(s, "invalid import binding");--    if (local_name != JS_ATOM_default) {-        for (i = 0; i < s->cur_func->closure_var_count; i++) {-            if (s->cur_func->closure_var[i].var_name == local_name)-                return js_parse_error(s, "duplicate import binding");-        }-    }--    is_local = (import_name == JS_ATOM__star_);-    var_idx = add_closure_var(ctx, s->cur_func, is_local, FALSE,-                              m->import_entries_count,-                              local_name, TRUE, TRUE, FALSE);-    if (var_idx < 0)-        return -1;-    if (js_resize_array(ctx, (void **)&m->import_entries,-                        sizeof(JSImportEntry),-                        &m->import_entries_size,-                        m->import_entries_count + 1))-        return -1;-    mi = &m->import_entries[m->import_entries_count++];-    mi->import_name = JS_DupAtom(ctx, import_name);-    mi->var_idx = var_idx;-    return 0;-}--static __exception int js_parse_import(JSParseState *s)-{-    JSContext *ctx = s->ctx;-    JSModuleDef *m = s->cur_func->module;-    JSAtom local_name, import_name, module_name;-    int first_import, i, idx;--    if (next_token(s))-        return -1;--    first_import = m->import_entries_count;-    if (s->token.val == TOK_STRING) {-        module_name = JS_ValueToAtom(ctx, s->token.u.str.str);-        if (module_name == JS_ATOM_NULL)-            return -1;-        if (next_token(s)) {-            JS_FreeAtom(ctx, module_name);-            return -1;-        }-    } else {-        if (s->token.val == TOK_IDENT) {-            if (s->token.u.ident.is_reserved) {-                return js_parse_error_reserved_identifier(s);-            }-            /* "default" import */-            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            import_name = JS_ATOM_default;-            if (next_token(s))-                goto fail;-            if (add_import(s, m, local_name, import_name))-                goto fail;-            JS_FreeAtom(ctx, local_name);--            if (s->token.val != ',')-                goto end_import_clause;-            if (next_token(s))-                return -1;-        }--        if (s->token.val == '*') {-            /* name space import */-            if (next_token(s))-                return -1;-            if (!token_is_pseudo_keyword(s, JS_ATOM_as))-                return js_parse_error(s, "expecting 'as'");-            if (next_token(s))-                return -1;-            if (!token_is_ident(s->token.val)) {-                js_parse_error(s, "identifier expected");-                return -1;-            }-            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            import_name = JS_ATOM__star_;-            if (next_token(s))-                goto fail;-            if (add_import(s, m, local_name, import_name))-                goto fail;-            JS_FreeAtom(ctx, local_name);-        } else if (s->token.val == '{') {-            if (next_token(s))-                return -1;--            while (s->token.val != '}') {-                if (!token_is_ident(s->token.val)) {-                    js_parse_error(s, "identifier expected");-                    return -1;-                }-                import_name = JS_DupAtom(ctx, s->token.u.ident.atom);-                local_name = JS_ATOM_NULL;-                if (next_token(s))-                    goto fail;-                if (token_is_pseudo_keyword(s, JS_ATOM_as)) {-                    if (next_token(s))-                        goto fail;-                    if (!token_is_ident(s->token.val)) {-                        js_parse_error(s, "identifier expected");-                        goto fail;-                    }-                    local_name = JS_DupAtom(ctx, s->token.u.ident.atom);-                    if (next_token(s)) {-                    fail:-                        JS_FreeAtom(ctx, local_name);-                        JS_FreeAtom(ctx, import_name);-                        return -1;-                    }-                } else {-                    local_name = JS_DupAtom(ctx, import_name);-                }-                if (add_import(s, m, local_name, import_name))-                    goto fail;-                JS_FreeAtom(ctx, local_name);-                JS_FreeAtom(ctx, import_name);-                if (s->token.val != ',')-                    break;-                if (next_token(s))-                    return -1;-            }-            if (js_parse_expect(s, '}'))-                return -1;-        }-    end_import_clause:-        module_name = js_parse_from_clause(s);-        if (module_name == JS_ATOM_NULL)-            return -1;-    }-    idx = add_req_module_entry(ctx, m, module_name);-    JS_FreeAtom(ctx, module_name);-    if (idx < 0)-        return -1;-    for(i = first_import; i < m->import_entries_count; i++)-        m->import_entries[i].req_module_idx = idx;--    return js_parse_expect_semi(s);-}--static __exception int js_parse_source_element(JSParseState *s)-{-    JSFunctionDef *fd = s->cur_func;-    int tok;-    -    if (s->token.val == TOK_FUNCTION ||-        (token_is_pseudo_keyword(s, JS_ATOM_async) &&-         peek_token(s, TRUE) == TOK_FUNCTION)) {-        if (js_parse_function_decl(s, JS_PARSE_FUNC_STATEMENT,-                                   JS_FUNC_NORMAL, JS_ATOM_NULL,-                                   s->token.ptr, s->token.line_num))-            return -1;-    } else if (s->token.val == TOK_EXPORT && fd->module) {-        if (js_parse_export(s))-            return -1;-    } else if (s->token.val == TOK_IMPORT && fd->module &&-               ((tok = peek_token(s, FALSE)) != '(' && tok != '.'))  {-        /* the peek_token is needed to avoid confusion with ImportCall-           (dynamic import) or import.meta */-        if (js_parse_import(s))-            return -1;-    } else {-        if (js_parse_statement_or_decl(s, DECL_MASK_ALL))-            return -1;-    }-    return 0;-}--static JSFunctionDef *js_new_function_def(JSContext *ctx,-                                          JSFunctionDef *parent,-                                          BOOL is_eval,-                                          BOOL is_func_expr,-                                          const char *filename, int line_num)-{-    JSFunctionDef *fd;--    fd = js_mallocz(ctx, sizeof(*fd));-    if (!fd)-        return NULL;--    fd->ctx = ctx;-    init_list_head(&fd->child_list);--    /* insert in parent list */-    fd->parent = parent;-    fd->parent_cpool_idx = -1;-    if (parent) {-        list_add_tail(&fd->link, &parent->child_list);-        fd->js_mode = parent->js_mode;-        fd->parent_scope_level = parent->scope_level;-    }--    fd->is_eval = is_eval;-    fd->is_func_expr = is_func_expr;-    js_dbuf_init(ctx, &fd->byte_code);-    fd->last_opcode_pos = -1;-    fd->func_name = JS_ATOM_NULL;-    fd->var_object_idx = -1;-    fd->arguments_var_idx = -1;-    fd->func_var_idx = -1;-    fd->eval_ret_idx = -1;-    fd->this_var_idx = -1;-    fd->new_target_var_idx = -1;-    fd->this_active_func_var_idx = -1;-    fd->home_object_var_idx = -1;--    /* XXX: should distinguish arg, var and var object and body scopes */-    fd->scope_level = 0;  /* 0: var/arg scope, 1:body scope */-    fd->scope_first = -1;-    fd->scopes = fd->def_scope_array;-    fd->scope_size = countof(fd->def_scope_array);-    fd->scope_count = 1;-    fd->scopes[0].first = -1;-    fd->scopes[0].parent = -1;--    fd->filename = JS_NewAtom(ctx, filename);-    fd->line_num = line_num;--    js_dbuf_init(ctx, &fd->pc2line);-    //fd->pc2line_last_line_num = line_num;-    //fd->pc2line_last_pc = 0;-    fd->last_opcode_line_num = line_num;--    return fd;-}--static void free_bytecode_atoms(JSRuntime *rt,-                                const uint8_t *bc_buf, int bc_len,-                                BOOL use_short_opcodes)-{-    int pos, len, op;-    JSAtom atom;-    const JSOpCode *oi;-    -    pos = 0;-    while (pos < bc_len) {-        op = bc_buf[pos];-        if (use_short_opcodes)-            oi = &short_opcode_info(op);-        else-            oi = &opcode_info[op];-            -        len = oi->size;-        switch(oi->fmt) {-        case OP_FMT_atom:-        case OP_FMT_atom_u8:-        case OP_FMT_atom_u16:-        case OP_FMT_atom_label_u8:-        case OP_FMT_atom_label_u16:-            atom = get_u32(bc_buf + pos + 1);-            JS_FreeAtomRT(rt, atom);-            break;-        default:-            break;-        }-        pos += len;-    }-}--static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)-{-    int i;-    struct list_head *el, *el1;--    /* free the child functions */-    list_for_each_safe(el, el1, &fd->child_list) {-        JSFunctionDef *fd1;-        fd1 = list_entry(el, JSFunctionDef, link);-        js_free_function_def(ctx, fd1);-    }--    free_bytecode_atoms(ctx->rt, fd->byte_code.buf, fd->byte_code.size,-                        fd->use_short_opcodes);-    dbuf_free(&fd->byte_code);-    js_free(ctx, fd->jump_slots);-    js_free(ctx, fd->label_slots);-    js_free(ctx, fd->line_number_slots);--    for(i = 0; i < fd->cpool_count; i++) {-        JS_FreeValue(ctx, fd->cpool[i]);-    }-    js_free(ctx, fd->cpool);--    JS_FreeAtom(ctx, fd->func_name);--    for(i = 0; i < fd->var_count; i++) {-        JS_FreeAtom(ctx, fd->vars[i].var_name);-    }-    js_free(ctx, fd->vars);-    for(i = 0; i < fd->arg_count; i++) {-        JS_FreeAtom(ctx, fd->args[i].var_name);-    }-    js_free(ctx, fd->args);--    for(i = 0; i < fd->hoisted_def_count; i++) {-        JS_FreeAtom(ctx, fd->hoisted_def[i].var_name);-    }-    js_free(ctx, fd->hoisted_def);--    for(i = 0; i < fd->closure_var_count; i++) {-        JSClosureVar *cv = &fd->closure_var[i];-        JS_FreeAtom(ctx, cv->var_name);-    }-    js_free(ctx, fd->closure_var);--    if (fd->scopes != fd->def_scope_array)-        js_free(ctx, fd->scopes);--    JS_FreeAtom(ctx, fd->filename);-    dbuf_free(&fd->pc2line);--    js_free(ctx, fd->source);--    if (fd->parent) {-        /* remove in parent list */-        list_del(&fd->link);-    }-    js_free(ctx, fd);-}--#ifdef DUMP_BYTECODE-static const char *skip_lines(const char *p, int n) {-    while (n-- > 0 && *p) {-        while (*p && *p++ != '\n')-            continue;-    }-    return p;-}--static void print_lines(const char *source, int line, int line1) {-    const char *s = source;-    const char *p = skip_lines(s, line);-    if (*p) {-        while (line++ < line1) {-            p = skip_lines(s = p, 1);-            printf(";; %.*s", (int)(p - s), s);-            if (!*p) {-                if (p[-1] != '\n')-                    printf("\n");-                break;-            }-        }-    }-}--static void dump_byte_code(JSContext *ctx, int pass,-                           const uint8_t *tab, int len,-                           const JSVarDef *args, int arg_count,-                           const JSVarDef *vars, int var_count,-                           const JSClosureVar *closure_var, int closure_var_count,-                           const JSValue *cpool, uint32_t cpool_count,-                           const char *source, int line_num,-                           const LabelSlot *label_slots, JSFunctionBytecode *b)-{-    const JSOpCode *oi;-    int pos, pos_next, op, size, idx, addr, line, line1, in_source;-    uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits));-    BOOL use_short_opcodes = (b != NULL);--    /* scan for jump targets */-    for (pos = 0; pos < len; pos = pos_next) {-        op = tab[pos];-        if (use_short_opcodes)-            oi = &short_opcode_info(op);-        else-            oi = &opcode_info[op];-        pos_next = pos + oi->size;-        if (op < OP_COUNT) {-            switch (oi->fmt) {-#if SHORT_OPCODES-            case OP_FMT_label8:-                pos++;-                addr = (int8_t)tab[pos];-                goto has_addr;-            case OP_FMT_label16:-                pos++;-                addr = (int16_t)get_u16(tab + pos);-                goto has_addr;-#endif-            case OP_FMT_atom_label_u8:-            case OP_FMT_atom_label_u16:-                pos += 4;-                /* fall thru */-            case OP_FMT_label:-            case OP_FMT_label_u16:-                pos++;-                addr = get_u32(tab + pos);-                goto has_addr;-            has_addr:-                if (pass == 1)-                    addr = label_slots[addr].pos;-                if (pass == 2)-                    addr = label_slots[addr].pos2;-                if (pass == 3)-                    addr += pos;-                if (addr >= 0 && addr < len)-                    bits[addr] |= 1;-                break;-            }-        }-    }-    in_source = 0;-    if (source) {-        /* Always print first line: needed if single line */-        print_lines(source, 0, 1);-        in_source = 1;-    }-    line1 = line = 1;-    pos = 0;-    while (pos < len) {-        op = tab[pos];-        if (source) {-            if (b) {-                line1 = find_line_num(ctx, b, pos) - line_num + 1;-            } else if (op == OP_line_num) {-                line1 = get_u32(tab + pos + 1) - line_num + 1;-            }-            if (line1 > line) {-                if (!in_source)-                    printf("\n");-                in_source = 1;-                print_lines(source, line, line1);-                line = line1;-                //bits[pos] |= 2;-            }-        }-        if (in_source)-            printf("\n");-        in_source = 0;-        if (op >= OP_COUNT) {-            printf("invalid opcode (0x%02x)\n", op);-            pos++;-            continue;-        }-        if (use_short_opcodes)-            oi = &short_opcode_info(op);-        else-            oi = &opcode_info[op];-        size = oi->size;-        if (pos + size > len) {-            printf("truncated opcode (0x%02x)\n", op);-            break;-        }-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 16)-        {-            int i, x, x0;-            x = x0 = printf("%5d ", pos);-            for (i = 0; i < size; i++) {-                if (i == 6) {-                    printf("\n%*s", x = x0, "");-                }-                x += printf(" %02X", tab[pos + i]);-            }-            printf("%*s", x0 + 20 - x, "");-        }-#endif-        if (bits[pos]) {-            printf("%5d:  ", pos);-        } else {-            printf("        ");-        }-        printf("%s", oi->name);-        pos++;-        switch(oi->fmt) {-        case OP_FMT_none_int:-            printf(" %d", op - OP_push_0);-            break;-        case OP_FMT_npopx:-            printf(" %d", op - OP_call0);-            break;-        case OP_FMT_u8:-            printf(" %u", get_u8(tab + pos));-            break;-        case OP_FMT_i8:-            printf(" %d", get_i8(tab + pos));-            break;-        case OP_FMT_u16:-        case OP_FMT_npop:-            printf(" %u", get_u16(tab + pos));-            break;-        case OP_FMT_npop_u16:-            printf(" %u,%u", get_u16(tab + pos), get_u16(tab + pos + 2));-            break;-        case OP_FMT_i16:-            printf(" %d", get_i16(tab + pos));-            break;-        case OP_FMT_i32:-            printf(" %d", get_i32(tab + pos));-            break;-        case OP_FMT_u32:-            printf(" %u", get_u32(tab + pos));-            break;-#if SHORT_OPCODES-        case OP_FMT_label8:-            addr = get_i8(tab + pos);-            goto has_addr1;-        case OP_FMT_label16:-            addr = get_i16(tab + pos);-            goto has_addr1;-#endif-        case OP_FMT_label:-            addr = get_u32(tab + pos);-            goto has_addr1;-        has_addr1:-            if (pass == 1)-                printf(" %u:%u", addr, label_slots[addr].pos);-            if (pass == 2)-                printf(" %u:%u", addr, label_slots[addr].pos2);-            if (pass == 3)-                printf(" %u", addr + pos);-            break;-        case OP_FMT_label_u16:-            addr = get_u32(tab + pos);-            if (pass == 1)-                printf(" %u:%u", addr, label_slots[addr].pos);-            if (pass == 2)-                printf(" %u:%u", addr, label_slots[addr].pos2);-            if (pass == 3)-                printf(" %u", addr + pos);-            printf(",%u", get_u16(tab + pos + 4));-            break;-#if SHORT_OPCODES-        case OP_FMT_const8:-            idx = get_u8(tab + pos);-            goto has_pool_idx;-#endif-        case OP_FMT_const:-            idx = get_u32(tab + pos);-            goto has_pool_idx;-        has_pool_idx:-            printf(" %u: ", idx);-            if (idx < cpool_count) {-                JS_DumpValue(ctx, cpool[idx]);-            }-            break;-        case OP_FMT_atom:-            printf(" ");-            print_atom(ctx, get_u32(tab + pos));-            break;-        case OP_FMT_atom_u8:-            printf(" ");-            print_atom(ctx, get_u32(tab + pos));-            printf(",%d", get_u8(tab + pos + 4));-            break;-        case OP_FMT_atom_u16:-            printf(" ");-            print_atom(ctx, get_u32(tab + pos));-            printf(",%d", get_u16(tab + pos + 4));-            break;-        case OP_FMT_atom_label_u8:-        case OP_FMT_atom_label_u16:-            printf(" ");-            print_atom(ctx, get_u32(tab + pos));-            addr = get_u32(tab + pos + 4);-            if (pass == 1)-                printf(",%u:%u", addr, label_slots[addr].pos);-            if (pass == 2)-                printf(",%u:%u", addr, label_slots[addr].pos2);-            if (pass == 3)-                printf(",%u", addr + pos + 4);-            if (oi->fmt == OP_FMT_atom_label_u8)-                printf(",%u", get_u8(tab + pos + 8));-            else-                printf(",%u", get_u16(tab + pos + 8));-            break;-        case OP_FMT_none_loc:-            idx = (op - OP_get_loc0) % 4;-            goto has_loc;-        case OP_FMT_loc8:-            idx = get_u8(tab + pos);-            goto has_loc;-        case OP_FMT_loc:-            idx = get_u16(tab + pos);-        has_loc:-            printf(" %d: ", idx);-            if (idx < var_count) {-                print_atom(ctx, vars[idx].var_name);-            }-            break;-        case OP_FMT_none_arg:-            idx = (op - OP_get_arg0) % 4;-            goto has_arg;-        case OP_FMT_arg:-            idx = get_u16(tab + pos);-        has_arg:-            printf(" %d: ", idx);-            if (idx < arg_count) {-                print_atom(ctx, args[idx].var_name);-            }-            break;-        case OP_FMT_none_var_ref:-            idx = (op - OP_get_var_ref0) % 4;-            goto has_var_ref;-        case OP_FMT_var_ref:-            idx = get_u16(tab + pos);-        has_var_ref:-            printf(" %d: ", idx);-            if (idx < closure_var_count) {-                print_atom(ctx, closure_var[idx].var_name);-            }-            break;-        default:-            break;-        }-        printf("\n");-        pos += oi->size - 1;-    }-    if (source) {-        if (!in_source)-            printf("\n");-        print_lines(source, line, INT32_MAX);-    }-    js_free(ctx, bits);-}--static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,-                                                 int line_num)-{-    const uint8_t *p_end, *p_next, *p;-    int pc, v;-    unsigned int op;--    if (len <= 0)-        return;--    printf("%5s %5s\n", "PC", "LINE");--    p = buf;-    p_end = buf + len;-    pc = 0;-    while (p < p_end) {-        op = *p++;-        if (op == 0) {-            v = unicode_from_utf8(p, p_end - p, &p_next);-            if (v < 0)-                goto fail;-            pc += v;-            p = p_next;-            v = unicode_from_utf8(p, p_end - p, &p_next);-            if (v < 0) {-            fail:-                printf("invalid pc2line encode pos=%d\n", (int)(p - buf));-                return;-            }-            if (!(v & 1)) {-                v = v >> 1;-            } else {-                v = -(v >> 1) - 1;-            }-            line_num += v;-            p = p_next;-        } else {-            op -= PC2LINE_OP_FIRST;-            pc += (op / PC2LINE_RANGE);-            line_num += (op % PC2LINE_RANGE) + PC2LINE_BASE;-        }-        printf("%5d %5d\n", pc, line_num);-    }-}--static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b)-{-    int i;-    char atom_buf[ATOM_GET_STR_BUF_SIZE];-    const char *str;--    if (b->has_debug && b->debug.filename != JS_ATOM_NULL) {-        str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->debug.filename);-        printf("%s:%d: ", str, b->debug.line_num);-    }--    str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name);-    printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str);-    if (b->js_mode) {-        printf("  mode:");-        if (b->js_mode & JS_MODE_STRICT)-            printf(" strict");-#ifdef CONFIG_BIGNUM-        if (b->js_mode & JS_MODE_MATH)-            printf(" math");-#endif-        printf("\n");-    }-    if (b->arg_count && b->vardefs) {-        printf("  args:");-        for(i = 0; i < b->arg_count; i++) {-            printf(" %s", JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf),-                                        b->vardefs[i].var_name));-        }-        printf("\n");-    }-    if (b->var_count && b->vardefs) {-        printf("  locals:\n");-        for(i = 0; i < b->var_count; i++) {-            JSVarDef *vd = &b->vardefs[b->arg_count + i];-            printf("%5d: %s %s", i,-                   vd->var_kind == JS_VAR_CATCH ? "catch" :-                   (vd->var_kind == JS_VAR_FUNCTION_DECL ||-                    vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) ? "function" :-                   vd->is_const ? "const" :-                   vd->is_lexical ? "let" : "var",-                   JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), vd->var_name));-            if (vd->scope_level)-                printf(" [level:%d next:%d]", vd->scope_level, vd->scope_next);-            printf("\n");-        }-    }-    if (b->closure_var_count) {-        printf("  closure vars:\n");-        for(i = 0; i < b->closure_var_count; i++) {-            JSClosureVar *cv = &b->closure_var[i];-            printf("%5d: %s %s:%s%d %s\n", i,-                   JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), cv->var_name),-                   cv->is_local ? "local" : "parent",-                   cv->is_arg ? "arg" : "loc", cv->var_idx,-                   cv->is_const ? "const" :-                   cv->is_lexical ? "let" : "var");-        }-    }-    printf("  stack_size: %d\n", b->stack_size);-    printf("  opcodes:\n");-    dump_byte_code(ctx, 3, b->byte_code_buf, b->byte_code_len,-                   b->vardefs, b->arg_count,-                   b->vardefs ? b->vardefs + b->arg_count : NULL, b->var_count,-                   b->closure_var, b->closure_var_count,-                   b->cpool, b->cpool_count,-                   b->has_debug ? b->debug.source : NULL,-                   b->has_debug ? b->debug.line_num : -1, NULL, b);-#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 32)-    if (b->has_debug)-        dump_pc2line(ctx, b->debug.pc2line_buf, b->debug.pc2line_len, b->debug.line_num);-#endif-    printf("\n");-}-#endif--static int add_closure_var(JSContext *ctx, JSFunctionDef *s,-                           BOOL is_local, BOOL is_arg,-                           int var_idx, JSAtom var_name,-                           BOOL is_const, BOOL is_lexical,-                           JSVarKindEnum var_kind)-{-    JSClosureVar *cv;--    /* the closure variable indexes are currently stored on 16 bits */-    if (s->closure_var_count >= JS_MAX_LOCAL_VARS) {-        JS_ThrowInternalError(ctx, "too many closure variables");-        return -1;-    }--    if (js_resize_array(ctx, (void **)&s->closure_var,-                        sizeof(s->closure_var[0]),-                        &s->closure_var_size, s->closure_var_count + 1))-        return -1;-    cv = &s->closure_var[s->closure_var_count++];-    cv->is_local = is_local;-    cv->is_arg = is_arg;-    cv->is_const = is_const;-    cv->is_lexical = is_lexical;-    cv->var_kind = var_kind;-    cv->var_idx = var_idx;-    cv->var_name = JS_DupAtom(ctx, var_name);-    return s->closure_var_count - 1;-}--static int find_closure_var(JSContext *ctx, JSFunctionDef *s,-                            JSAtom var_name)-{-    int i;-    for(i = 0; i < s->closure_var_count; i++) {-        JSClosureVar *cv = &s->closure_var[i];-        if (cv->var_name == var_name)-            return i;-    }-    return -1;-}--/* 'fd' must be a parent of 's'. Create in 's' a closure referencing a-   local variable (is_local = TRUE) or a closure (is_local = FALSE) in-   'fd' */-static int get_closure_var2(JSContext *ctx, JSFunctionDef *s,-                            JSFunctionDef *fd, BOOL is_local,-                            BOOL is_arg, int var_idx, JSAtom var_name,-                            BOOL is_const, BOOL is_lexical,-                            JSVarKindEnum var_kind)-{-    int i;--    if (fd != s->parent) {-        var_idx = get_closure_var2(ctx, s->parent, fd, is_local,-                                   is_arg, var_idx, var_name,-                                   is_const, is_lexical, var_kind);-        if (var_idx < 0)-            return -1;-        is_local = FALSE;-    }-    for(i = 0; i < s->closure_var_count; i++) {-        JSClosureVar *cv = &s->closure_var[i];-        if (cv->var_idx == var_idx && cv->is_arg == is_arg &&-            cv->is_local == is_local)-            return i;-    }-    return add_closure_var(ctx, s, is_local, is_arg, var_idx, var_name,-                           is_const, is_lexical, var_kind);-}--static int get_closure_var(JSContext *ctx, JSFunctionDef *s,-                           JSFunctionDef *fd, BOOL is_arg,-                           int var_idx, JSAtom var_name,-                           BOOL is_const, BOOL is_lexical,-                           JSVarKindEnum var_kind)-{-    return get_closure_var2(ctx, s, fd, TRUE, is_arg,-                            var_idx, var_name, is_const, is_lexical,-                            var_kind);-}--static int get_with_scope_opcode(int op)-{-    if (op == OP_scope_get_var_undef)-        return OP_with_get_var;-    else-        return OP_with_get_var + (op - OP_scope_get_var);-}--static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos)-{-    int opcode = bc_buf[pos];-    return (bc_buf[pos + 1] == OP_put_ref_value &&-            (opcode == OP_insert3 ||-             opcode == OP_perm4 ||-             opcode == OP_nop ||-             opcode == OP_rot3l));-}--static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos)-{-    int opcode = bc_buf[pos];-    return (bc_buf[pos + 1] == OP_put_ref_value &&-            (opcode == OP_insert3 ||-             opcode == OP_perm4 ||-             opcode == OP_nop ||-             opcode == OP_rot3l));-}--static int optimize_scope_make_ref(JSContext *ctx, JSFunctionDef *s,-                                   DynBuf *bc, uint8_t *bc_buf,-                                   LabelSlot *ls, int pos_next,-                                   int get_op, int var_idx)-{-    int label_pos, end_pos, pos;--    /* XXX: should optimize `loc(a) += expr` as `expr add_loc(a)`-       but only if expr does not modify `a`.-       should scan the code between pos_next and label_pos-       for operations that can potentially change `a`:-       OP_scope_make_ref(a), function calls, jumps and gosub.-     */-    /* replace the reference get/put with normal variable-       accesses */-    if (bc_buf[pos_next] == OP_get_ref_value) {-        dbuf_putc(bc, get_op);-        dbuf_put_u16(bc, var_idx);-        pos_next++;-    }-    /* remove the OP_label to make room for replacement */-    /* label should have a refcount of 0 anyway */-    /* XXX: should avoid this patch by inserting nops in phase 1 */-    label_pos = ls->pos;-    pos = label_pos - 5;-    assert(bc_buf[pos] == OP_label);-    /* label points to an instruction pair:-       - insert3 / put_ref_value-       - perm4 / put_ref_value-       - rot3l / put_ref_value-       - nop / put_ref_value-     */-    end_pos = label_pos + 2;-    if (bc_buf[label_pos] == OP_insert3)-        bc_buf[pos++] = OP_dup;-    bc_buf[pos] = get_op + 1;-    put_u16(bc_buf + pos + 1, var_idx);-    pos += 3;-    /* pad with OP_nop */-    while (pos < end_pos)-        bc_buf[pos++] = OP_nop;-    return pos_next;-}--static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,-                                          DynBuf *bc, uint8_t *bc_buf,-                                          LabelSlot *ls, int pos_next,-                                          JSAtom var_name)-{-    int label_pos, end_pos, pos, op;-    BOOL is_strict;-    is_strict = ((s->js_mode & JS_MODE_STRICT) != 0);--    /* replace the reference get/put with normal variable-       accesses */-    if (is_strict) {-        /* need to check if the variable exists before evaluating the right-           expression */-        /* XXX: need an extra OP_true if destructuring an array */-        dbuf_putc(bc, OP_check_var);-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-    } else {-        /* XXX: need 2 extra OP_true if destructuring an array */-    }-    if (bc_buf[pos_next] == OP_get_ref_value) {-        dbuf_putc(bc, OP_get_var);-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        pos_next++;-    }-    /* remove the OP_label to make room for replacement */-    /* label should have a refcount of 0 anyway */-    /* XXX: should have emitted several OP_nop to avoid this kludge */-    label_pos = ls->pos;-    pos = label_pos - 5;-    assert(bc_buf[pos] == OP_label);-    end_pos = label_pos + 2;-    op = bc_buf[label_pos];-    if (is_strict) {-        if (op != OP_nop) {-            switch(op) {-            case OP_insert3:-                op = OP_insert2;-                break;-            case OP_perm4:-                op = OP_perm3;-                break;-            case OP_rot3l:-                op = OP_swap;-                break;-            default:-                abort();-            }-            bc_buf[pos++] = op;-        }-    } else {-        if (op == OP_insert3)-            bc_buf[pos++] = OP_dup;-    }-    if (is_strict) {-        bc_buf[pos] = OP_put_var_strict;-        /* XXX: need 1 extra OP_drop if destructuring an array */-    } else {-        bc_buf[pos] = OP_put_var;-        /* XXX: need 2 extra OP_drop if destructuring an array */-    }-    put_u32(bc_buf + pos + 1, JS_DupAtom(ctx, var_name));-    pos += 5;-    /* pad with OP_nop */-    while (pos < end_pos)-        bc_buf[pos++] = OP_nop;-    return pos_next;-}--static int add_var_this(JSContext *ctx, JSFunctionDef *fd)-{-    int idx;-    idx = add_var(ctx, fd, JS_ATOM_this);-    if (idx >= 0 && fd->is_derived_class_constructor) {-        JSVarDef *vd = &fd->vars[idx];-        /* XXX: should have is_this flag or var type */-        vd->is_lexical = 1; /* used to trigger 'uninitialized' checks-                               in a derived class constructor */-    }-    return idx;-}--static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,-                               JSAtom var_name)-{-    int var_idx;--    if (!s->has_this_binding)-        return -1;-    switch(var_name) {-    case JS_ATOM_home_object:-        /* 'home_object' pseudo variable */-        var_idx = s->home_object_var_idx = add_var(ctx, s, var_name);-        break;-    case JS_ATOM_this_active_func:-        /* 'this.active_func' pseudo variable */-        var_idx = s->this_active_func_var_idx = add_var(ctx, s, var_name);-        break;-    case JS_ATOM_new_target:-        /* 'new.target' pseudo variable */-        var_idx = s->new_target_var_idx = add_var(ctx, s, var_name);-        break;-    case JS_ATOM_this:-        /* 'this' pseudo variable */-        var_idx = s->this_var_idx = add_var_this(ctx, s);-        break;-    default:-        var_idx = -1;-        break;-    }-    return var_idx;-}--/* return the position of the next opcode */-static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,-                             JSAtom var_name, int scope_level, int op,-                             DynBuf *bc, uint8_t *bc_buf,-                             LabelSlot *ls, int pos_next, int arg_valid)-{-    int idx, var_idx, is_put;-    int label_done;-    BOOL is_func_var = FALSE;-    JSFunctionDef *fd;-    JSVarDef *vd;-    BOOL is_pseudo_var;--    label_done = -1;--    /* XXX: could be simpler to use a specific function to-       resolve the pseudo variables */-    is_pseudo_var = (var_name == JS_ATOM_home_object ||-                     var_name == JS_ATOM_this_active_func ||-                     var_name == JS_ATOM_new_target ||-                     var_name == JS_ATOM_this);--    /* resolve local scoped variables */-    var_idx = -1;-    for (idx = s->scopes[scope_level].first; idx >= 0;) {-        vd = &s->vars[idx];-        if (vd->var_name == var_name) {-            if (op == OP_scope_put_var || op == OP_scope_make_ref) {-                if (vd->is_const) {-                    dbuf_putc(bc, OP_throw_var);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    dbuf_putc(bc, JS_THROW_VAR_RO);-                    goto done;-                }-                is_func_var = vd->is_func_var;-            }-            var_idx = idx;-            break;-        } else-        if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {-            dbuf_putc(bc, OP_get_loc);-            dbuf_put_u16(bc, idx);-            dbuf_putc(bc, get_with_scope_opcode(op));-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-            label_done = new_label_fd(s, label_done);-            dbuf_put_u32(bc, label_done);-            dbuf_putc(bc, 1);-            update_label(s, label_done, 1);-            s->jump_size++;-        }-        idx = vd->scope_next;-    }-    if (var_idx < 0) {-        /* XXX: scoping issues:-           should not resolve vars from the function body during argument parse,-           `arguments` and function-name should not be hidden by later vars.-         */-        var_idx = find_var(ctx, s, var_name);-        if (var_idx >= 0) {-            if (scope_level == 0-            &&  (var_idx & ARGUMENT_VAR_OFFSET)-            &&  (var_idx - ARGUMENT_VAR_OFFSET) >= arg_valid) {-                /* referring to an uninitialized argument */-                dbuf_putc(bc, OP_throw_var);-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                dbuf_putc(bc, JS_THROW_VAR_UNINITIALIZED);-            }-            if (!(var_idx & ARGUMENT_VAR_OFFSET))-                is_func_var = s->vars[var_idx].is_func_var;-        }--        if (var_idx < 0 && is_pseudo_var)-            var_idx = resolve_pseudo_var(ctx, s, var_name);--        if (var_idx < 0 && var_name == JS_ATOM_arguments &&-            s->has_arguments_binding) {-            /* 'arguments' pseudo variable */-            var_idx = add_arguments_var(ctx, s, var_name);-        }-        if (var_idx < 0 && s->is_func_expr && var_name == s->func_name) {-            /* add a new variable with the function name */-            var_idx = add_func_var(ctx, s, var_name);-            is_func_var = TRUE;-        }-    }-    if (var_idx >= 0) {-        /* OP_scope_put_var_init is only used to initialize a-           lexical variable, so it is never used in a with or var object. It-           can be used with a closure (module global variable case). */-        switch (op) {-        case OP_scope_make_ref:-            if (is_func_var) {-                /* Create a dummy object reference for the func_var */-                dbuf_putc(bc, OP_object);-                dbuf_putc(bc, OP_get_loc);-                dbuf_put_u16(bc, var_idx);-                dbuf_putc(bc, OP_define_field);-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                dbuf_putc(bc, OP_push_atom_value);-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-            } else-            if (label_done == -1 && can_opt_put_ref_value(bc_buf, ls->pos)) {-                int get_op;-                if (var_idx & ARGUMENT_VAR_OFFSET) {-                    get_op = OP_get_arg;-                    var_idx -= ARGUMENT_VAR_OFFSET;-                } else {-                    if (s->vars[var_idx].is_lexical)-                        get_op = OP_get_loc_check;-                    else-                        get_op = OP_get_loc;-                }-                pos_next = optimize_scope_make_ref(ctx, s, bc, bc_buf, ls,-                                                   pos_next, get_op, var_idx);-            } else {-                /* Create a dummy object with a named slot that is-                   a reference to the local variable */-                if (var_idx & ARGUMENT_VAR_OFFSET) {-                    dbuf_putc(bc, OP_make_arg_ref);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);-                } else {-                    dbuf_putc(bc, OP_make_loc_ref);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    dbuf_put_u16(bc, var_idx);-                }-            }-            break;-        case OP_scope_get_ref:-            dbuf_putc(bc, OP_undefined);-            /* fall thru */-        case OP_scope_get_var_undef:-        case OP_scope_get_var:-        case OP_scope_put_var:-        case OP_scope_put_var_init:-            is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init);-            if (var_idx & ARGUMENT_VAR_OFFSET) {-                dbuf_putc(bc, OP_get_arg + is_put);-                dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);-                /* XXX: should test if argument reference needs TDZ check */-            } else {-                if (is_put) {-                    if (s->vars[var_idx].is_lexical) {-                        if (op == OP_scope_put_var_init) {-                            /* 'this' can only be initialized once */-                            if (var_name == JS_ATOM_this)-                                dbuf_putc(bc, OP_put_loc_check_init);-                            else-                                dbuf_putc(bc, OP_put_loc);-                        } else {-                            dbuf_putc(bc, OP_put_loc_check);-                        }-                    } else {-                        dbuf_putc(bc, OP_put_loc);-                    }-                } else {-                    if (s->vars[var_idx].is_lexical) {-                        dbuf_putc(bc, OP_get_loc_check);-                    } else {-                        dbuf_putc(bc, OP_get_loc);-                    }-                }-                dbuf_put_u16(bc, var_idx);-            }-            break;-        case OP_scope_delete_var:-            dbuf_putc(bc, OP_push_false);-            break;-        }-        goto done;-    }-    /* check eval object */-    if (s->var_object_idx >= 0 && !is_pseudo_var) {-        dbuf_putc(bc, OP_get_loc);-        dbuf_put_u16(bc, s->var_object_idx);-        dbuf_putc(bc, get_with_scope_opcode(op));-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        label_done = new_label_fd(s, label_done);-        dbuf_put_u32(bc, label_done);-        dbuf_putc(bc, 0);-        update_label(s, label_done, 1);-        s->jump_size++;-    }-    /* check parent scopes */-    for (fd = s; fd->parent;) {-        scope_level = fd->parent_scope_level;-        fd = fd->parent;-        if (scope_level == 0) {-            /* function is defined as part of the argument parsing: hide vars-               from the function body.-               XXX: variables created from argument destructuring might need-               to be visible, should refine this method.-             */-            var_idx = find_arg(ctx, fd, var_name);-            goto check_idx;-        }-        for (idx = fd->scopes[scope_level].first; idx >= 0;) {-            vd = &fd->vars[idx];-            if (vd->var_name == var_name) {-                if (op == OP_scope_put_var || op == OP_scope_make_ref) {-                    if (vd->is_const) {-                        dbuf_putc(bc, OP_throw_var);-                        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                        dbuf_putc(bc, JS_THROW_VAR_RO);-                        goto done;-                    }-                    is_func_var = vd->is_func_var;-                }-                var_idx = idx;-                break;-            } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {-                vd->is_captured = 1;-                idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, JS_VAR_NORMAL);-                if (idx >= 0) {-                    dbuf_putc(bc, OP_get_var_ref);-                    dbuf_put_u16(bc, idx);-                    dbuf_putc(bc, get_with_scope_opcode(op));-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    label_done = new_label_fd(s, label_done);-                    dbuf_put_u32(bc, label_done);-                    dbuf_putc(bc, 1);-                    update_label(s, label_done, 1);-                    s->jump_size++;-                }-            }-            idx = vd->scope_next;-        }-        if (var_idx >= 0)-            break;--        var_idx = find_var(ctx, fd, var_name);-    check_idx:-        if (var_idx >= 0) {-            if (!(var_idx & ARGUMENT_VAR_OFFSET))-                is_func_var = fd->vars[var_idx].is_func_var;-            break;-        }-        if (is_pseudo_var) {-            var_idx = resolve_pseudo_var(ctx, fd, var_name);-            if (var_idx >= 0)-                break;-        }-        if (var_name == JS_ATOM_arguments && fd->has_arguments_binding) {-            var_idx = add_arguments_var(ctx, fd, var_name);-            break;-        }-        if (fd->is_func_expr && fd->func_name == var_name) {-            /* add a new variable with the function name */-            var_idx = add_func_var(ctx, fd, var_name);-            is_func_var = TRUE;-            break;-        }--        /* check eval object */-        if (fd->var_object_idx >= 0 && !is_pseudo_var) {-            fd->vars[fd->var_object_idx].is_captured = 1;-            idx = get_closure_var(ctx, s, fd, FALSE,-                                  fd->var_object_idx, JS_ATOM__var_,-                                  FALSE, FALSE, JS_VAR_NORMAL);-            dbuf_putc(bc, OP_get_var_ref);-            dbuf_put_u16(bc, idx);-            dbuf_putc(bc, get_with_scope_opcode(op));-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-            label_done = new_label_fd(s, label_done);-            dbuf_put_u32(bc, label_done);-            dbuf_putc(bc, 0);-            update_label(s, label_done, 1);-            s->jump_size++;-        }--        if (fd->is_eval)-            break; /* it it necessarily the top level function */-    }--    /* check direct eval scope (in the closure of the eval function-       which is necessarily at the top level) */-    if (!fd)-        fd = s;-    if (var_idx < 0 && fd->is_eval) {-        int idx1;-        for (idx1 = 0; idx1 < fd->closure_var_count; idx1++) {-            JSClosureVar *cv = &fd->closure_var[idx1];-            if (var_name == cv->var_name) {-                if (fd != s) {-                    idx = get_closure_var2(ctx, s, fd,-                                           FALSE,-                                           cv->is_arg, idx1,-                                           cv->var_name, cv->is_const,-                                           cv->is_lexical, cv->var_kind);-                } else {-                    idx = idx1;-                }-                goto has_idx;-            } else if ((cv->var_name == JS_ATOM__var_ ||-                        cv->var_name == JS_ATOM__with_) && !is_pseudo_var) {-                int is_with = (cv->var_name == JS_ATOM__with_);-                if (fd != s) {-                    idx = get_closure_var2(ctx, s, fd,-                                           FALSE,-                                           cv->is_arg, idx1,-                                           cv->var_name, FALSE, FALSE,-                                           JS_VAR_NORMAL);-                } else {-                    idx = idx1;-                }-                dbuf_putc(bc, OP_get_var_ref);-                dbuf_put_u16(bc, idx);-                dbuf_putc(bc, get_with_scope_opcode(op));-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                label_done = new_label_fd(s, label_done);-                dbuf_put_u32(bc, label_done);-                dbuf_putc(bc, is_with);-                update_label(s, label_done, 1);-                s->jump_size++;-            }-        }-    }--    if (var_idx >= 0) {-        /* find the corresponding closure variable */-        if (var_idx & ARGUMENT_VAR_OFFSET) {-            fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1;-            idx = get_closure_var(ctx, s, fd,-                                  TRUE, var_idx - ARGUMENT_VAR_OFFSET,-                                  var_name, FALSE, FALSE, JS_VAR_NORMAL);-        } else {-            fd->vars[var_idx].is_captured = 1;-            idx = get_closure_var(ctx, s, fd,-                                  FALSE, var_idx,-                                  var_name,-                                  fd->vars[var_idx].is_const,-                                  fd->vars[var_idx].is_lexical,-                                  fd->vars[var_idx].var_kind);-        }-        if (idx >= 0) {-        has_idx:-            if ((op == OP_scope_put_var || op == OP_scope_make_ref) &&-                s->closure_var[idx].is_const) {-                dbuf_putc(bc, OP_throw_var);-                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                dbuf_putc(bc, JS_THROW_VAR_RO);-                goto done;-            }-            switch (op) {-            case OP_scope_make_ref:-                if (is_func_var) {-                    /* Create a dummy object reference for the func_var */-                    dbuf_putc(bc, OP_object);-                    dbuf_putc(bc, OP_get_var_ref);-                    dbuf_put_u16(bc, idx);-                    dbuf_putc(bc, OP_define_field);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    dbuf_putc(bc, OP_push_atom_value);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                } else-                if (label_done == -1 &&-                    can_opt_put_ref_value(bc_buf, ls->pos)) {-                    int get_op;-                    if (s->closure_var[idx].is_lexical)-                        get_op = OP_get_var_ref_check;-                    else-                        get_op = OP_get_var_ref;-                    pos_next = optimize_scope_make_ref(ctx, s, bc, bc_buf, ls,-                                                       pos_next,-                                                       get_op, idx);-                } else {-                    /* Create a dummy object with a named slot that is-                       a reference to the closure variable */-                    dbuf_putc(bc, OP_make_var_ref_ref);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-                    dbuf_put_u16(bc, idx);-                }-                break;-            case OP_scope_get_ref:-                /* XXX: should create a dummy object with a named slot that is-                   a reference to the closure variable */-                dbuf_putc(bc, OP_undefined);-                /* fall thru */-            case OP_scope_get_var_undef:-            case OP_scope_get_var:-            case OP_scope_put_var:-            case OP_scope_put_var_init:-                is_put = (op == OP_scope_put_var ||-                          op == OP_scope_put_var_init);-                if (is_put) {-                    if (s->closure_var[idx].is_lexical) {-                        if (op == OP_scope_put_var_init) {-                            /* 'this' can only be initialized once */-                            if (var_name == JS_ATOM_this)-                                dbuf_putc(bc, OP_put_var_ref_check_init);-                            else-                                dbuf_putc(bc, OP_put_var_ref);-                        } else {-                            dbuf_putc(bc, OP_put_var_ref_check);-                        }-                    } else {-                        dbuf_putc(bc, OP_put_var_ref);-                    }-                } else {-                    if (s->closure_var[idx].is_lexical) {-                        dbuf_putc(bc, OP_get_var_ref_check);-                    } else {-                        dbuf_putc(bc, OP_get_var_ref);-                    }-                }-                dbuf_put_u16(bc, idx);-                break;-            case OP_scope_delete_var:-                dbuf_putc(bc, OP_push_false);-                break;-            }-            goto done;-        }-    }--    /* global variable access */--    switch (op) {-    case OP_scope_make_ref:-        if (label_done == -1 && can_opt_put_global_ref_value(bc_buf, ls->pos)) {-            pos_next = optimize_scope_make_global_ref(ctx, s, bc, bc_buf, ls,-                                                      pos_next, var_name);-        } else {-            dbuf_putc(bc, OP_make_var_ref);-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        }-        break;-    case OP_scope_get_ref:-        /* XXX: should create a dummy object with a named slot that is-           a reference to the global variable */-        dbuf_putc(bc, OP_undefined);-        dbuf_putc(bc, OP_get_var);-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        break;-    case OP_scope_get_var_undef:-    case OP_scope_get_var:-    case OP_scope_put_var:-        dbuf_putc(bc, OP_get_var_undef + (op - OP_scope_get_var_undef));-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        break;-    case OP_scope_put_var_init:-        dbuf_putc(bc, OP_put_var_init);-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        break;-    case OP_scope_delete_var:-        dbuf_putc(bc, OP_delete_var);-        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-        break;-    }-done:-    if (label_done >= 0) {-        dbuf_putc(bc, OP_label);-        dbuf_put_u32(bc, label_done);-        s->label_slots[label_done].pos2 = bc->size;-    }-    return pos_next;-}--/* search in all scopes */-static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd,-                                        JSAtom name, int scope_level)-{-    int idx;--    idx = fd->scopes[scope_level].first;-    while (idx >= 0) {-        if (fd->vars[idx].var_name == name)-            return idx;-        idx = fd->vars[idx].scope_next;-    }-    return -1;-}--static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx)-{-    /* if the field is not initialized, the error is catched when-       accessing it */-    if (is_ref) -        dbuf_putc(bc, OP_get_var_ref);-    else-        dbuf_putc(bc, OP_get_loc);-    dbuf_put_u16(bc, idx);-}--static int resolve_scope_private_field1(JSContext *ctx,-                                        BOOL *pis_ref, int *pvar_kind,-                                        JSFunctionDef *s,-                                        JSAtom var_name, int scope_level)-{-    int idx, var_kind;-    JSFunctionDef *fd;-    BOOL is_ref;-    -    fd = s;-    is_ref = FALSE;-    for(;;) {-        idx = find_private_class_field_all(ctx, fd, var_name, scope_level);-        if (idx >= 0) {-            var_kind = fd->vars[idx].var_kind;-            if (is_ref) {-                idx = get_closure_var(ctx, s, fd, FALSE, idx, var_name,-                                      TRUE, TRUE, JS_VAR_NORMAL);-                if (idx < 0)-                    return -1;-            }-            break;-        }-        scope_level = fd->parent_scope_level;-        if (!fd->parent) {-            if (fd->is_eval) {-                /* closure of the eval function (top level) */-                for (idx = 0; idx < fd->closure_var_count; idx++) {-                    JSClosureVar *cv = &fd->closure_var[idx];-                    if (cv->var_name == var_name) {-                        var_kind = cv->var_kind;-                        is_ref = TRUE;-                        if (fd != s) {-                            idx = get_closure_var2(ctx, s, fd,-                                                   FALSE,-                                                   cv->is_arg, idx,-                                                   cv->var_name, cv->is_const,-                                                   cv->is_lexical,-                                                   cv->var_kind);-                            if (idx < 0)-                                return -1;-                        }-                        goto done;-                    }-                }-            }-            /* XXX: no line number info */-            JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'",-                                    var_name);-            return -1;-        } else {-            fd = fd->parent;-        }-        is_ref = TRUE;-    }- done:-    *pis_ref = is_ref;-    *pvar_kind = var_kind;-    return idx;-}--/* return 0 if OK or -1 if the private field could not be resolved */-static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,-                                       JSAtom var_name, int scope_level, int op,-                                       DynBuf *bc)-{-    int idx, var_kind;-    BOOL is_ref;--    idx = resolve_scope_private_field1(ctx, &is_ref, &var_kind, s,-                                       var_name, scope_level);-    if (idx < 0)-        return -1;-    assert(var_kind != JS_VAR_NORMAL);-    switch (op) {-    case OP_scope_get_private_field:-    case OP_scope_get_private_field2:-        switch(var_kind) {-        case JS_VAR_PRIVATE_FIELD:-            if (op == OP_scope_get_private_field2)-                dbuf_putc(bc, OP_dup);-            get_loc_or_ref(bc, is_ref, idx);-            dbuf_putc(bc, OP_get_private_field);-            break;-        case JS_VAR_PRIVATE_METHOD:-            get_loc_or_ref(bc, is_ref, idx);-            dbuf_putc(bc, OP_check_brand);-            if (op != OP_scope_get_private_field2)-                dbuf_putc(bc, OP_nip);-            break;-        case JS_VAR_PRIVATE_GETTER:-        case JS_VAR_PRIVATE_GETTER_SETTER:-            if (op == OP_scope_get_private_field2)-                dbuf_putc(bc, OP_dup);-            get_loc_or_ref(bc, is_ref, idx);-            dbuf_putc(bc, OP_check_brand);-            dbuf_putc(bc, OP_call_method);-            dbuf_put_u16(bc, 0);-            break;-        case JS_VAR_PRIVATE_SETTER:-            /* XXX: add clearer error message */-            dbuf_putc(bc, OP_throw_var);-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-            dbuf_putc(bc, JS_THROW_VAR_RO);-            break;-        default:-            abort();-        }-        break;-    case OP_scope_put_private_field:-        switch(var_kind) {-        case JS_VAR_PRIVATE_FIELD:-            get_loc_or_ref(bc, is_ref, idx);-            dbuf_putc(bc, OP_put_private_field);-            break;-        case JS_VAR_PRIVATE_METHOD:-        case JS_VAR_PRIVATE_GETTER:-            /* XXX: add clearer error message */-            dbuf_putc(bc, OP_throw_var);-            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));-            dbuf_putc(bc, JS_THROW_VAR_RO);-            break;-        case JS_VAR_PRIVATE_SETTER:-        case JS_VAR_PRIVATE_GETTER_SETTER:-            {-                JSAtom setter_name = get_private_setter_name(ctx, var_name);-                if (setter_name == JS_ATOM_NULL)-                    return -1;-                idx = resolve_scope_private_field1(ctx, &is_ref,-                                                   &var_kind, s,-                                                   setter_name, scope_level);-                JS_FreeAtom(ctx, setter_name);-                if (idx < 0)-                    return -1;-                assert(var_kind == JS_VAR_PRIVATE_SETTER);-                get_loc_or_ref(bc, is_ref, idx);-                dbuf_putc(bc, OP_swap);-                /* obj func value */-                dbuf_putc(bc, OP_rot3r);-                /* value obj func */-                dbuf_putc(bc, OP_check_brand);-                dbuf_putc(bc, OP_rot3l);-                /* obj func value */-                dbuf_putc(bc, OP_call_method);-                dbuf_put_u16(bc, 1);-            }-            break;-        default:-            abort();-        }-        break;-    default:-        abort();-    }-    return 0;-}--static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s,-                                         int scope_level)-{-    int idx;-    JSVarDef *vd;--    for (idx = s->scopes[scope_level].first; idx >= 0;) {-        vd = &s->vars[idx];-        vd->is_captured = 1;-        idx = vd->scope_next;-    }-}--static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)-{-    JSFunctionDef *fd;-    JSVarDef *vd;-    int i, scope_level, scope_idx;-    BOOL has_arguments_binding, has_this_binding;--    /* in non strict mode, variables are created in the caller's-       environment object */-    if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) {-        s->var_object_idx = add_var(ctx, s, JS_ATOM__var_);-    }--    /* eval can potentially use 'arguments' so we must define it */-    has_this_binding = s->has_this_binding;-    if (has_this_binding) {-        if (s->this_var_idx < 0)-            s->this_var_idx = add_var_this(ctx, s);-        if (s->new_target_var_idx < 0)-            s->new_target_var_idx = add_var(ctx, s, JS_ATOM_new_target);-        if (s->is_derived_class_constructor && s->this_active_func_var_idx < 0)-            s->this_active_func_var_idx = add_var(ctx, s, JS_ATOM_this_active_func);-        if (s->has_home_object && s->home_object_var_idx < 0)-            s->home_object_var_idx = add_var(ctx, s, JS_ATOM_home_object);-    }-    has_arguments_binding = s->has_arguments_binding;-    if (has_arguments_binding)-        add_arguments_var(ctx, s, JS_ATOM_arguments);-    if (s->is_func_expr && s->func_name != JS_ATOM_NULL)-        add_func_var(ctx, s, s->func_name);--    /* eval can use all the variables of the enclosing functions, so-       they must be all put in the closure. The closure variables are-       ordered by scope. It works only because no closure are created-       before. */-    assert(s->is_eval || s->closure_var_count == 0);--    /* XXX: inefficient, but eval performance is less critical */-    fd = s;-    for(;;) {-        scope_level = fd->parent_scope_level;-        fd = fd->parent;-        if (!fd)-            break;-        scope_idx = fd->scopes[scope_level].first;-        /* add 'this' if it was not previously added */-        if (!has_this_binding && fd->has_this_binding) {-            if (fd->this_var_idx < 0)-                fd->this_var_idx = add_var_this(ctx, fd);-            if (fd->new_target_var_idx < 0)-                fd->new_target_var_idx = add_var(ctx, fd, JS_ATOM_new_target);-            if (fd->is_derived_class_constructor && fd->this_active_func_var_idx < 0)-                fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func);-            if (fd->has_home_object && fd->home_object_var_idx < 0)-                fd->home_object_var_idx = add_var(ctx, fd, JS_ATOM_home_object);-            has_this_binding = TRUE;-        }-        /* add 'arguments' if it was not previously added */-        if (!has_arguments_binding && fd->has_arguments_binding) {-            add_arguments_var(ctx, fd, JS_ATOM_arguments);-            has_arguments_binding = TRUE;-        }-        /* add function name */-        if (fd->is_func_expr && fd->func_name != JS_ATOM_NULL)-            add_func_var(ctx, fd, fd->func_name);--        /* add lexical variables */-        while (scope_idx >= 0) {-            vd = &fd->vars[scope_idx];-            vd->is_captured = 1;-            get_closure_var(ctx, s, fd, FALSE, scope_idx,-                            vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind);-            scope_idx = vd->scope_next;-        }-        /* add unscoped variables */-        for(i = 0; i < fd->arg_count; i++) {-            vd = &fd->args[i];-            if (vd->var_name != JS_ATOM_NULL) {-                get_closure_var(ctx, s, fd,-                                TRUE, i, vd->var_name, FALSE, FALSE,-                                JS_VAR_NORMAL);-            }-        }-        for(i = 0; i < fd->var_count; i++) {-            vd = &fd->vars[i];-            /* do not close top level last result */-            if (vd->scope_level == 0 &&-                vd->var_name != JS_ATOM__ret_ &&-                vd->var_name != JS_ATOM_NULL) {-                get_closure_var(ctx, s, fd,-                                FALSE, i, vd->var_name, FALSE, FALSE,-                                JS_VAR_NORMAL);-            }-        }-        if (fd->is_eval) {-            int idx;-            /* add direct eval variables (we are necessarily at the-               top level) */-            for (idx = 0; idx < fd->closure_var_count; idx++) {-                JSClosureVar *cv = &fd->closure_var[idx];-                get_closure_var2(ctx, s, fd,-                                 FALSE, cv->is_arg,-                                 idx, cv->var_name, cv->is_const,-                                 cv->is_lexical, cv->var_kind);-            }-        }-    }-}--/* for direct eval compilation: add references to the variables of the-   calling function */-static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,-                                             JSFunctionBytecode *b, int scope_idx)-{-    int i, count;-    JSVarDef *vd;--    count = b->arg_count + b->var_count + b->closure_var_count;-    s->closure_var = NULL;-    s->closure_var_count = 0;-    s->closure_var_size = count;-    if (count == 0)-        return 0;-    s->closure_var = js_malloc(ctx, sizeof(s->closure_var[0]) * count);-    if (!s->closure_var)-        return -1;-    /* Add lexical variables in scope at the point of evaluation */-    for (i = scope_idx; i >= 0;) {-        vd = &b->vardefs[b->arg_count + i];-        if (vd->scope_level > 0) {-            JSClosureVar *cv = &s->closure_var[s->closure_var_count++];-            cv->is_local = TRUE;-            cv->is_arg = FALSE;-            cv->is_const = vd->is_const;-            cv->is_lexical = vd->is_lexical;-            cv->var_kind = vd->var_kind;-            cv->var_idx = i;-            cv->var_name = JS_DupAtom(ctx, vd->var_name);-        }-        i = vd->scope_next;-    }-    /* Add argument variables */-    for(i = 0; i < b->arg_count; i++) {-        JSClosureVar *cv = &s->closure_var[s->closure_var_count++];-        vd = &b->vardefs[i];-        cv->is_local = TRUE;-        cv->is_arg = TRUE;-        cv->is_const = FALSE;-        cv->is_lexical = FALSE;-        cv->var_kind = JS_VAR_NORMAL;-        cv->var_idx = i;-        cv->var_name = JS_DupAtom(ctx, vd->var_name);-    }-    /* Add local non lexical variables */-    for(i = 0; i < b->var_count; i++) {-        vd = &b->vardefs[b->arg_count + i];-        if (vd->scope_level == 0 && vd->var_name != JS_ATOM__ret_) {-            JSClosureVar *cv = &s->closure_var[s->closure_var_count++];-            cv->is_local = TRUE;-            cv->is_arg = FALSE;-            cv->is_const = FALSE;-            cv->is_lexical = FALSE;-            cv->var_kind = JS_VAR_NORMAL;-            cv->var_idx = i;-            cv->var_name = JS_DupAtom(ctx, vd->var_name);-        }-    }-    for(i = 0; i < b->closure_var_count; i++) {-        JSClosureVar *cv0 = &b->closure_var[i];-        JSClosureVar *cv = &s->closure_var[s->closure_var_count++];-        cv->is_local = FALSE;-        cv->is_arg = cv0->is_arg;-        cv->is_const = cv0->is_const;-        cv->is_lexical = cv0->is_lexical;-        cv->var_kind = cv0->var_kind;-        cv->var_idx = i;-        cv->var_name = JS_DupAtom(ctx, cv0->var_name);-    }-    return 0;-}--typedef struct CodeContext {-    const uint8_t *bc_buf; /* code buffer */-    int bc_len;   /* length of the code buffer */-    int pos;      /* position past the matched code pattern */-    int line_num; /* last visited OP_line_num parameter or -1 */-    int op;-    int idx;-    int label;-    int val;-    JSAtom atom;-} CodeContext;--#define M2(op1, op2)            ((op1) | ((op2) << 8))-#define M3(op1, op2, op3)       ((op1) | ((op2) << 8) | ((op3) << 16))-#define M4(op1, op2, op3, op4)  ((op1) | ((op2) << 8) | ((op3) << 16) | ((op4) << 24))--static BOOL code_match(CodeContext *s, int pos, ...)-{-    const uint8_t *tab = s->bc_buf;-    int op, len, op1, line_num, pos_next;-    va_list ap;-    BOOL ret = FALSE;--    line_num = -1;-    va_start(ap, pos);--    for(;;) {-        op1 = va_arg(ap, int);-        if (op1 == -1) {-            s->pos = pos;-            s->line_num = line_num;-            ret = TRUE;-            break;-        }-        for (;;) {-            if (pos >= s->bc_len)-                goto done;-            op = tab[pos];-            len = opcode_info[op].size;-            pos_next = pos + len;-            if (pos_next > s->bc_len)-                goto done;-            if (op == OP_line_num) {-                line_num = get_u32(tab + pos + 1);-                pos = pos_next;-            } else {-                break;-            }-        }-        if (op != op1) {-            if (op1 == (uint8_t)op1 || !op)-                break;-            if (op != (uint8_t)op1-            &&  op != (uint8_t)(op1 >> 8)-            &&  op != (uint8_t)(op1 >> 16)-            &&  op != (uint8_t)(op1 >> 24)) {-                break;-            }-            s->op = op;-        }--        pos++;-        switch(opcode_info[op].fmt) {-        case OP_FMT_loc8:-        case OP_FMT_u8:-            {-                int idx = tab[pos];-                int arg = va_arg(ap, int);-                if (arg == -1) {-                    s->idx = idx;-                } else {-                    if (arg != idx)-                        goto done;-                }-                break;-            }-        case OP_FMT_u16:-        case OP_FMT_npop:-        case OP_FMT_loc:-        case OP_FMT_arg:-        case OP_FMT_var_ref:-            {-                int idx = get_u16(tab + pos);-                int arg = va_arg(ap, int);-                if (arg == -1) {-                    s->idx = idx;-                } else {-                    if (arg != idx)-                        goto done;-                }-                break;-            }-        case OP_FMT_i32:-        case OP_FMT_u32:-        case OP_FMT_label:-        case OP_FMT_const:-            {-                s->label = get_u32(tab + pos);-                break;-            }-        case OP_FMT_label_u16:-            {-                s->label = get_u32(tab + pos);-                s->val = get_u16(tab + pos + 4);-                break;-            }-        case OP_FMT_atom:-            {-                s->atom = get_u32(tab + pos);-                break;-            }-        case OP_FMT_atom_u8:-            {-                s->atom = get_u32(tab + pos);-                s->val = get_u8(tab + pos + 4);-                break;-            }-        case OP_FMT_atom_u16:-            {-                s->atom = get_u32(tab + pos);-                s->val = get_u16(tab + pos + 4);-                break;-            }-        case OP_FMT_atom_label_u8:-            {-                s->atom = get_u32(tab + pos);-                s->label = get_u32(tab + pos + 4);-                s->val = get_u8(tab + pos + 8);-                break;-            }-        default:-            break;-        }-        pos = pos_next;-    }- done:-    va_end(ap);-    return ret;-}--static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, DynBuf *bc)-{-    int i, idx, var_idx;--    /* add the hoisted functions and variables */-    for(i = 0; i < s->hoisted_def_count; i++) {-        JSHoistedDef *hf = &s->hoisted_def[i];-        int has_closure = 0;-        BOOL force_init = hf->force_init;-        if (s->is_global_var && hf->var_name != JS_ATOM_NULL) {-            /* we are in an eval, so the closure contains all the-               enclosing variables */-            /* If the outer function has a variable environment,-               create a property for the variable there */-            for(idx = 0; idx < s->closure_var_count; idx++) {-                JSClosureVar *cv = &s->closure_var[idx];-                if (cv->var_name == hf->var_name) {-                    has_closure = 2;-                    force_init = FALSE;-                    break;-                }-                if (cv->var_name == JS_ATOM__var_) {-                    dbuf_putc(bc, OP_get_var_ref);-                    dbuf_put_u16(bc, idx);-                    has_closure = 1;-                    force_init = TRUE;-                    break;-                }-            }-            if (!has_closure) {-                int flags;--                flags = 0;-                if (s->eval_type != JS_EVAL_TYPE_GLOBAL)-                    flags |= JS_PROP_CONFIGURABLE;-                if (hf->cpool_idx >= 0 && !hf->is_lexical) {-                    /* global function definitions need a specific handling */-                    dbuf_putc(bc, OP_fclosure);-                    dbuf_put_u32(bc, hf->cpool_idx);--                    dbuf_putc(bc, OP_define_func);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));-                    dbuf_putc(bc, flags);--                    goto done_hoisted_def;-                } else {-                    if (hf->is_lexical) {-                        flags |= DEFINE_GLOBAL_LEX_VAR;-                        if (!hf->is_const)-                            flags |= JS_PROP_WRITABLE;-                    }-                    dbuf_putc(bc, OP_define_var);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));-                    dbuf_putc(bc, flags);-                }-            }-        }-        if (hf->cpool_idx >= 0 || force_init) {-            if (hf->cpool_idx >= 0) {-                dbuf_putc(bc, OP_fclosure);-                dbuf_put_u32(bc, hf->cpool_idx);-                if (hf->var_name == JS_ATOM__default_) {-                    /* set default export function name */-                    dbuf_putc(bc, OP_set_name);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, JS_ATOM_default));-                }-            } else {-                dbuf_putc(bc, OP_undefined);-            }-            if (s->is_global_var) {-                if (has_closure == 2) {-                    dbuf_putc(bc, OP_put_var_ref);-                    dbuf_put_u16(bc, idx);-                } else if (has_closure == 1) {-                    dbuf_putc(bc, OP_define_field);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));-                    dbuf_putc(bc, OP_drop);-                } else {-                    /* XXX: Check if variable is writable and enumerable */-                    dbuf_putc(bc, OP_put_var);-                    dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));-                }-            } else {-                var_idx = hf->var_idx;-                if (var_idx & ARGUMENT_VAR_OFFSET) {-                    dbuf_putc(bc, OP_put_arg);-                    dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);-                } else {-                    dbuf_putc(bc, OP_put_loc);-                    dbuf_put_u16(bc, var_idx);-                }-            }-        }-    done_hoisted_def:-        JS_FreeAtom(ctx, hf->var_name);-    }-    js_free(ctx, s->hoisted_def);-    s->hoisted_def = NULL;-    s->hoisted_def_count = 0;-    s->hoisted_def_size = 0;-}--static int skip_dead_code(JSFunctionDef *s, const uint8_t *bc_buf, int bc_len,-                          int pos, int *linep)-{-    int op, len, label;--    for (; pos < bc_len; pos += len) {-        op = bc_buf[pos];-        len = opcode_info[op].size;-        if (op == OP_line_num) {-            *linep = get_u32(bc_buf + pos + 1);-        } else-        if (op == OP_label) {-            label = get_u32(bc_buf + pos + 1);-            if (update_label(s, label, 0) > 0)-                break;-#if 0-            if (s->label_slots[label].first_reloc) {-                printf("line %d: unreferenced label %d:%d has relocations\n",-                       *linep, label, s->label_slots[label].pos2);-            }-#endif-            assert(s->label_slots[label].first_reloc == NULL);-        } else {-            /* XXX: output a warning for unreachable code? */-            JSAtom atom;-            switch(opcode_info[op].fmt) {-            case OP_FMT_label:-            case OP_FMT_label_u16:-                label = get_u32(bc_buf + pos + 1);-                update_label(s, label, -1);-                break;-            case OP_FMT_atom_label_u8:-            case OP_FMT_atom_label_u16:-                label = get_u32(bc_buf + pos + 5);-                update_label(s, label, -1);-                /* fall thru */-            case OP_FMT_atom:-            case OP_FMT_atom_u8:-            case OP_FMT_atom_u16:-                atom = get_u32(bc_buf + pos + 1);-                JS_FreeAtom(s->ctx, atom);-                break;-            default:-                break;-            }-        }-    }-    return pos;-}--static int get_label_pos(JSFunctionDef *s, int label)-{-    int i, pos;-    for (i = 0; i < 20; i++) {-        pos = s->label_slots[label].pos;-        for (;;) {-            switch (s->byte_code.buf[pos]) {-            case OP_line_num:-            case OP_label:-                pos += 5;-                continue;-            case OP_goto:-                label = get_u32(s->byte_code.buf + pos + 1);-                break;-            default:-                return pos;-            }-            break;-        }-    }-    return pos;-}--/* convert global variable accesses to local variables or closure-   variables when necessary */-static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)-{-    int pos, pos_next, bc_len, op, len, i, idx, arg_valid, line_num;-    uint8_t *bc_buf;-    JSAtom var_name;-    DynBuf bc_out;-    CodeContext cc;-    int scope;--    cc.bc_buf = bc_buf = s->byte_code.buf;-    cc.bc_len = bc_len = s->byte_code.size;-    js_dbuf_init(ctx, &bc_out);--    /* first pass for runtime checks (must be done before the-       variables are created) */-    if (s->is_global_var) {-        for(i = 0; i < s->hoisted_def_count; i++) {-            JSHoistedDef *hf = &s->hoisted_def[i];-            int flags;--            if (hf->var_name != JS_ATOM_NULL) {-                /* check if global variable (XXX: simplify) */-                for(idx = 0; idx < s->closure_var_count; idx++) {-                    JSClosureVar *cv = &s->closure_var[idx];-                    if (cv->var_name == hf->var_name) {-                        if (s->eval_type == JS_EVAL_TYPE_DIRECT &&-                            cv->is_lexical) {-                            /* Check if a lexical variable is-                               redefined as 'var'. XXX: Could abort-                               compilation here, but for consistency-                               with the other checks, we delay the-                               error generation. */-                            dbuf_putc(&bc_out, OP_throw_var);-                            dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));-                            dbuf_putc(&bc_out, JS_THROW_VAR_REDECL);-                        }-                        goto next;-                    }-                    if (cv->var_name == JS_ATOM__var_)-                        goto next;-                }--                dbuf_putc(&bc_out, OP_check_define_var);-                dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));-                flags = 0;-                if (hf->is_lexical)-                    flags |= DEFINE_GLOBAL_LEX_VAR;-                if (hf->cpool_idx >= 0)-                    flags |= DEFINE_GLOBAL_FUNC_VAR;-                dbuf_putc(&bc_out, flags);-            }-        next: ;-        }-    }--    arg_valid = 0;-    line_num = 0; /* avoid warning */-    for (pos = 0; pos < bc_len; pos = pos_next) {-        op = bc_buf[pos];-        len = opcode_info[op].size;-        pos_next = pos + len;-        switch(op) {-        case OP_line_num:-            line_num = get_u32(bc_buf + pos + 1);-            s->line_number_size++;-            goto no_change;--        case OP_set_arg_valid_upto:-            arg_valid = get_u16(bc_buf + pos + 1);-            break;-        case OP_eval: /* convert scope index to adjusted variable index */-            {-                int call_argc = get_u16(bc_buf + pos + 1);-                scope = get_u16(bc_buf + pos + 1 + 2);-                mark_eval_captured_variables(ctx, s, scope);-                dbuf_putc(&bc_out, op);-                dbuf_put_u16(&bc_out, call_argc);-                dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);-            }-            break;-        case OP_apply_eval: /* convert scope index to adjusted variable index */-            scope = get_u16(bc_buf + pos + 1);-            mark_eval_captured_variables(ctx, s, scope);-            dbuf_putc(&bc_out, op);-            dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);-            break;-        case OP_scope_get_var_undef:-        case OP_scope_get_var:-        case OP_scope_put_var:-        case OP_scope_delete_var:-        case OP_scope_get_ref:-        case OP_scope_put_var_init:-            var_name = get_u32(bc_buf + pos + 1);-            scope = get_u16(bc_buf + pos + 5);-            pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,-                                         NULL, NULL, pos_next, arg_valid);-            JS_FreeAtom(ctx, var_name);-            break;-        case OP_scope_make_ref:-            {-                int label;-                LabelSlot *ls;-                var_name = get_u32(bc_buf + pos + 1);-                label = get_u32(bc_buf + pos + 5);-                scope = get_u16(bc_buf + pos + 9);-                ls = &s->label_slots[label];-                ls->ref_count--;  /* always remove label reference */-                pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,-                                             bc_buf, ls, pos_next, arg_valid);-                JS_FreeAtom(ctx, var_name);-            }-            break;-        case OP_scope_get_private_field:-        case OP_scope_get_private_field2:-        case OP_scope_put_private_field:-            {-                int ret;-                var_name = get_u32(bc_buf + pos + 1);-                scope = get_u16(bc_buf + pos + 5);-                ret = resolve_scope_private_field(ctx, s, var_name, scope, op, &bc_out);-                if (ret < 0)-                    goto fail;-                JS_FreeAtom(ctx, var_name);-            }-            break;-        case OP_gosub:-            s->jump_size++;-            if (OPTIMIZE) {-                /* remove calls to empty finalizers  */-                int label;-                LabelSlot *ls;--                label = get_u32(bc_buf + pos + 1);-                assert(label >= 0 && label < s->label_count);-                ls = &s->label_slots[label];-                if (code_match(&cc, ls->pos, OP_ret, -1)) {-                    ls->ref_count--;-                    break;-                }-            }-            goto no_change;-        case OP_drop:-            if (0) {-                /* remove drops before return_undef */-                /* do not perform this optimization in pass2 because-                   it breaks patterns recognised in resolve_labels */-                int pos1 = pos_next;-                int line1 = line_num;-                while (code_match(&cc, pos1, OP_drop, -1)) {-                    if (cc.line_num >= 0) line1 = cc.line_num;-                    pos1 = cc.pos;-                }-                if (code_match(&cc, pos1, OP_return_undef, -1)) {-                    pos_next = pos1;-                    if (line1 != -1 && line1 != line_num) {-                        line_num = line1;-                        s->line_number_size++;-                        dbuf_putc(&bc_out, OP_line_num);-                        dbuf_put_u32(&bc_out, line_num);-                    }-                    break;-                }-            }-            goto no_change;-        case OP_insert3:-            if (OPTIMIZE) {-                /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */-                if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) {-                    dbuf_putc(&bc_out, cc.op);-                    pos_next = cc.pos;-                    if (cc.line_num != -1 && cc.line_num != line_num) {-                        line_num = cc.line_num;-                        s->line_number_size++;-                        dbuf_putc(&bc_out, OP_line_num);-                        dbuf_put_u32(&bc_out, line_num);-                    }-                    break;-                }-            }-            goto no_change;--        case OP_goto:-            s->jump_size++;-            /* fall thru */-        case OP_tail_call:-        case OP_tail_call_method:-        case OP_return:-        case OP_return_undef:-        case OP_throw:-        case OP_throw_var:-        case OP_ret:-            if (OPTIMIZE) {-                /* remove dead code */-                int line = -1;-                dbuf_put(&bc_out, bc_buf + pos, len);-                pos = skip_dead_code(s, bc_buf, bc_len, pos + len, &line);-                pos_next = pos;-                if (pos < bc_len && line >= 0 && line_num != line) {-                    line_num = line;-                    s->line_number_size++;-                    dbuf_putc(&bc_out, OP_line_num);-                    dbuf_put_u32(&bc_out, line_num);-                }-                break;-            }-            goto no_change;--        case OP_label:-            {-                int label;-                LabelSlot *ls;--                label = get_u32(bc_buf + pos + 1);-                assert(label >= 0 && label < s->label_count);-                ls = &s->label_slots[label];-                ls->pos2 = bc_out.size + opcode_info[op].size;-            }-            goto no_change;--        case OP_enter_scope:-            {-                int scope_idx, scope = get_u16(bc_buf + pos + 1);--                if (scope == 1) {-                    instantiate_hoisted_definitions(ctx, s, &bc_out);-                }--                for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {-                    JSVarDef *vd = &s->vars[scope_idx];-                    if (vd->scope_level == scope) {-                        if (vd->var_kind == JS_VAR_FUNCTION_DECL ||-                            vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) {-                            /* Initialize lexical variable upon entering scope */-                            dbuf_putc(&bc_out, OP_fclosure);-                            dbuf_put_u32(&bc_out, vd->func_pool_or_scope_idx);-                            dbuf_putc(&bc_out, OP_put_loc);-                            dbuf_put_u16(&bc_out, scope_idx);-                        } else {-                            /* XXX: should check if variable can be used-                               before initialization */-                            dbuf_putc(&bc_out, OP_set_loc_uninitialized);-                            dbuf_put_u16(&bc_out, scope_idx);-                        }-                        scope_idx = vd->scope_next;-                    } else {-                        break;-                    }-                }-            }-            break;--        case OP_leave_scope:-            {-                int scope_idx, scope = get_u16(bc_buf + pos + 1);--                for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {-                    JSVarDef *vd = &s->vars[scope_idx];-                    if (vd->scope_level == scope) {-                        if (vd->is_captured) {-                            dbuf_putc(&bc_out, OP_close_loc);-                            dbuf_put_u16(&bc_out, scope_idx);-                        }-                        scope_idx = vd->scope_next;-                    } else {-                        break;-                    }-                }-            }-            break;--        case OP_set_name:-            {-                /* remove dummy set_name opcodes */-                JSAtom name = get_u32(bc_buf + pos + 1);-                if (name == JS_ATOM_NULL)-                    break;-            }-            goto no_change;--        case OP_if_false:-        case OP_if_true:-        case OP_catch:-            s->jump_size++;-            goto no_change;--        case OP_dup:-            if (OPTIMIZE) {-                /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */-                /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */-                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) {-                    int lab0, lab1, op1, pos1, line1, pos2;-                    lab0 = lab1 = cc.label;-                    assert(lab1 >= 0 && lab1 < s->label_count);-                    op1 = cc.op;-                    pos1 = cc.pos;-                    line1 = cc.line_num;-                    while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) {-                        lab1 = cc.label;-                    }-                    if (code_match(&cc, pos2, op1, -1)) {-                        s->jump_size++;-                        update_label(s, lab0, -1);-                        update_label(s, cc.label, +1);-                        dbuf_putc(&bc_out, op1);-                        dbuf_put_u32(&bc_out, cc.label);-                        pos_next = pos1;-                        if (line1 != -1 && line1 != line_num) {-                            line_num = line1;-                            s->line_number_size++;-                            dbuf_putc(&bc_out, OP_line_num);-                            dbuf_put_u32(&bc_out, line_num);-                        }-                        break;-                    }-                }-            }-            goto no_change;--        case OP_nop:-            /* remove erased code */-            break;-        case OP_set_class_name:-            /* only used during parsing */-            break;-            -        default:-        no_change:-            dbuf_put(&bc_out, bc_buf + pos, len);-            break;-        }-    }--    /* set the new byte code */-    dbuf_free(&s->byte_code);-    s->byte_code = bc_out;-    if (dbuf_error(&s->byte_code)) {-        JS_ThrowOutOfMemory(ctx);-        return -1;-    }-    return 0;- fail:-    /* continue the copy to keep the atom refcounts consistent */-    /* XXX: find a better solution ? */-    for (; pos < bc_len; pos = pos_next) {-        op = bc_buf[pos];-        len = opcode_info[op].size;-        pos_next = pos + len;-        dbuf_put(&bc_out, bc_buf + pos, len);-    }-    dbuf_free(&s->byte_code);-    s->byte_code = bc_out;-    return -1;-}--/* the pc2line table gives a line number for each PC value */-static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, int line_num)-{-    if (s->line_number_slots != NULL-    &&  s->line_number_count < s->line_number_size-    &&  pc >= s->line_number_last_pc-    &&  line_num != s->line_number_last) {-        s->line_number_slots[s->line_number_count].pc = pc;-        s->line_number_slots[s->line_number_count].line_num = line_num;-        s->line_number_count++;-        s->line_number_last_pc = pc;-        s->line_number_last = line_num;-    }-}--static void compute_pc2line_info(JSFunctionDef *s)-{-    if (!(s->js_mode & JS_MODE_STRIP) && s->line_number_slots) {-        int last_line_num = s->line_num;-        uint32_t last_pc = 0;-        int i;--        js_dbuf_init(s->ctx, &s->pc2line);-        for (i = 0; i < s->line_number_count; i++) {-            uint32_t pc = s->line_number_slots[i].pc;-            int line_num = s->line_number_slots[i].line_num;-            int diff_pc, diff_line;--            if (line_num < 0)-                continue;--            diff_pc = pc - last_pc;-            diff_line = line_num - last_line_num;-            if (diff_line == 0 || diff_pc < 0)-                continue;--            if (diff_line >= PC2LINE_BASE &&-                diff_line < PC2LINE_BASE + PC2LINE_RANGE &&-                diff_pc <= PC2LINE_DIFF_PC_MAX) {-                dbuf_putc(&s->pc2line, (diff_line - PC2LINE_BASE) +-                          diff_pc * PC2LINE_RANGE + PC2LINE_OP_FIRST);-            } else {-                /* longer encoding */-                dbuf_putc(&s->pc2line, 0);-                dbuf_put_leb128(&s->pc2line, diff_pc);-                dbuf_put_sleb128(&s->pc2line, diff_line);-            }-            last_pc = pc;-            last_line_num = line_num;-        }-    }-}--static RelocEntry *add_reloc(JSContext *ctx, LabelSlot *ls, uint32_t addr, int size)-{-    RelocEntry *re;-    re = js_malloc(ctx, sizeof(*re));-    if (!re)-        return NULL;-    re->addr = addr;-    re->size = size;-    re->next = ls->first_reloc;-    ls->first_reloc = re;-    return re;-}--static BOOL code_has_label(CodeContext *s, int pos, int label)-{-    while (pos < s->bc_len) {-        int op = s->bc_buf[pos];-        if (op == OP_line_num) {-            pos += 5;-            continue;-        }-        if (op == OP_label) {-            int lab = get_u32(s->bc_buf + pos + 1);-            if (lab == label)-                return TRUE;-            pos += 5;-            continue;-        }-        if (op == OP_goto) {-            int lab = get_u32(s->bc_buf + pos + 1);-            if (lab == label)-                return TRUE;-        }-        break;-    }-    return FALSE;-}--/* return the target label, following the OP_goto jumps-   the first opcode at destination is stored in *pop- */-static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline)-{-    int i, pos, op;--    update_label(s, label, -1);-    for (i = 0; i < 10; i++) {-        assert(label >= 0 && label < s->label_count);-        pos = s->label_slots[label].pos2;-        for (;;) {-            switch(op = s->byte_code.buf[pos]) {-            case OP_line_num:-                if (pline)-                    *pline = get_u32(s->byte_code.buf + pos + 1);-                /* fall thru */-            case OP_label:-                pos += opcode_info[op].size;-                continue;-            case OP_goto:-                label = get_u32(s->byte_code.buf + pos + 1);-                break;-            case OP_drop:-                /* ignore drop opcodes if followed by OP_return_undef */-                while (s->byte_code.buf[++pos] == OP_drop)-                    continue;-                if (s->byte_code.buf[pos] == OP_return_undef)-                    op = OP_return_undef;-                /* fall thru */-            default:-                goto done;-            }-            break;-        }-    }-    /* cycle detected, could issue a warning */- done:-    *pop = op;-    update_label(s, label, +1);-    return label;-}--static void push_short_int(DynBuf *bc_out, int val)-{-#if SHORT_OPCODES-    if (val >= -1 && val <= 7) {-        dbuf_putc(bc_out, OP_push_0 + val);-        return;-    }-    if (val == (int8_t)val) {-        dbuf_putc(bc_out, OP_push_i8);-        dbuf_putc(bc_out, val);-        return;-    }-    if (val == (int16_t)val) {-        dbuf_putc(bc_out, OP_push_i16);-        dbuf_put_u16(bc_out, val);-        return;-    }-#endif-    dbuf_putc(bc_out, OP_push_i32);-    dbuf_put_u32(bc_out, val);-}--static void put_short_code(DynBuf *bc_out, int op, int idx)-{-#if SHORT_OPCODES-    if (idx < 4) {-        switch (op) {-        case OP_get_loc:-            dbuf_putc(bc_out, OP_get_loc0 + idx);-            return;-        case OP_put_loc:-            dbuf_putc(bc_out, OP_put_loc0 + idx);-            return;-        case OP_set_loc:-            dbuf_putc(bc_out, OP_set_loc0 + idx);-            return;-        case OP_get_arg:-            dbuf_putc(bc_out, OP_get_arg0 + idx);-            return;-        case OP_put_arg:-            dbuf_putc(bc_out, OP_put_arg0 + idx);-            return;-        case OP_set_arg:-            dbuf_putc(bc_out, OP_set_arg0 + idx);-            return;-        case OP_get_var_ref:-            dbuf_putc(bc_out, OP_get_var_ref0 + idx);-            return;-        case OP_put_var_ref:-            dbuf_putc(bc_out, OP_put_var_ref0 + idx);-            return;-        case OP_set_var_ref:-            dbuf_putc(bc_out, OP_set_var_ref0 + idx);-            return;-        case OP_call:-            dbuf_putc(bc_out, OP_call0 + idx);-            return;-        }-    }-    if (idx < 256) {-        switch (op) {-        case OP_get_loc:-            dbuf_putc(bc_out, OP_get_loc8);-            dbuf_putc(bc_out, idx);-            return;-        case OP_put_loc:-            dbuf_putc(bc_out, OP_put_loc8);-            dbuf_putc(bc_out, idx);-            return;-        case OP_set_loc:-            dbuf_putc(bc_out, OP_set_loc8);-            dbuf_putc(bc_out, idx);-            return;-        }-    }-#endif-    dbuf_putc(bc_out, op);-    dbuf_put_u16(bc_out, idx);-}--/* peephole optimizations and resolve goto/labels */-static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)-{-    int pos, pos_next, bc_len, op, op1, len, i, line_num;-    const uint8_t *bc_buf;-    DynBuf bc_out;-    LabelSlot *label_slots, *ls;-    RelocEntry *re, *re_next;-    CodeContext cc;-    int label;-#if SHORT_OPCODES-    JumpSlot *jp;-#endif--    label_slots = s->label_slots;--    line_num = s->line_num;--    cc.bc_buf = bc_buf = s->byte_code.buf;-    cc.bc_len = bc_len = s->byte_code.size;-    js_dbuf_init(ctx, &bc_out);--#if SHORT_OPCODES-    if (s->jump_size) {-        s->jump_slots = js_mallocz(s->ctx, sizeof(*s->jump_slots) * s->jump_size);-        if (s->jump_slots == NULL)-            return -1;-    }-#endif-    /* XXX: Should skip this phase if not generating SHORT_OPCODES */-    if (s->line_number_size && !(s->js_mode & JS_MODE_STRIP)) {-        s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size);-        if (s->line_number_slots == NULL)-            return -1;-        s->line_number_last = s->line_num;-        s->line_number_last_pc = 0;-    }--    /* initialize the 'home_object' variable if needed */-    if (s->home_object_var_idx >= 0) {-        dbuf_putc(&bc_out, OP_special_object);-        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_HOME_OBJECT);-        put_short_code(&bc_out, OP_put_loc, s->home_object_var_idx);-    }-    /* initialize the 'this.active_func' variable if needed */-    if (s->this_active_func_var_idx >= 0) {-        dbuf_putc(&bc_out, OP_special_object);-        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC);-        put_short_code(&bc_out, OP_put_loc, s->this_active_func_var_idx);-    }-    /* initialize the 'new.target' variable if needed */-    if (s->new_target_var_idx >= 0) {-        dbuf_putc(&bc_out, OP_special_object);-        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_NEW_TARGET);-        put_short_code(&bc_out, OP_put_loc, s->new_target_var_idx);-    }-    /* initialize the 'this' variable if needed. In a derived class-       constructor, this is initially uninitialized. */-    if (s->this_var_idx >= 0) {-        if (s->is_derived_class_constructor) {-            dbuf_putc(&bc_out, OP_set_loc_uninitialized);-            dbuf_put_u16(&bc_out, s->this_var_idx);-        } else {-            dbuf_putc(&bc_out, OP_push_this);-            put_short_code(&bc_out, OP_put_loc, s->this_var_idx);-        }-    }-    /* initialize the 'arguments' variable if needed */-    if (s->arguments_var_idx >= 0) {-        if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) {-            dbuf_putc(&bc_out, OP_special_object);-            dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS);-        } else {-            dbuf_putc(&bc_out, OP_special_object);-            dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS);-        }-        put_short_code(&bc_out, OP_put_loc, s->arguments_var_idx);-    }-    /* initialize a reference to the current function if needed */-    if (s->func_var_idx >= 0) {-        dbuf_putc(&bc_out, OP_special_object);-        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC);-        put_short_code(&bc_out, OP_put_loc, s->func_var_idx);-    }-    /* initialize the variable environment object if needed */-    if (s->var_object_idx >= 0) {-        dbuf_putc(&bc_out, OP_special_object);-        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT);-        put_short_code(&bc_out, OP_put_loc, s->var_object_idx);-    }--    for (pos = 0; pos < bc_len; pos = pos_next) {-        int val;-        op = bc_buf[pos];-        len = opcode_info[op].size;-        pos_next = pos + len;-        switch(op) {-        case OP_line_num:-            /* line number info (for debug). We put it in a separate-               compressed table to reduce memory usage and get better-               performance */-            line_num = get_u32(bc_buf + pos + 1);-            break;--        case OP_label:-            {-                label = get_u32(bc_buf + pos + 1);-                assert(label >= 0 && label < s->label_count);-                ls = &label_slots[label];-                assert(ls->addr == -1);-                ls->addr = bc_out.size;-                /* resolve the relocation entries */-                for(re = ls->first_reloc; re != NULL; re = re_next) {-                    int diff = ls->addr - re->addr;-                    re_next = re->next;-                    switch (re->size) {-                    case 4:-                        put_u32(bc_out.buf + re->addr, diff);-                        break;-                    case 2:-                        assert(diff == (int16_t)diff);-                        put_u16(bc_out.buf + re->addr, diff);-                        break;-                    case 1:-                        assert(diff == (int8_t)diff);-                        put_u8(bc_out.buf + re->addr, diff);-                        break;-                    }-                    js_free(ctx, re);-                }-                ls->first_reloc = NULL;-            }-            break;--        case OP_call:-        case OP_call_method:-            {-                /* detect and transform tail calls */-                int argc;-                argc = get_u16(bc_buf + pos + 1);-                if (code_match(&cc, pos_next, OP_return, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    put_short_code(&bc_out, op + 1, argc);-                    pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, &line_num);-                    break;-                }-                add_pc2line_info(s, bc_out.size, line_num);-                put_short_code(&bc_out, op, argc);-                break;-            }-            goto no_change;--        case OP_return:-        case OP_return_undef:-        case OP_return_async:-        case OP_throw:-        case OP_throw_var:-            pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);-            goto no_change;--        case OP_goto:-            label = get_u32(bc_buf + pos + 1);-        has_goto:-            if (OPTIMIZE) {-                int line1 = -1;-                /* Use custom matcher because multiple labels can follow */-                label = find_jump_target(s, label, &op1, &line1);-                if (code_has_label(&cc, pos_next, label)) {-                    /* jump to next instruction: remove jump */-                    update_label(s, label, -1);-                    break;-                }-                if (op1 == OP_return || op1 == OP_return_undef || op1 == OP_throw) {-                    /* jump to return/throw: remove jump, append return/throw */-                    /* updating the line number obfuscates assembly listing */-                    //if (line1 >= 0) line_num = line1;-                    update_label(s, label, -1);-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, op1);-                    pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);-                    break;-                }-                /* XXX: should duplicate single instructions followed by goto or return */-                /* For example, can match one of these followed by return:-                   push_i32 / push_const / push_atom_value / get_var /-                   undefined / null / push_false / push_true / get_ref_value /-                   get_loc / get_arg / get_var_ref-                 */-            }-            goto has_label;--        case OP_gosub:-            label = get_u32(bc_buf + pos + 1);-            if (0 && OPTIMIZE) {-                label = find_jump_target(s, label, &op1, NULL);-                if (op1 == OP_ret) {-                    update_label(s, label, -1);-                    /* empty finally clause: remove gosub */-                    break;-                }-            }-            goto has_label;--        case OP_catch:-            label = get_u32(bc_buf + pos + 1);-            goto has_label;--        case OP_if_true:-        case OP_if_false:-            label = get_u32(bc_buf + pos + 1);-            if (OPTIMIZE) {-                label = find_jump_target(s, label, &op1, NULL);-                /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */-                if (code_has_label(&cc, pos_next, label)) {-                    update_label(s, label, -1);-                    dbuf_putc(&bc_out, OP_drop);-                    break;-                }-                /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */-                if (code_match(&cc, pos_next, OP_goto, -1)) {-                    int pos1 = cc.pos;-                    int line1 = cc.line_num;-                    if (code_has_label(&cc, pos1, label)) {-                        if (line1 >= 0) line_num = line1;-                        pos_next = pos1;-                        update_label(s, label, -1);-                        label = cc.label;-                        op ^= OP_if_true ^ OP_if_false;-                    }-                }-            }-        has_label:-            add_pc2line_info(s, bc_out.size, line_num);-            if (op == OP_goto) {-                pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);-            }-            assert(label >= 0 && label < s->label_count);-            ls = &label_slots[label];-#if SHORT_OPCODES-            jp = &s->jump_slots[s->jump_count++];-            jp->op = op;-            jp->size = 4;-            jp->pos = bc_out.size + 1;-            jp->label = label;--            if (ls->addr == -1) {-                int diff = ls->pos2 - pos - 1;-                if (diff < 128 && (op == OP_if_false || op == OP_if_true || op == OP_goto)) {-                    jp->size = 1;-                    jp->op = OP_if_false8 + (op - OP_if_false);-                    dbuf_putc(&bc_out, OP_if_false8 + (op - OP_if_false));-                    dbuf_putc(&bc_out, 0);-                    if (!add_reloc(ctx, ls, bc_out.size - 1, 1))-                        goto fail;-                    break;-                }-                if (diff < 32768 && op == OP_goto) {-                    jp->size = 2;-                    jp->op = OP_goto16;-                    dbuf_putc(&bc_out, OP_goto16);-                    dbuf_put_u16(&bc_out, 0);-                    if (!add_reloc(ctx, ls, bc_out.size - 2, 2))-                        goto fail;-                    break;-                }-            } else {-                int diff = ls->addr - bc_out.size - 1;-                if (diff == (int8_t)diff && (op == OP_if_false || op == OP_if_true || op == OP_goto)) {-                    jp->size = 1;-                    jp->op = OP_if_false8 + (op - OP_if_false);-                    dbuf_putc(&bc_out, OP_if_false8 + (op - OP_if_false));-                    dbuf_putc(&bc_out, diff);-                    break;-                }-                if (diff == (int16_t)diff && op == OP_goto) {-                    jp->size = 2;-                    jp->op = OP_goto16;-                    dbuf_putc(&bc_out, OP_goto16);-                    dbuf_put_u16(&bc_out, diff);-                    break;-                }-            }-#endif-            dbuf_putc(&bc_out, op);-            dbuf_put_u32(&bc_out, ls->addr - bc_out.size);-            if (ls->addr == -1) {-                /* unresolved yet: create a new relocation entry */-                if (!add_reloc(ctx, ls, bc_out.size - 4, 4))-                    goto fail;-            }-            break;-        case OP_with_get_var:-        case OP_with_put_var:-        case OP_with_delete_var:-        case OP_with_make_ref:-        case OP_with_get_ref:-        case OP_with_get_ref_undef:-            {-                JSAtom atom;-                int is_with;--                atom = get_u32(bc_buf + pos + 1);-                label = get_u32(bc_buf + pos + 5);-                is_with = bc_buf[pos + 9];-                if (OPTIMIZE) {-                    label = find_jump_target(s, label, &op1, NULL);-                }-                assert(label >= 0 && label < s->label_count);-                ls = &label_slots[label];-                add_pc2line_info(s, bc_out.size, line_num);-#if SHORT_OPCODES-                jp = &s->jump_slots[s->jump_count++];-                jp->op = op;-                jp->size = 4;-                jp->pos = bc_out.size + 5;-                jp->label = label;-#endif-                dbuf_putc(&bc_out, op);-                dbuf_put_u32(&bc_out, atom);-                dbuf_put_u32(&bc_out, ls->addr - bc_out.size);-                if (ls->addr == -1) {-                    /* unresolved yet: create a new relocation entry */-                    if (!add_reloc(ctx, ls, bc_out.size - 4, 4))-                        goto fail;-                }-                dbuf_putc(&bc_out, is_with);-            }-            break;--        case OP_drop:-            if (OPTIMIZE) {-                /* remove useless drops before return */-                if (code_match(&cc, pos_next, OP_return_undef, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    break;-                }-            }-            goto no_change;--        case OP_null:-#if SHORT_OPCODES-            if (OPTIMIZE) {-                /* transform null strict_eq into is_null */-                if (code_match(&cc, pos_next, OP_strict_eq, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_is_null);-                    pos_next = cc.pos;-                    break;-                }-                /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */-                if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_is_null);-                    pos_next = cc.pos;-                    label = cc.label;-                    op = cc.op ^ OP_if_false ^ OP_if_true;-                    goto has_label;-                }-            }-#endif-            /* fall thru */-        case OP_push_false:-        case OP_push_true:-            if (OPTIMIZE) {-                val = (op == OP_push_true);-                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {-                has_constant_test:-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    if (val == cc.op - OP_if_false) {-                        /* transform null if_false(l1) -> goto l1 */-                        /* transform false if_false(l1) -> goto l1 */-                        /* transform true if_true(l1) -> goto l1 */-                        pos_next = cc.pos;-                        op = OP_goto;-                        label = cc.label;-                        goto has_goto;-                    } else {-                        /* transform null if_true(l1) -> nop */-                        /* transform false if_true(l1) -> nop */-                        /* transform true if_false(l1) -> nop */-                        pos_next = cc.pos;-                        update_label(s, cc.label, -1);-                        break;-                    }-                }-            }-            goto no_change;--        case OP_push_i32:-            if (OPTIMIZE) {-                /* transform i32(val) neg -> i32(-val) */-                val = get_i32(bc_buf + pos + 1);-                if ((val != INT32_MIN && val != 0)-                &&  code_match(&cc, pos_next, OP_neg, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    if (code_match(&cc, cc.pos, OP_drop, -1)) {-                        if (cc.line_num >= 0) line_num = cc.line_num;-                    } else {-                        add_pc2line_info(s, bc_out.size, line_num);-                        push_short_int(&bc_out, -val);-                    }-                    pos_next = cc.pos;-                    break;-                }-                /* remove push/drop pairs generated by the parser */-                if (code_match(&cc, pos_next, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    pos_next = cc.pos;-                    break;-                }-                /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */-                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {-                    val = (val != 0);-                    goto has_constant_test;-                }-                add_pc2line_info(s, bc_out.size, line_num);-                push_short_int(&bc_out, val);-                break;-            }-            goto no_change;--#if SHORT_OPCODES-        case OP_push_const:-        case OP_fclosure:-            if (OPTIMIZE) {-                int idx = get_u32(bc_buf + pos + 1);-                if (idx < 256) {-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_push_const8 + op - OP_push_const);-                    dbuf_putc(&bc_out, idx);-                    break;-                }-            }-            goto no_change;--        case OP_get_field:-            if (OPTIMIZE) {-                JSAtom atom = get_u32(bc_buf + pos + 1);-                if (atom == JS_ATOM_length) {-                    JS_FreeAtom(ctx, atom);-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_get_length);-                    break;-                }-            }-            goto no_change;-#endif-        case OP_push_atom_value:-            if (OPTIMIZE) {-                JSAtom atom = get_u32(bc_buf + pos + 1);-                /* remove push/drop pairs generated by the parser */-                if (code_match(&cc, pos_next, OP_drop, -1)) {-                    JS_FreeAtom(ctx, atom);-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    pos_next = cc.pos;-                    break;-                }-#if SHORT_OPCODES-                if (atom == JS_ATOM_empty_string) {-                    JS_FreeAtom(ctx, atom);-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_push_empty_string);-                    break;-                }-#endif-            }-            goto no_change;--        case OP_to_propkey:-        case OP_to_propkey2:-            if (OPTIMIZE) {-                /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */-                if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1)-                ||  code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1)-                ||  code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) {-                    break;-                }-            }-            goto no_change;--        case OP_undefined:-            if (OPTIMIZE) {-                /* remove push/drop pairs generated by the parser */-                if (code_match(&cc, pos_next, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    pos_next = cc.pos;-                    break;-                }-                /* transform undefined return -> return_undefined */-                if (code_match(&cc, pos_next, OP_return, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_return_undef);-                    pos_next = cc.pos;-                    break;-                }-                /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */-                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {-                    val = 0;-                    goto has_constant_test;-                }-#if SHORT_OPCODES-                /* transform undefined strict_eq -> is_undefined */-                if (code_match(&cc, pos_next, OP_strict_eq, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_is_undefined);-                    pos_next = cc.pos;-                    break;-                }-                /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */-                if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_is_undefined);-                    pos_next = cc.pos;-                    label = cc.label;-                    op = cc.op ^ OP_if_false ^ OP_if_true;-                    goto has_label;-                }-#endif-            }-            goto no_change;--        case OP_insert2:-            if (OPTIMIZE) {-                /* Transformation:-                   insert2 put_field(a) drop -> put_field(a)-                   insert2 put_var_strict(a) drop -> put_var_strict(a)-                */-                if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, cc.op);-                    dbuf_put_u32(&bc_out, cc.atom);-                    pos_next = cc.pos;-                    break;-                }-            }-            goto no_change;--        case OP_dup:-            if (OPTIMIZE) {-                /* Transformation: dup put_x(n) drop -> put_x(n) */-                int op1, line2 = -1;-                /* Transformation: dup put_x(n) -> set_x(n) */-                if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    op1 = cc.op + 1;  /* put_x -> set_x */-                    pos_next = cc.pos;-                    if (code_match(&cc, cc.pos, OP_drop, -1)) {-                        if (cc.line_num >= 0) line_num = cc.line_num;-                        op1 -= 1; /* set_x drop -> put_x */-                        pos_next = cc.pos;-                        if (code_match(&cc, cc.pos, op1 - 1, cc.idx, -1)) {-                            line2 = cc.line_num; /* delay line number update */-                            op1 += 1;   /* put_x(n) get_x(n) -> set_x(n) */-                            pos_next = cc.pos;-                        }-                    }-                    add_pc2line_info(s, bc_out.size, line_num);-                    put_short_code(&bc_out, op1, cc.idx);-                    if (line2 >= 0) line_num = line2;-                    break;-                }-            }-            goto no_change;--        case OP_get_loc:-            if (OPTIMIZE) {-                /* transformation:-                   get_loc(n) post_dec put_loc(n) drop -> dec_loc(n)-                   get_loc(n) post_inc put_loc(n) drop -> inc_loc(n)-                   get_loc(n) dec dup put_loc(n) drop -> dec_loc(n)-                   get_loc(n) inc dup put_loc(n) drop -> inc_loc(n)-                 */-                int idx;-                idx = get_u16(bc_buf + pos + 1);-                if (idx >= 256)-                    goto no_change;-                if (code_match(&cc, pos_next, M2(OP_post_dec, OP_post_inc), OP_put_loc, idx, OP_drop, -1) ||-                    code_match(&cc, pos_next, M2(OP_dec, OP_inc), OP_dup, OP_put_loc, idx, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, (cc.op == OP_inc || cc.op == OP_post_inc) ? OP_inc_loc : OP_dec_loc);-                    dbuf_putc(&bc_out, idx);-                    pos_next = cc.pos;-                    break;-                }-                /* transformation:-                   get_loc(n) push_atom_value(x) add dup put_loc(n) drop -> push_atom_value(x) add_loc(n)-                 */-                if (code_match(&cc, pos_next, OP_push_atom_value, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-#if SHORT_OPCODES-                    if (cc.atom == JS_ATOM_empty_string) {-                        JS_FreeAtom(ctx, cc.atom);-                        dbuf_putc(&bc_out, OP_push_empty_string);-                    } else-#endif-                    {-                        dbuf_putc(&bc_out, OP_push_atom_value);-                        dbuf_put_u32(&bc_out, cc.atom);-                    }-                    dbuf_putc(&bc_out, OP_add_loc);-                    dbuf_putc(&bc_out, idx);-                    pos_next = cc.pos;-                    break;-                }-                /* transformation:-                   get_loc(n) push_i32(x) add dup put_loc(n) drop -> push_i32(x) add_loc(n)-                 */-                if (code_match(&cc, pos_next, OP_push_i32, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    push_short_int(&bc_out, cc.label);-                    dbuf_putc(&bc_out, OP_add_loc);-                    dbuf_putc(&bc_out, idx);-                    pos_next = cc.pos;-                    break;-                }-                /* transformation: XXX: also do these:-                   get_loc(n) get_loc(x) add dup put_loc(n) drop -> get_loc(x) add_loc(n)-                   get_loc(n) get_arg(x) add dup put_loc(n) drop -> get_arg(x) add_loc(n)-                   get_loc(n) get_var_ref(x) add dup put_loc(n) drop -> get_var_ref(x) add_loc(n)-                 */-                if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    put_short_code(&bc_out, cc.op, cc.idx);-                    dbuf_putc(&bc_out, OP_add_loc);-                    dbuf_putc(&bc_out, idx);-                    pos_next = cc.pos;-                    break;-                }-                add_pc2line_info(s, bc_out.size, line_num);-                put_short_code(&bc_out, op, idx);-                break;-            }-            goto no_change;-#if SHORT_OPCODES-        case OP_get_arg:-        case OP_get_var_ref:-            if (OPTIMIZE) {-                int idx;-                idx = get_u16(bc_buf + pos + 1);-                add_pc2line_info(s, bc_out.size, line_num);-                put_short_code(&bc_out, op, idx);-                break;-            }-            goto no_change;-#endif-        case OP_put_loc:-        case OP_put_arg:-        case OP_put_var_ref:-            if (OPTIMIZE) {-                /* transformation: put_x(n) get_x(n) -> set_x(n) */-                int idx;-                idx = get_u16(bc_buf + pos + 1);-                if (code_match(&cc, pos_next, op - 1, idx, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    put_short_code(&bc_out, op + 1, idx);-                    pos_next = cc.pos;-                    break;-                }-                add_pc2line_info(s, bc_out.size, line_num);-                put_short_code(&bc_out, op, idx);-                break;-            }-            goto no_change;--        case OP_post_inc:-        case OP_post_dec:-            if (OPTIMIZE) {-                /* transformation:-                   post_inc put_x drop -> inc put_x-                   post_inc perm3 put_field drop -> inc put_field-                   post_inc perm3 put_var_strict drop -> inc put_var_strict-                   post_inc perm4 put_array_el drop -> inc put_array_el-                 */-                int op1, idx;-                if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    op1 = cc.op;-                    idx = cc.idx;-                    pos_next = cc.pos;-                    if (code_match(&cc, cc.pos, op1 - 1, idx, -1)) {-                        if (cc.line_num >= 0) line_num = cc.line_num;-                        op1 += 1;   /* put_x(n) get_x(n) -> set_x(n) */-                        pos_next = cc.pos;-                    }-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));-                    put_short_code(&bc_out, op1, idx);-                    break;-                }-                if (code_match(&cc, pos_next, OP_perm3, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));-                    dbuf_putc(&bc_out, cc.op);-                    dbuf_put_u32(&bc_out, cc.atom);-                    pos_next = cc.pos;-                    break;-                }-                if (code_match(&cc, pos_next, OP_perm4, OP_put_array_el, OP_drop, -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    add_pc2line_info(s, bc_out.size, line_num);-                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));-                    dbuf_putc(&bc_out, OP_put_array_el);-                    pos_next = cc.pos;-                    break;-                }-            }-            goto no_change;--#if SHORT_OPCODES-        case OP_typeof:-            if (OPTIMIZE) {-                /* simplify typeof tests */-                if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {-                    if (cc.line_num >= 0) line_num = cc.line_num;-                    int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;-                    int op2 = -1;-                    switch (cc.atom) {-                    case JS_ATOM_undefined:-                        op2 = OP_typeof_is_undefined;-                        break;-                    case JS_ATOM_function:-                        op2 = OP_typeof_is_function;-                        break;-                    }-                    if (op2 >= 0) {-                        /* transform typeof(s) == "<type>" into is_<type> */-                        if (op1 == OP_strict_eq) {-                            add_pc2line_info(s, bc_out.size, line_num);-                            dbuf_putc(&bc_out, op2);-                            JS_FreeAtom(ctx, cc.atom);-                            pos_next = cc.pos;-                            break;-                        }-                        if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) {-                            /* transform typeof(s) != "<type>" if_false into is_<type> if_true */-                            if (cc.line_num >= 0) line_num = cc.line_num;-                            add_pc2line_info(s, bc_out.size, line_num);-                            dbuf_putc(&bc_out, op2);-                            JS_FreeAtom(ctx, cc.atom);-                            pos_next = cc.pos;-                            label = cc.label;-                            op = OP_if_true;-                            goto has_label;-                        }-                    }-                }-            }-            goto no_change;-#endif--        default:-        no_change:-            add_pc2line_info(s, bc_out.size, line_num);-            dbuf_put(&bc_out, bc_buf + pos, len);-            break;-        }-    }--    /* check that there were no missing labels */-    for(i = 0; i < s->label_count; i++) {-        assert(label_slots[i].first_reloc == NULL);-    }-#if SHORT_OPCODES-    if (OPTIMIZE) {-        /* more jump optimizations */-        int patch_offsets = 0;-        for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) {-            LabelSlot *ls;-            JumpSlot *jp1;-            int j, pos, diff, delta;--            delta = 3;-            switch (op = jp->op) {-            case OP_goto16:-                delta = 1;-                /* fall thru */-            case OP_if_false:-            case OP_if_true:-            case OP_goto:-                pos = jp->pos;-                diff = s->label_slots[jp->label].addr - pos;-                if (diff >= -128 && diff <= 127 + delta) {-                    //put_u8(bc_out.buf + pos, diff);-                    jp->size = 1;-                    if (op == OP_goto16) {-                        bc_out.buf[pos - 1] = jp->op = OP_goto8;-                    } else {-                        bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);-                    }-                    goto shrink;-                } else-                if (diff == (int16_t)diff && op == OP_goto) {-                    //put_u16(bc_out.buf + pos, diff);-                    jp->size = 2;-                    delta = 2;-                    bc_out.buf[pos - 1] = jp->op = OP_goto16;-                shrink:-                    /* XXX: should reduce complexity, using 2 finger copy scheme */-                    memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta,-                            bc_out.size - pos - jp->size - delta);-                    bc_out.size -= delta;-                    patch_offsets++;-                    for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) {-                        if (ls->addr > pos)-                            ls->addr -= delta;-                    }-                    for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) {-                        if (jp1->pos > pos)-                            jp1->pos -= delta;-                    }-                    for (j = 0; j < s->line_number_count; j++) {-                        if (s->line_number_slots[j].pc > pos)-                            s->line_number_slots[j].pc -= delta;-                    }-                    continue;-                }-                break;-            }-        }-        if (patch_offsets) {-            JumpSlot *jp1;-            int j;-            for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) {-                int diff1 = s->label_slots[jp1->label].addr - jp1->pos;-                switch (jp1->size) {-                case 1:-                    put_u8(bc_out.buf + jp1->pos, diff1);-                    break;-                case 2:-                    put_u16(bc_out.buf + jp1->pos, diff1);-                    break;-                case 4:-                    put_u32(bc_out.buf + jp1->pos, diff1);-                    break;-                }-            }-        }-    }-    js_free(ctx, s->jump_slots);-    s->jump_slots = NULL;-#endif-    js_free(ctx, s->label_slots);-    s->label_slots = NULL;-    /* XXX: should delay until copying to runtime bytecode function */-    compute_pc2line_info(s);-    js_free(ctx, s->line_number_slots);-    s->line_number_slots = NULL;-    /* set the new byte code */-    dbuf_free(&s->byte_code);-    s->byte_code = bc_out;-    s->use_short_opcodes = TRUE;-    if (dbuf_error(&s->byte_code)) {-        JS_ThrowOutOfMemory(ctx);-        return -1;-    }-    return 0;- fail:-    /* XXX: not safe */-    dbuf_free(&bc_out);-    return -1;-}--/* compute the maximum stack size needed by the function */--typedef struct StackSizeState {-    int stack_len_max;-    uint16_t *stack_level_tab;-} StackSizeState;--static __exception int compute_stack_size_rec(JSContext *ctx,-                                              JSFunctionDef *fd,-                                              StackSizeState *s,-                                              int pos, int op, int stack_len)-{-    int bc_len, diff, n_pop, pos_next;-    const JSOpCode *oi;-    const uint8_t *bc_buf;--    if (stack_len > s->stack_len_max) {-        s->stack_len_max = stack_len;-        if (s->stack_len_max > JS_STACK_SIZE_MAX)-            goto stack_overflow;-    }-    bc_buf = fd->byte_code.buf;-    bc_len = fd->byte_code.size;-    for(;;) {-        if ((unsigned)pos >= bc_len)-            goto buf_overflow;-#if 0-        printf("%5d: %d\n", pos, stack_len);-#endif-        if (s->stack_level_tab[pos] != 0xffff) {-            /* already explored: check that the stack size is consistent */-            if (s->stack_level_tab[pos] != stack_len) {-                JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",-                                      s->stack_level_tab[pos], stack_len, pos);-                return -1;-            } else {-                return 0;-            }-        } else {-            s->stack_level_tab[pos] = stack_len;-        }--        op = bc_buf[pos];-        if (op == 0 || op >= OP_COUNT) {-            JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos);-            return -1;-        }-        oi = &short_opcode_info(op);-        pos_next = pos + oi->size;-        if (pos_next > bc_len) {-        buf_overflow:-            JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);-            return -1;-        }-        n_pop = oi->n_pop;-        /* call pops a variable number of arguments */-        if (oi->fmt == OP_FMT_npop || oi->fmt == OP_FMT_npop_u16) {-            n_pop += get_u16(bc_buf + pos + 1);-        } else {-#if SHORT_OPCODES-            if (oi->fmt == OP_FMT_npopx) {-                n_pop += op - OP_call0;-            }-#endif-        }--        if (stack_len < n_pop) {-            JS_ThrowInternalError(ctx, "stack underflow (op=%d, pc=%d)", op, pos);-            return -1;-        }-        stack_len += oi->n_push - n_pop;-        if (stack_len > s->stack_len_max) {-            s->stack_len_max = stack_len;-            if (s->stack_len_max > JS_STACK_SIZE_MAX)-                goto stack_overflow;-        }-        switch(op) {-        case OP_tail_call:-        case OP_tail_call_method:-        case OP_return:-        case OP_return_undef:-        case OP_return_async:-        case OP_throw:-        case OP_throw_var:-        case OP_ret:-            goto done;-        case OP_goto:-            diff = get_u32(bc_buf + pos + 1);-            pos_next = pos + 1 + diff;-            break;-#if SHORT_OPCODES-        case OP_goto16:-            diff = (int16_t)get_u16(bc_buf + pos + 1);-            pos_next = pos + 1 + diff;-            break;-        case OP_goto8:-            diff = (int8_t)bc_buf[pos + 1];-            pos_next = pos + 1 + diff;-            break;-        case OP_if_true8:-        case OP_if_false8:-            diff = (int8_t)bc_buf[pos + 1];-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len))-                return -1;-            break;-#endif-        case OP_if_true:-        case OP_if_false:-        case OP_catch:-            diff = get_u32(bc_buf + pos + 1);-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len))-                return -1;-            break;-        case OP_gosub:-            diff = get_u32(bc_buf + pos + 1);-            if (compute_stack_size_rec(ctx, fd, s, pos + 1 + diff, op, stack_len + 1))-                return -1;-            break;-        case OP_with_get_var:-        case OP_with_delete_var:-            diff = get_u32(bc_buf + pos + 5);-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len + 1))-                return -1;-            break;-        case OP_with_make_ref:-        case OP_with_get_ref:-        case OP_with_get_ref_undef:-            diff = get_u32(bc_buf + pos + 5);-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len + 2))-                return -1;-            break;-        case OP_with_put_var:-            diff = get_u32(bc_buf + pos + 5);-            if (compute_stack_size_rec(ctx, fd, s, pos + 5 + diff, op, stack_len - 1))-                return -1;-            break;--        default:-            break;-        }-        pos = pos_next;-    }- done:-    return 0;-- stack_overflow:-    JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);-    return -1;-}--static __exception int compute_stack_size(JSContext *ctx,-                                          JSFunctionDef *fd,-                                          int *pstack_size)-{-    StackSizeState s_s, *s = &s_s;-    int bc_len, i, ret;--    bc_len = fd->byte_code.size;-    /* bc_len > 0 */-    s->stack_level_tab = js_malloc(ctx, sizeof(s->stack_level_tab[0]) * bc_len);-    if (!s->stack_level_tab)-        return -1;-    for(i = 0; i < bc_len; i++)-        s->stack_level_tab[i] = 0xffff;-    s->stack_len_max = 0;-    ret = compute_stack_size_rec(ctx, fd, s, 0, OP_invalid, 0);-    js_free(ctx, s->stack_level_tab);-    *pstack_size = s->stack_len_max;-    return ret;-}--static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)-{-    int i, idx;-    JSModuleDef *m = fd->module;-    JSExportEntry *me;-    JSHoistedDef *hf;--    /* The imported global variables were added as closure variables-       in js_parse_import(). We add here the module global-       variables. */--    for(i = 0; i < fd->hoisted_def_count; i++) {-        hf = &fd->hoisted_def[i];-        if (add_closure_var(ctx, fd, TRUE, FALSE, i, hf->var_name, hf->is_const,-                            hf->is_lexical, FALSE) < 0)-            return -1;-    }--    /* resolve the variable names of the local exports */-    for(i = 0; i < m->export_entries_count; i++) {-        me = &m->export_entries[i];-        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-            idx = find_closure_var(ctx, fd, me->local_name);-            if (idx < 0) {-                JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist",-                                        me->local_name);-                return -1;-            }-            me->u.local.var_idx = idx;-        }-    }-    return 0;-}--/* create a function object from a function definition. The function-   definition is freed. All the child functions are also created. It-   must be done this way to resolve all the variables. */-static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)-{-    JSValue func_obj;-    JSFunctionBytecode *b;-    struct list_head *el, *el1;-    int stack_size, scope, idx;-    int function_size, byte_code_offset, cpool_offset;-    int closure_var_offset, vardefs_offset;--    /* recompute scope linkage */-    for (scope = 0; scope < fd->scope_count; scope++) {-        fd->scopes[scope].first = -1;-    }-    for (idx = 0; idx < fd->var_count; idx++) {-        JSVarDef *vd = &fd->vars[idx];-        vd->scope_next = fd->scopes[vd->scope_level].first;-        fd->scopes[vd->scope_level].first = idx;-    }-    for (scope = 2; scope < fd->scope_count; scope++) {-        JSVarScope *sd = &fd->scopes[scope];-        if (sd->first == -1)-            sd->first = fd->scopes[sd->parent].first;-    }-    for (idx = 0; idx < fd->var_count; idx++) {-        JSVarDef *vd = &fd->vars[idx];-        if (vd->scope_next == -1 && vd->scope_level > 1) {-            scope = fd->scopes[vd->scope_level].parent;-            vd->scope_next = fd->scopes[scope].first;-        }-    }--    /* if the function contains an eval call, the closure variables-       are used to compile the eval and they must be ordered by scope,-       so it is necessary to create the closure variables before any-       other variable lookup is done. */-    if (fd->has_eval_call)-        add_eval_variables(ctx, fd);--    /* add the module global variables in the closure */-    if (fd->module) {-        if (add_module_variables(ctx, fd))-            goto fail;-    }--    /* first create all the child functions */-    list_for_each_safe(el, el1, &fd->child_list) {-        JSFunctionDef *fd1;-        int cpool_idx;--        fd1 = list_entry(el, JSFunctionDef, link);-        cpool_idx = fd1->parent_cpool_idx;-        func_obj = js_create_function(ctx, fd1);-        if (JS_IsException(func_obj))-            goto fail;-        /* save it in the constant pool */-        assert(cpool_idx >= 0);-        fd->cpool[cpool_idx] = func_obj;-    }--#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4)-    if (!(fd->js_mode & JS_MODE_STRIP)) {-        printf("pass 1\n");-        dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size,-                       fd->args, fd->arg_count, fd->vars, fd->var_count,-                       fd->closure_var, fd->closure_var_count,-                       fd->cpool, fd->cpool_count, fd->source, fd->line_num,-                       fd->label_slots, NULL);-        printf("\n");-    }-#endif--    if (resolve_variables(ctx, fd))-        goto fail;--#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2)-    if (!(fd->js_mode & JS_MODE_STRIP)) {-        printf("pass 2\n");-        dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size,-                       fd->args, fd->arg_count, fd->vars, fd->var_count,-                       fd->closure_var, fd->closure_var_count,-                       fd->cpool, fd->cpool_count, fd->source, fd->line_num,-                       fd->label_slots, NULL);-        printf("\n");-    }-#endif--    if (resolve_labels(ctx, fd))-        goto fail;--    if (compute_stack_size(ctx, fd, &stack_size) < 0)-        goto fail;--    if (fd->js_mode & JS_MODE_STRIP) {-        function_size = offsetof(JSFunctionBytecode, debug);-    } else {-        function_size = sizeof(*b);-    }-    cpool_offset = function_size;-    function_size += fd->cpool_count * sizeof(*fd->cpool);-    vardefs_offset = function_size;-    if (!(fd->js_mode & JS_MODE_STRIP) || fd->has_eval_call) {-        function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs);-    }-    closure_var_offset = function_size;-    function_size += fd->closure_var_count * sizeof(*fd->closure_var);-    byte_code_offset = function_size;-    function_size += fd->byte_code.size;--    b = js_mallocz(ctx, function_size);-    if (!b)-        goto fail;-    b->header.ref_count = 1;--    b->byte_code_buf = (void *)((uint8_t*)b + byte_code_offset);-    b->byte_code_len = fd->byte_code.size;-    memcpy(b->byte_code_buf, fd->byte_code.buf, fd->byte_code.size);-    js_free(ctx, fd->byte_code.buf);-    fd->byte_code.buf = NULL;--    b->func_name = fd->func_name;-    if (fd->arg_count + fd->var_count > 0) {-        if ((fd->js_mode & JS_MODE_STRIP) && !fd->has_eval_call) {-            /* Strip variable definitions not needed at runtime */-            int i;-            for(i = 0; i < fd->var_count; i++) {-                JS_FreeAtom(ctx, fd->vars[i].var_name);-            }-            for(i = 0; i < fd->arg_count; i++) {-                JS_FreeAtom(ctx, fd->args[i].var_name);-            }-            for(i = 0; i < fd->closure_var_count; i++) {-                JS_FreeAtom(ctx, fd->closure_var[i].var_name);-                fd->closure_var[i].var_name = JS_ATOM_NULL;-            }-        } else {-            b->vardefs = (void *)((uint8_t*)b + vardefs_offset);-            memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));-            memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));-        }-        b->var_count = fd->var_count;-        b->arg_count = fd->arg_count;-        b->defined_arg_count = fd->defined_arg_count;-        js_free(ctx, fd->args);-        js_free(ctx, fd->vars);-    }-    b->cpool_count = fd->cpool_count;-    if (b->cpool_count) {-        b->cpool = (void *)((uint8_t*)b + cpool_offset);-        memcpy(b->cpool, fd->cpool, b->cpool_count * sizeof(*b->cpool));-    }-    js_free(ctx, fd->cpool);-    fd->cpool = NULL;--    b->stack_size = stack_size;--    if (fd->js_mode & JS_MODE_STRIP) {-        JS_FreeAtom(ctx, fd->filename);-        dbuf_free(&fd->pc2line);    // probably useless-    } else {-        /* XXX: source and pc2line info should be packed at the end of the-           JSFunctionBytecode structure, avoiding allocation overhead-         */-        b->has_debug = 1;-        b->debug.filename = fd->filename;-        b->debug.line_num = fd->line_num;--        //DynBuf pc2line;-        //compute_pc2line_info(fd, &pc2line);-        //js_free(ctx, fd->line_number_slots)-        b->debug.pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size);-        if (!b->debug.pc2line_buf)-            b->debug.pc2line_buf = fd->pc2line.buf;-        b->debug.pc2line_len = fd->pc2line.size;-        b->debug.source = fd->source;-        b->debug.source_len = fd->source_len;-    }-    if (fd->scopes != fd->def_scope_array)-        js_free(ctx, fd->scopes);--    b->closure_var_count = fd->closure_var_count;-    if (b->closure_var_count) {-        b->closure_var = (void *)((uint8_t*)b + closure_var_offset);-        memcpy(b->closure_var, fd->closure_var, b->closure_var_count * sizeof(*b->closure_var));-    }-    js_free(ctx, fd->closure_var);-    fd->closure_var = NULL;--    b->has_prototype = fd->has_prototype;-    b->has_simple_parameter_list = fd->has_simple_parameter_list;-    b->js_mode = fd->js_mode;-    b->is_derived_class_constructor = fd->is_derived_class_constructor;-    b->func_kind = fd->func_kind;-    b->need_home_object = (fd->home_object_var_idx >= 0 ||-                           fd->need_home_object);-    b->new_target_allowed = fd->new_target_allowed;-    b->super_call_allowed = fd->super_call_allowed;-    b->super_allowed = fd->super_allowed;-    b->arguments_allowed = fd->arguments_allowed;-    b->backtrace_barrier = fd->backtrace_barrier;-    b->realm = JS_DupContext(ctx);--    add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);-    -#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1)-    if (!(fd->js_mode & JS_MODE_STRIP)) {-        js_dump_function_bytecode(ctx, b);-    }-#endif--    if (fd->parent) {-        /* remove from parent list */-        list_del(&fd->link);-    }--    js_free(ctx, fd);-    return JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);- fail:-    js_free_function_def(ctx, fd);-    return JS_EXCEPTION;-}--static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)-{-    int i;--#if 0-    {-        char buf[ATOM_GET_STR_BUF_SIZE];-        printf("freeing %s\n",-               JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));-    }-#endif-    free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE);--    if (b->vardefs) {-        for(i = 0; i < b->arg_count + b->var_count; i++) {-            JS_FreeAtomRT(rt, b->vardefs[i].var_name);-        }-    }-    for(i = 0; i < b->cpool_count; i++)-        JS_FreeValueRT(rt, b->cpool[i]);--    for(i = 0; i < b->closure_var_count; i++) {-        JSClosureVar *cv = &b->closure_var[i];-        JS_FreeAtomRT(rt, cv->var_name);-    }-    if (b->realm)-        JS_FreeContext(b->realm);--    JS_FreeAtomRT(rt, b->func_name);-    if (b->has_debug) {-        JS_FreeAtomRT(rt, b->debug.filename);-        js_free_rt(rt, b->debug.pc2line_buf);-        js_free_rt(rt, b->debug.source);-    }--    remove_gc_object(&b->header);-    if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) {-        list_add_tail(&b->header.link, &rt->gc_zero_ref_count_list);-    } else {-        js_free_rt(rt, b);-    }-}--static __exception int js_parse_directives(JSParseState *s)-{-    char str[20];-    JSParsePos pos;-    BOOL has_semi;--    if (s->token.val != TOK_STRING)-        return 0;--    js_parse_get_pos(s, &pos);--    while(s->token.val == TOK_STRING) {-        /* Copy actual source string representation */-        snprintf(str, sizeof str, "%.*s",-                 (int)(s->buf_ptr - s->token.ptr - 2), s->token.ptr + 1);--        if (next_token(s))-            return -1;--        has_semi = FALSE;-        switch (s->token.val) {-        case ';':-            if (next_token(s))-                return -1;-            has_semi = TRUE;-            break;-        case '}':-        case TOK_EOF:-            has_semi = TRUE;-            break;-        case TOK_NUMBER:-        case TOK_STRING:-        case TOK_TEMPLATE:-        case TOK_IDENT:-        case TOK_REGEXP:-        case TOK_DEC:-        case TOK_INC:-        case TOK_NULL:-        case TOK_FALSE:-        case TOK_TRUE:-        case TOK_IF:-        case TOK_RETURN:-        case TOK_VAR:-        case TOK_THIS:-        case TOK_DELETE:-        case TOK_TYPEOF:-        case TOK_NEW:-        case TOK_DO:-        case TOK_WHILE:-        case TOK_FOR:-        case TOK_SWITCH:-        case TOK_THROW:-        case TOK_TRY:-        case TOK_FUNCTION:-        case TOK_DEBUGGER:-        case TOK_WITH:-        case TOK_CLASS:-        case TOK_CONST:-        case TOK_ENUM:-        case TOK_EXPORT:-        case TOK_IMPORT:-        case TOK_SUPER:-        case TOK_INTERFACE:-        case TOK_LET:-        case TOK_PACKAGE:-        case TOK_PRIVATE:-        case TOK_PROTECTED:-        case TOK_PUBLIC:-        case TOK_STATIC:-            /* automatic insertion of ';' */-            if (s->got_lf)-                has_semi = TRUE;-            break;-        default:-            break;-        }-        if (!has_semi)-            break;-        if (!strcmp(str, "use strict")) {-            s->cur_func->has_use_strict = TRUE;-            s->cur_func->js_mode |= JS_MODE_STRICT;-        }-#if !defined(DUMP_BYTECODE) || !(DUMP_BYTECODE & 8)-        else if (!strcmp(str, "use strip")) {-            s->cur_func->js_mode |= JS_MODE_STRIP;-        }-#endif-#ifdef CONFIG_BIGNUM-        else if (s->ctx->bignum_ext && !strcmp(str, "use math")) {-            s->cur_func->js_mode |= JS_MODE_MATH;-        }-#endif-    }-    return js_parse_seek_token(s, &pos);-}--static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,-                                         JSAtom func_name)-{-    JSAtom name;-    int i, idx;--    if (fd->js_mode & JS_MODE_STRICT) {-        if (!fd->has_simple_parameter_list && fd->has_use_strict) {-            return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");-        }-        if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) {-            return js_parse_error(s, "invalid function name in strict code");-        }-        for (idx = 0; idx < fd->arg_count; idx++) {-            name = fd->args[idx].var_name;--            if (name == JS_ATOM_eval || name == JS_ATOM_arguments) {-                return js_parse_error(s, "invalid argument name in strict code");-            }-        }-    }-    /* check async_generator case */-    if ((fd->js_mode & JS_MODE_STRICT)-    ||  !fd->has_simple_parameter_list-    ||  (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC)-    ||  fd->func_type == JS_PARSE_FUNC_ARROW-    ||  fd->func_type == JS_PARSE_FUNC_METHOD) {-        for (idx = 0; idx < fd->arg_count; idx++) {-            name = fd->args[idx].var_name;-            if (name != JS_ATOM_NULL) {-                for (i = 0; i < idx; i++) {-                    if (fd->args[i].var_name == name)-                        goto duplicate;-                }-                /* Check if argument name duplicates a destructuring parameter */-                /* XXX: should have a flag for such variables */-                for (i = 0; i < fd->var_count; i++) {-                    if (fd->vars[i].var_name == name)-                        goto duplicate;-                }-            }-        }-    }-    return 0;--duplicate:-    return js_parse_error(s, "duplicate argument names not allowed in this context");-}--/* create a function to initialize class fields */-static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)-{-    JSFunctionDef *fd;-    -    fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE,-                             s->filename, 0);-    if (!fd)-        return NULL;-    fd->func_name = JS_ATOM_NULL;-    fd->has_prototype = FALSE;-    fd->has_home_object = TRUE;-    -    fd->has_arguments_binding = FALSE;-    fd->has_this_binding = TRUE;-    fd->is_derived_class_constructor = FALSE;-    fd->new_target_allowed = TRUE;-    fd->super_call_allowed = FALSE;-    fd->super_allowed = fd->has_home_object;-    fd->arguments_allowed = FALSE;-    -    fd->func_kind = JS_FUNC_NORMAL;-    fd->func_type = JS_PARSE_FUNC_METHOD;-    return fd;-}--/* func_name must be JS_ATOM_NULL for JS_PARSE_FUNC_STATEMENT and-   JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW and JS_PARSE_FUNC_VAR */-static __exception int js_parse_function_decl2(JSParseState *s,-                                               JSParseFunctionEnum func_type,-                                               JSFunctionKindEnum func_kind,-                                               JSAtom func_name,-                                               const uint8_t *ptr,-                                               int function_line_num,-                                               JSParseExportEnum export_flag,-                                               JSFunctionDef **pfd)-{-    JSContext *ctx = s->ctx;-    JSFunctionDef *fd = s->cur_func;-    BOOL is_expr;-    int func_idx, lexical_func_idx = -1;-    BOOL has_opt_arg;-    BOOL create_func_var = FALSE;--    is_expr = (func_type != JS_PARSE_FUNC_STATEMENT &&-               func_type != JS_PARSE_FUNC_VAR);--    if (func_type == JS_PARSE_FUNC_STATEMENT ||-        func_type == JS_PARSE_FUNC_VAR ||-        func_type == JS_PARSE_FUNC_EXPR) {-        if (func_kind == JS_FUNC_NORMAL &&-            token_is_pseudo_keyword(s, JS_ATOM_async) &&-            peek_token(s, TRUE) != '\n') {-            if (next_token(s))-                return -1;-            func_kind = JS_FUNC_ASYNC;-        }-        if (next_token(s))-            return -1;-        if (s->token.val == '*') {-            if (next_token(s))-                return -1;-            func_kind |= JS_FUNC_GENERATOR;-        }--        if (s->token.val == TOK_IDENT) {-            if (s->token.u.ident.is_reserved ||-                (s->token.u.ident.atom == JS_ATOM_yield &&-                 func_type == JS_PARSE_FUNC_EXPR &&-                 (func_kind & JS_FUNC_GENERATOR)) ||-                (s->token.u.ident.atom == JS_ATOM_await &&-                 func_type == JS_PARSE_FUNC_EXPR &&-                 (func_kind & JS_FUNC_ASYNC))) {-                return js_parse_error_reserved_identifier(s);-            }-        }-        if (s->token.val == TOK_IDENT ||-            (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) ||-             (s->token.val == TOK_AWAIT && !s->is_module)) &&-             func_type == JS_PARSE_FUNC_EXPR)) {-            func_name = JS_DupAtom(ctx, s->token.u.ident.atom);-            if (next_token(s)) {-                JS_FreeAtom(ctx, func_name);-                return -1;-            }-        } else {-            if (func_type != JS_PARSE_FUNC_EXPR &&-                export_flag != JS_PARSE_EXPORT_DEFAULT) {-                return js_parse_error(s, "function name expected");-            }-        }-    } else if (func_type != JS_PARSE_FUNC_ARROW) {-        func_name = JS_DupAtom(ctx, func_name);-    }--    if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_MODULE &&-        (func_type == JS_PARSE_FUNC_STATEMENT || func_type == JS_PARSE_FUNC_VAR)) {-        JSHoistedDef *hf;-        hf = find_hoisted_def(fd, func_name);-        /* XXX: should check scope chain */-        if (hf && hf->scope_level == fd->scope_level) {-            js_parse_error(s, "invalid redefinition of global identifier in module code");-            JS_FreeAtom(ctx, func_name);-            return -1;-        }-    }--    if (func_type == JS_PARSE_FUNC_VAR) {-        /* Create lexical name here so function closure contains it */-        if (!(fd->js_mode & JS_MODE_STRICT)-        &&  find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0-        &&  !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))-        &&  !(func_name == JS_ATOM_arguments && fd->has_arguments_binding)) {-            create_func_var = TRUE;-        }-        if (fd->is_eval &&-            (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||-             fd->eval_type == JS_EVAL_TYPE_MODULE) &&-            fd->scope_level == 1) {-            /* avoid creating a lexical variable in the global-               scope. XXX: check annex B */-            JSHoistedDef *hf;-            hf = find_hoisted_def(fd, func_name);-            /* XXX: should check scope chain */-            if (hf && hf->scope_level == fd->scope_level) {-                js_parse_error(s, "invalid redefinition of global identifier");-                JS_FreeAtom(ctx, func_name);-                return -1;-            }-        } else {-            /* Always create a lexical name, fail if at the same scope as-               existing name */-            /* Lexical variable will be initialized upon entering scope */-            lexical_func_idx = define_var(s, fd, func_name,-                                          func_kind != JS_FUNC_NORMAL ?-                                          JS_VAR_DEF_NEW_FUNCTION_DECL :-                                          JS_VAR_DEF_FUNCTION_DECL);-            if (lexical_func_idx < 0) {-                JS_FreeAtom(ctx, func_name);-                return -1;-            }-        }-    }--    fd = js_new_function_def(ctx, fd, FALSE, is_expr,-                             s->filename, function_line_num);-    if (!fd) {-        JS_FreeAtom(ctx, func_name);-        return -1;-    }-    if (pfd)-        *pfd = fd;-    s->cur_func = fd;-    fd->func_name = func_name;-    /* XXX: test !fd->is_generator is always false */-    fd->has_prototype = (func_type == JS_PARSE_FUNC_STATEMENT ||-                         func_type == JS_PARSE_FUNC_VAR ||-                         func_type == JS_PARSE_FUNC_EXPR) &&-                        func_kind == JS_FUNC_NORMAL;-    fd->has_home_object = (func_type == JS_PARSE_FUNC_METHOD ||-                           func_type == JS_PARSE_FUNC_GETTER ||-                           func_type == JS_PARSE_FUNC_SETTER ||-                           func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||-                           func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);-    fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW);-    fd->has_this_binding = fd->has_arguments_binding;-    fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);-    if (func_type == JS_PARSE_FUNC_ARROW) {-        fd->new_target_allowed = fd->parent->new_target_allowed;-        fd->super_call_allowed = fd->parent->super_call_allowed;-        fd->super_allowed = fd->parent->super_allowed;-        fd->arguments_allowed = fd->parent->arguments_allowed;-    } else {-        fd->new_target_allowed = TRUE;-        fd->super_call_allowed = fd->is_derived_class_constructor;-        fd->super_allowed = fd->has_home_object;-        fd->arguments_allowed = TRUE;-    }--    /* fd->in_function_body == FALSE prevents yield/await during the parsing-       of the arguments in generator/async functions. They are parsed as-       regular identifiers for other function kinds. */-    fd->func_kind = func_kind;-    fd->func_type = func_type;--    if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||-        func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR) {-        /* error if not invoked as a constructor */-        emit_op(s, OP_check_ctor);-    }--    if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {-        emit_class_field_init(s);-    }-    -    /* parse arguments */-    fd->has_simple_parameter_list = TRUE;-    has_opt_arg = FALSE;-    if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {-        JSAtom name;-        if (s->token.u.ident.is_reserved) {-            js_parse_error_reserved_identifier(s);-            goto fail;-        }-        name = s->token.u.ident.atom;-        if (add_arg(ctx, fd, name) < 0)-            goto fail;-        fd->defined_arg_count = 1;-    } else {-        if (js_parse_expect(s, '('))-            goto fail;--        while (s->token.val != ')') {-            JSAtom name;-            BOOL rest = FALSE;-            int idx;--            if (s->token.val == TOK_ELLIPSIS) {-                fd->has_simple_parameter_list = FALSE;-                rest = TRUE;-                if (next_token(s))-                    goto fail;-            }-            if (s->token.val == '[' || s->token.val == '{') {-                fd->has_simple_parameter_list = FALSE;-                if (rest) {-                    emit_op(s, OP_rest);-                    emit_u16(s, fd->arg_count);-                } else {-                    /* unnamed arg for destructuring */-                    idx = add_arg(ctx, fd, JS_ATOM_NULL);-                    emit_op(s, OP_get_arg);-                    emit_u16(s, idx);-                }-                if (js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE))-                    goto fail;-            } else if (s->token.val == TOK_IDENT) {-                if (s->token.u.ident.is_reserved) {-                    js_parse_error_reserved_identifier(s);-                    goto fail;-                }-                name = s->token.u.ident.atom;-                if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {-                    js_parse_error_reserved_identifier(s);-                    goto fail;-                }-                idx = add_arg(ctx, fd, name);-                if (idx < 0)-                    goto fail;-                if (next_token(s))-                    goto fail;-                if (rest) {-                    emit_op(s, OP_rest);-                    emit_u16(s, idx);-                    emit_op(s, OP_put_arg);-                    emit_u16(s, idx);-                    fd->has_simple_parameter_list = FALSE;-                    has_opt_arg = TRUE;-                } else if (s->token.val == '=') {-                    fd->has_simple_parameter_list = FALSE;-                    has_opt_arg = TRUE;--                    if (next_token(s))-                        goto fail;--                    /* optimize `x = void 0` default value: no code needed */-                    if (s->token.val == TOK_VOID) {-                        JSParsePos pos;-                        js_parse_get_pos(s, &pos);-                        if (next_token(s))-                            goto fail;-                        if (s->token.val == TOK_NUMBER) {-                            if (next_token(s))-                                goto fail;-                            if (s->token.val == ',') {-                                if (next_token(s))-                                    goto fail;-                                continue;-                            }-                            if (s->token.val == ')') {-                                continue;-                            }-                        }-                        if (js_parse_seek_token(s, &pos))-                            goto fail;-                    }-#if 0-                    /* XXX: not correct for eval code */-                    /* Check for a default value of `undefined`-                       to omit default argument processing */-                    if (s->token.val == TOK_IDENT &&-                        s->token.u.ident.atom == JS_ATOM_undefined &&-                        fd->parent == NULL &&-                        ((tok = peek_token(s, FALSE)) == ',' || tok == ')')) {-                        if (next_token(s))  /* ignore undefined token */-                            goto fail;-                    } else-#endif-                    {-                        int label = new_label(s);-                        if (idx > 0) {-                            emit_op(s, OP_set_arg_valid_upto);-                            emit_u16(s, idx);-                        }-                        emit_op(s, OP_get_arg);-                        emit_u16(s, idx);-                        emit_op(s, OP_undefined);-                        emit_op(s, OP_strict_eq);-                        emit_goto(s, OP_if_false, label);-                        if (js_parse_assign_expr(s, TRUE))-                            goto fail;-                        set_object_name(s, name);-                        emit_op(s, OP_put_arg);-                        emit_u16(s, idx);-                        emit_label(s, label);-                    }-                } else if (!has_opt_arg) {-                    fd->defined_arg_count++;-                }-            } else {-                js_parse_error(s, "missing formal parameter");-                goto fail;-            }-            if (rest && s->token.val != ')') {-                js_parse_expect(s, ')');-                goto fail;-            }-            if (s->token.val == ')')-                break;-            if (js_parse_expect(s, ','))-                goto fail;-        }-        if ((func_type == JS_PARSE_FUNC_GETTER && fd->arg_count != 0) ||-            (func_type == JS_PARSE_FUNC_SETTER && fd->arg_count != 1)) {-            js_parse_error(s, "invalid number of arguments for getter or setter");-            goto fail;-        }-    }--    if (next_token(s))-        goto fail;--    /* generator function: yield after the parameters are evaluated */-    if (func_kind == JS_FUNC_GENERATOR ||-        func_kind == JS_FUNC_ASYNC_GENERATOR)-        emit_op(s, OP_initial_yield);--    /* in generators, yield expression is forbidden during the parsing-       of the arguments */-    fd->in_function_body = TRUE;-    push_scope(s);  /* enter body scope: fd->scope_level = 1 */--    if (s->token.val == TOK_ARROW) {-        if (next_token(s))-            goto fail;--        if (s->token.val != '{') {-            if (js_parse_function_check_names(s, fd, func_name))-                goto fail;--            if (js_parse_assign_expr(s, TRUE))-                goto fail;--            if (func_kind != JS_FUNC_NORMAL)-                emit_op(s, OP_return_async);-            else-                emit_op(s, OP_return);--            if (!(fd->js_mode & JS_MODE_STRIP)) {-                /* save the function source code */-                /* the end of the function source code is after the last-                   token of the function source stored into s->last_ptr */-                fd->source_len = s->last_ptr - ptr;-                fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);-                if (!fd->source)-                    goto fail;-            }-            goto done;-        }-    }--    if (js_parse_expect(s, '{'))-        goto fail;--    if (js_parse_directives(s))-        goto fail;--    /* in strict_mode, check function and argument names */-    if (js_parse_function_check_names(s, fd, func_name))-        goto fail;--    while (s->token.val != '}') {-        if (js_parse_source_element(s))-            goto fail;-    }-    if (!(fd->js_mode & JS_MODE_STRIP)) {-        /* save the function source code */-        fd->source_len = s->buf_ptr - ptr;-        fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);-        if (!fd->source)-            goto fail;-    }--    if (next_token(s)) {-        /* consume the '}' */-        goto fail;-    }--    /* in case there is no return, add one */-    if (js_is_live_code(s)) {-        emit_return(s, FALSE);-    }-done:-    s->cur_func = fd->parent;--    /* create the function object */-    {-        int idx;-        JSAtom func_name = fd->func_name;--        /* the real object will be set at the end of the compilation */-        idx = cpool_add(s, JS_NULL);-        fd->parent_cpool_idx = idx;--        if (is_expr) {-            /* for constructors, no code needs to be generated here */-            if (func_type != JS_PARSE_FUNC_CLASS_CONSTRUCTOR &&-                func_type != JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR) {-                /* OP_fclosure creates the function object from the bytecode-                   and adds the scope information */-                emit_op(s, OP_fclosure);-                emit_u32(s, idx);-                if (func_name == JS_ATOM_NULL) {-                    emit_op(s, OP_set_name);-                    emit_u32(s, JS_ATOM_NULL);-                }-            }-        } else if (func_type == JS_PARSE_FUNC_VAR) {-            emit_op(s, OP_fclosure);-            emit_u32(s, idx);-            if (create_func_var) {-                if (s->cur_func->is_global_var) {-                    JSHoistedDef *hf;-                    /* the global variable must be defined at the start of the-                       function */-                    hf = add_hoisted_def(ctx, s->cur_func, -1, func_name, -1, FALSE);-                    if (!hf)-                        goto fail;-                    /* it is considered as defined at the top level-                       (needed for annex B.3.3.4 and B.3.3.5-                       checks) */-                    hf->scope_level = 0; -                    hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0);-                    /* store directly into global var, bypass lexical scope */-                    emit_op(s, OP_dup);-                    emit_op(s, OP_scope_put_var);-                    emit_atom(s, func_name);-                    emit_u16(s, 0);-                } else {-                    /* do not call define_var to bypass lexical scope check */-                    func_idx = find_var(ctx, s->cur_func, func_name);-                    if (func_idx < 0) {-                        func_idx = add_var(ctx, s->cur_func, func_name);-                        if (func_idx < 0)-                            goto fail;-                    }-                    /* store directly into local var, bypass lexical catch scope */-                    emit_op(s, OP_dup);-                    emit_op(s, OP_scope_put_var);-                    emit_atom(s, func_name);-                    emit_u16(s, 0);-                }-            }-            if (lexical_func_idx >= 0) {-                /* lexical variable will be initialized upon entering scope */-                s->cur_func->vars[lexical_func_idx].func_pool_or_scope_idx = idx;-                emit_op(s, OP_drop);-            } else {-                /* store function object into its lexical name */-                /* XXX: could use OP_put_loc directly */-                emit_op(s, OP_scope_put_var_init);-                emit_atom(s, func_name);-                emit_u16(s, s->cur_func->scope_level);-            }-        } else {-            if (!s->cur_func->is_global_var) {-                int var_idx = define_var(s, s->cur_func, func_name, JS_VAR_DEF_VAR);--                if (var_idx < 0)-                    goto fail;-                /* the variable will be assigned at the top of the function */-                if (!add_hoisted_def(ctx, s->cur_func, idx, JS_ATOM_NULL, var_idx, FALSE))-                    goto fail;-            } else {-                JSAtom func_var_name;-                if (func_name == JS_ATOM_NULL)-                    func_var_name = JS_ATOM__default_; /* export default */-                else-                    func_var_name = func_name;-                /* the variable will be assigned at the top of the function */-                if (!add_hoisted_def(ctx, s->cur_func, idx, func_var_name, -1, FALSE))-                    goto fail;-                if (export_flag != JS_PARSE_EXPORT_NONE) {-                    if (!add_export_entry(s, s->cur_func->module, func_var_name,-                                          export_flag == JS_PARSE_EXPORT_NAMED ? func_var_name : JS_ATOM_default, JS_EXPORT_TYPE_LOCAL))-                        goto fail;-                }-            }-        }-    }-    return 0;- fail:-    s->cur_func = fd->parent;-    js_free_function_def(ctx, fd);-    if (pfd)-        *pfd = NULL;-    return -1;-}--static __exception int js_parse_function_decl(JSParseState *s,-                                              JSParseFunctionEnum func_type,-                                              JSFunctionKindEnum func_kind,-                                              JSAtom func_name,-                                              const uint8_t *ptr,-                                              int function_line_num)-{-    return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr,-                                   function_line_num, JS_PARSE_EXPORT_NONE,-                                   NULL);-}--static __exception int js_parse_program(JSParseState *s)-{-    JSFunctionDef *fd = s->cur_func;-    int idx;--    if (next_token(s))-        return -1;--    if (js_parse_directives(s))-        return -1;--    fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) ||-        (fd->eval_type == JS_EVAL_TYPE_MODULE) ||-        !(fd->js_mode & JS_MODE_STRICT);--    if (!s->is_module) {-        /* hidden variable for the return value */-        fd->eval_ret_idx = idx = add_var(s->ctx, fd, JS_ATOM__ret_);-        if (idx < 0)-            return -1;-    }--    while (s->token.val != TOK_EOF) {-        if (js_parse_source_element(s))-            return -1;-    }--    if (!s->is_module) {-        /* return the value of the hidden variable eval_ret_idx  */-        emit_op(s, OP_get_loc);-        emit_u16(s, fd->eval_ret_idx);--        emit_op(s, OP_return);-    } else {-        emit_op(s, OP_return_undef);-    }--    return 0;-}--static void js_parse_init(JSContext *ctx, JSParseState *s,-                          const char *input, size_t input_len,-                          const char *filename)-{-    memset(s, 0, sizeof(*s));-    s->ctx = ctx;-    s->filename = filename;-    s->line_num = 1;-    s->buf_ptr = (const uint8_t *)input;-    s->buf_end = s->buf_ptr + input_len;-    s->token.val = ' ';-    s->token.line_num = 1;-}--static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,-                                       JSValueConst this_obj,-                                       JSVarRef **var_refs, JSStackFrame *sf)-{-    JSValue ret_val;-    uint32_t tag;--    tag = JS_VALUE_GET_TAG(fun_obj);-    if (tag == JS_TAG_FUNCTION_BYTECODE) {-        fun_obj = js_closure(ctx, fun_obj, var_refs, sf);-        ret_val = JS_CallFree(ctx, fun_obj, this_obj, 0, NULL);-    } else if (tag == JS_TAG_MODULE) {-        JSModuleDef *m;-        m = JS_VALUE_GET_PTR(fun_obj);-        /* the module refcount should be >= 2 */-        JS_FreeValue(ctx, fun_obj);-        if (js_create_module_function(ctx, m) < 0)-            goto fail;-        if (js_instantiate_module(ctx, m) < 0)-            goto fail;-        ret_val = js_evaluate_module(ctx, m);-        if (JS_IsException(ret_val)) {-        fail:-            js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED);-            return JS_EXCEPTION;-        }-    } else {-        JS_FreeValue(ctx, fun_obj);-        ret_val = JS_ThrowTypeError(ctx, "bytecode function expected");-    }-    return ret_val;-}--JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)-{-    return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_obj, NULL, NULL);-}--static void skip_shebang(JSParseState *s)-{-    const uint8_t *p = s->buf_ptr;-    int c;--    if (p[0] == '#' && p[1] == '!') {-        p += 2;-        while (p < s->buf_end) {-            if (*p == '\n' || *p == '\r') {-                break;-            } else if (*p >= 0x80) {-                c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);-                if (c == CP_LS || c == CP_PS) {-                    break;-                } else if (c == -1) {-                    p++; /* skip invalid UTF-8 */-                }-            } else {-                p++;-            }-        }-        s->buf_ptr = p;-    }-}--/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */-static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,-                                 const char *input, size_t input_len,-                                 const char *filename, int flags, int scope_idx)-{-    JSParseState s1, *s = &s1;-    int err, js_mode, eval_type;-    JSValue fun_obj, ret_val;-    JSStackFrame *sf;-    JSVarRef **var_refs;-    JSFunctionBytecode *b;-    JSFunctionDef *fd;-    JSModuleDef *m;--    js_parse_init(ctx, s, input, input_len, filename);-    skip_shebang(s);--    eval_type = flags & JS_EVAL_TYPE_MASK;-    m = NULL;-    if (eval_type == JS_EVAL_TYPE_DIRECT) {-        JSObject *p;-        sf = ctx->rt->current_stack_frame;-        assert(sf != NULL);-        assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);-        p = JS_VALUE_GET_OBJ(sf->cur_func);-        assert(js_class_has_bytecode(p->class_id));-        b = p->u.func.function_bytecode;-        var_refs = p->u.func.var_refs;-        js_mode = b->js_mode;-    } else {-        sf = NULL;-        b = NULL;-        var_refs = NULL;-        js_mode = 0;-        if (flags & JS_EVAL_FLAG_STRICT)-            js_mode |= JS_MODE_STRICT;-        if (flags & JS_EVAL_FLAG_STRIP)-            js_mode |= JS_MODE_STRIP;-        if (eval_type == JS_EVAL_TYPE_MODULE) {-            JSAtom module_name = JS_NewAtom(ctx, filename);-            if (module_name == JS_ATOM_NULL)-                return JS_EXCEPTION;-            m = js_new_module_def(ctx, module_name);-            if (!m)-                return JS_EXCEPTION;-            js_mode |= JS_MODE_STRICT;-        }-    }-    fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1);-    if (!fd)-        goto fail1;-    s->cur_func = fd;-    fd->eval_type = eval_type;-    fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT);-    fd->backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0);-    if (eval_type == JS_EVAL_TYPE_DIRECT) {-        fd->new_target_allowed = b->new_target_allowed;-        fd->super_call_allowed = b->super_call_allowed;-        fd->super_allowed = b->super_allowed;-        fd->arguments_allowed = b->arguments_allowed;-    } else {-        fd->new_target_allowed = FALSE;-        fd->super_call_allowed = FALSE;-        fd->super_allowed = FALSE;-        fd->arguments_allowed = TRUE;-    }-    fd->js_mode = js_mode;-    fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);-    if (b) {-        if (add_closure_variables(ctx, fd, b, scope_idx))-            goto fail;-    }-    fd->module = m;-    s->is_module = (m != NULL);-    s->allow_html_comments = !s->is_module;--    push_scope(s); /* body scope */--    err = js_parse_program(s);-    if (err) {-    fail:-        free_token(s, &s->token);-        js_free_function_def(ctx, fd);-        goto fail1;-    }--    /* create the function object and all the enclosed functions */-    fun_obj = js_create_function(ctx, fd);-    if (JS_IsException(fun_obj))-        goto fail1;-    /* Could add a flag to avoid resolution if necessary */-    if (m) {-        m->func_obj = fun_obj;-        if (js_resolve_module(ctx, m) < 0)-            goto fail1;-        fun_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));-    }-    if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {-        ret_val = fun_obj;-    } else {-        ret_val = JS_EvalFunctionInternal(ctx, fun_obj, this_obj, var_refs, sf);-    }-    return ret_val;- fail1:-    /* XXX: should free all the unresolved dependencies */-    if (m)-        js_free_module_def(ctx, m);-    return JS_EXCEPTION;-}--/* the indirection is needed to make 'eval' optional */-static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,-                               const char *input, size_t input_len,-                               const char *filename, int flags, int scope_idx)-{-    if (unlikely(!ctx->eval_internal)) {-        return JS_ThrowTypeError(ctx, "eval is not supported");-    }-    return ctx->eval_internal(ctx, this_obj, input, input_len, filename,-                              flags, scope_idx);-}--static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,-                             JSValueConst val, int flags, int scope_idx)-{-    JSValue ret;-    const char *str;-    size_t len;--    if (!JS_IsString(val))-        return JS_DupValue(ctx, val);-    str = JS_ToCStringLen(ctx, &len, val);-    if (!str)-        return JS_EXCEPTION;-    ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", flags, scope_idx);-    JS_FreeCString(ctx, str);-    return ret;--}--JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,-                const char *filename, int eval_flags)-{-    int eval_type = eval_flags & JS_EVAL_TYPE_MASK;-    JSValue ret;--    assert(eval_type == JS_EVAL_TYPE_GLOBAL ||-           eval_type == JS_EVAL_TYPE_MODULE);-    ret = JS_EvalInternal(ctx, ctx->global_obj, input, input_len, filename,-                          eval_flags, -1);-    return ret;-}--int JS_ResolveModule(JSContext *ctx, JSValueConst obj)-{-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {-        JSModuleDef *m = JS_VALUE_GET_PTR(obj);-        if (js_resolve_module(ctx, m) < 0) {-            js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);-            return -1;-        }-    }-    return 0;-}--/*******************************************************************/-/* object list */--typedef struct {-    JSObject *obj;-    uint32_t hash_next; /* -1 if no next entry */-} JSObjectListEntry;--/* XXX: reuse it to optimize weak references */-typedef struct {-    JSObjectListEntry *object_tab;-    int object_count;-    int object_size;-    uint32_t *hash_table;-    uint32_t hash_size;-} JSObjectList;--static void js_object_list_init(JSObjectList *s)-{-    memset(s, 0, sizeof(*s));-}--static uint32_t js_object_list_get_hash(JSObject *p, uint32_t hash_size)-{-    return ((uintptr_t)p * 3163) & (hash_size - 1);-}--static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s,-                                 uint32_t new_hash_size)-{-    JSObjectListEntry *e;-    uint32_t i, h, *new_hash_table;--    new_hash_table = js_malloc(ctx, sizeof(new_hash_table[0]) * new_hash_size);-    if (!new_hash_table)-        return -1;-    js_free(ctx, s->hash_table);-    s->hash_table = new_hash_table;-    s->hash_size = new_hash_size;-    -    for(i = 0; i < s->hash_size; i++) {-        s->hash_table[i] = -1;-    }-    for(i = 0; i < s->object_count; i++) {-        e = &s->object_tab[i];-        h = js_object_list_get_hash(e->obj, s->hash_size); -        e->hash_next = s->hash_table[h];-        s->hash_table[h] = i;-    }-    return 0;-}--/* the reference count of 'obj' is not modified. Return 0 if OK, -1 if-   memory error */-static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj)-{-    JSObjectListEntry *e;-    uint32_t h, new_hash_size;-    -    if (js_resize_array(ctx, (void *)&s->object_tab,-                        sizeof(s->object_tab[0]),-                        &s->object_size, s->object_count + 1))-        return -1;-    if (unlikely((s->object_count + 1) >= s->hash_size)) {-        new_hash_size = max_uint32(s->hash_size, 4);-        while (new_hash_size <= s->object_count)-            new_hash_size *= 2;-        if (js_object_list_resize_hash(ctx, s, new_hash_size))-            return -1;-    }-    e = &s->object_tab[s->object_count++];-    h = js_object_list_get_hash(obj, s->hash_size); -    e->obj = obj;-    e->hash_next = s->hash_table[h];-    s->hash_table[h] = s->object_count - 1;-    return 0;-}--/* return -1 if not present or the object index */-static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj)-{-    JSObjectListEntry *e;-    uint32_t h, p;--    /* must test empty size because there is no hash table */-    if (s->object_count == 0)-        return -1;-    h = js_object_list_get_hash(obj, s->hash_size); -    p = s->hash_table[h];-    while (p != -1) {-        e = &s->object_tab[p];-        if (e->obj == obj)-            return p;-        p = e->hash_next;-    }-    return -1;-}--static void js_object_list_end(JSContext *ctx, JSObjectList *s)-{-    js_free(ctx, s->object_tab);-    js_free(ctx, s->hash_table);-}--/*******************************************************************/-/* binary object writer & reader */--typedef enum BCTagEnum {-    BC_TAG_NULL = 1,-    BC_TAG_UNDEFINED,-    BC_TAG_BOOL_FALSE,-    BC_TAG_BOOL_TRUE,-    BC_TAG_INT32,-    BC_TAG_FLOAT64,-    BC_TAG_STRING,-    BC_TAG_OBJECT,-    BC_TAG_ARRAY,-    BC_TAG_BIG_INT,-    BC_TAG_BIG_FLOAT,-    BC_TAG_BIG_DECIMAL,-    BC_TAG_TEMPLATE_OBJECT,-    BC_TAG_FUNCTION_BYTECODE,-    BC_TAG_MODULE,-    BC_TAG_TYPED_ARRAY,-    BC_TAG_ARRAY_BUFFER,-    BC_TAG_SHARED_ARRAY_BUFFER,-    BC_TAG_DATE,-    BC_TAG_OBJECT_VALUE,-    BC_TAG_OBJECT_REFERENCE,-} BCTagEnum;--#ifdef CONFIG_BIGNUM-#define BC_BASE_VERSION 2-#else-#define BC_BASE_VERSION 1-#endif-#define BC_BE_VERSION 0x40-#ifdef WORDS_BIGENDIAN-#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION)-#else-#define BC_VERSION BC_BASE_VERSION-#endif--typedef struct BCWriterState {-    JSContext *ctx;-    DynBuf dbuf;-    BOOL byte_swap : 8;-    BOOL allow_bytecode : 8;-    BOOL allow_sab : 8;-    BOOL allow_reference : 8;-    uint32_t first_atom;-    uint32_t *atom_to_idx;-    int atom_to_idx_size;-    JSAtom *idx_to_atom;-    int idx_to_atom_count;-    int idx_to_atom_size;-    uint8_t **sab_tab;-    int sab_tab_len;-    int sab_tab_size;-    /* list of referenced objects (used if allow_reference = TRUE) */-    JSObjectList object_list;-} BCWriterState;--#ifdef DUMP_READ_OBJECT-static const char * const bc_tag_str[] = {-    "invalid",-    "null",-    "undefined",-    "false",-    "true",-    "int32",-    "float64",-    "string",-    "object",-    "array",-    "bigint",-    "bigfloat",-    "bigdecimal",-    "template",-    "function",-    "module",-    "TypedArray",-    "ArrayBuffer",-    "SharedArrayBuffer",-    "Date",-    "ObjectValue",-    "ObjectReference",-};-#endif--static void bc_put_u8(BCWriterState *s, uint8_t v)-{-    dbuf_putc(&s->dbuf, v);-}--static void bc_put_u16(BCWriterState *s, uint16_t v)-{-    if (s->byte_swap)-        v = bswap16(v);-    dbuf_put_u16(&s->dbuf, v);-}--static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)-{-    if (s->byte_swap)-        v = bswap32(v);-    dbuf_put_u32(&s->dbuf, v);-}--static void bc_put_u64(BCWriterState *s, uint64_t v)-{-    if (s->byte_swap)-        v = bswap64(v);-    dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));-}--static void bc_put_leb128(BCWriterState *s, uint32_t v)-{-    dbuf_put_leb128(&s->dbuf, v);-}--static void bc_put_sleb128(BCWriterState *s, int32_t v)-{-    dbuf_put_sleb128(&s->dbuf, v);-}--static void bc_set_flags(uint32_t *pflags, int *pidx, uint32_t val, int n)-{-    *pflags = *pflags | (val << *pidx);-    *pidx += n;-}--static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)-{-    uint32_t v;--    if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {-        *pres = atom;-        return 0;-    }-    atom -= s->first_atom;-    if (atom < s->atom_to_idx_size && s->atom_to_idx[atom] != 0) {-        *pres = s->atom_to_idx[atom];-        return 0;-    }-    if (atom >= s->atom_to_idx_size) {-        int old_size, i;-        old_size = s->atom_to_idx_size;-        if (js_resize_array(s->ctx, (void **)&s->atom_to_idx,-                            sizeof(s->atom_to_idx[0]), &s->atom_to_idx_size,-                            atom + 1))-            return -1;-        /* XXX: could add a specific js_resize_array() function to do it */-        for(i = old_size; i < s->atom_to_idx_size; i++)-            s->atom_to_idx[i] = 0;-    }-    if (js_resize_array(s->ctx, (void **)&s->idx_to_atom,-                        sizeof(s->idx_to_atom[0]),-                        &s->idx_to_atom_size, s->idx_to_atom_count + 1))-        goto fail;--    v = s->idx_to_atom_count++;-    s->idx_to_atom[v] = atom + s->first_atom;-    v += s->first_atom;-    s->atom_to_idx[atom] = v;-    *pres = v;-    return 0;- fail:-    *pres = 0;-    return -1;-}--static int bc_put_atom(BCWriterState *s, JSAtom atom)-{-    uint32_t v;--    if (__JS_AtomIsTaggedInt(atom)) {-        v = (__JS_AtomToUInt32(atom) << 1) | 1;-    } else {-        if (bc_atom_to_idx(s, &v, atom))-            return -1;-        v <<= 1;-    }-    bc_put_leb128(s, v);-    return 0;-}--static void bc_byte_swap(uint8_t *bc_buf, int bc_len)-{-    int pos, len, op, fmt;--    pos = 0;-    while (pos < bc_len) {-        op = bc_buf[pos];-        len = short_opcode_info(op).size;-        fmt = short_opcode_info(op).fmt;-        switch(fmt) {-        case OP_FMT_u16:-        case OP_FMT_i16:-        case OP_FMT_label16:-        case OP_FMT_npop:-        case OP_FMT_loc:-        case OP_FMT_arg:-        case OP_FMT_var_ref:-            put_u16(bc_buf + pos + 1,-                    bswap16(get_u16(bc_buf + pos + 1)));-            break;-        case OP_FMT_i32:-        case OP_FMT_u32:-        case OP_FMT_const:-        case OP_FMT_label:-        case OP_FMT_atom:-        case OP_FMT_atom_u8:-            put_u32(bc_buf + pos + 1,-                    bswap32(get_u32(bc_buf + pos + 1)));-            break;-        case OP_FMT_atom_u16:-        case OP_FMT_label_u16:-            put_u32(bc_buf + pos + 1,-                    bswap32(get_u32(bc_buf + pos + 1)));-            put_u16(bc_buf + pos + 1 + 4,-                    bswap16(get_u16(bc_buf + pos + 1 + 4)));-            break;-        case OP_FMT_atom_label_u8:-        case OP_FMT_atom_label_u16:-            put_u32(bc_buf + pos + 1,-                    bswap32(get_u32(bc_buf + pos + 1)));-            put_u32(bc_buf + pos + 1 + 4,-                    bswap32(get_u32(bc_buf + pos + 1 + 4)));-            if (fmt == OP_FMT_atom_label_u16) {-                put_u16(bc_buf + pos + 1 + 4 + 4,-                        bswap16(get_u16(bc_buf + pos + 1 + 4 + 4)));-            }-            break;-        case OP_FMT_npop_u16:-            put_u16(bc_buf + pos + 1,-                    bswap16(get_u16(bc_buf + pos + 1)));-            put_u16(bc_buf + pos + 1 + 2,-                    bswap16(get_u16(bc_buf + pos + 1 + 2)));-            break;-        default:-            break;-        }-        pos += len;-    }-}--static int JS_WriteFunctionBytecode(BCWriterState *s,-                                    const uint8_t *bc_buf1, int bc_len)-{-    int pos, len, op;-    JSAtom atom;-    uint8_t *bc_buf;-    uint32_t val;--    bc_buf = js_malloc(s->ctx, bc_len);-    if (!bc_buf)-        return -1;-    memcpy(bc_buf, bc_buf1, bc_len);--    pos = 0;-    while (pos < bc_len) {-        op = bc_buf[pos];-        len = short_opcode_info(op).size;-        switch(short_opcode_info(op).fmt) {-        case OP_FMT_atom:-        case OP_FMT_atom_u8:-        case OP_FMT_atom_u16:-        case OP_FMT_atom_label_u8:-        case OP_FMT_atom_label_u16:-            atom = get_u32(bc_buf + pos + 1);-            if (bc_atom_to_idx(s, &val, atom))-                goto fail;-            put_u32(bc_buf + pos + 1, val);-            break;-        default:-            break;-        }-        pos += len;-    }--    if (s->byte_swap)-        bc_byte_swap(bc_buf, bc_len);--    dbuf_put(&s->dbuf, bc_buf, bc_len);--    js_free(s->ctx, bc_buf);-    return 0;- fail:-    js_free(s->ctx, bc_buf);-    return -1;-}--static void JS_WriteString(BCWriterState *s, JSString *p)-{-    int i;-    bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);-    if (p->is_wide_char) {-        for(i = 0; i < p->len; i++)-            bc_put_u16(s, p->u.str16[i]);-    } else {-        dbuf_put(&s->dbuf, p->u.str8, p->len);-    }-}--#ifdef CONFIG_BIGNUM-static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)-{-    uint32_t tag, tag1;-    int64_t e;-    JSBigFloat *bf = JS_VALUE_GET_PTR(obj);-    bf_t *a = &bf->num;-    size_t len, i, n1, j;-    limb_t v;--    tag = JS_VALUE_GET_TAG(obj);-    switch(tag) {-    case JS_TAG_BIG_INT:-        tag1 = BC_TAG_BIG_INT;-        break;-    case JS_TAG_BIG_FLOAT:-        tag1 = BC_TAG_BIG_FLOAT;-        break;-    case JS_TAG_BIG_DECIMAL:-        tag1 = BC_TAG_BIG_DECIMAL;-        break;-    default:-        abort();-    }-    bc_put_u8(s, tag1);--    /* sign + exponent */-    if (a->expn == BF_EXP_ZERO)-        e = 0;-    else if (a->expn == BF_EXP_INF)-        e = 1;-    else if (a->expn == BF_EXP_NAN)-        e = 2;-    else if (a->expn >= 0)-        e = a->expn + 3;-    else-        e = a->expn;-    e = (e << 1) | a->sign;-    if (e < INT32_MIN || e > INT32_MAX) {-        JS_ThrowInternalError(s->ctx, "bignum exponent is too large");-        return -1;-    }-    bc_put_sleb128(s, e);--    /* mantissa */-    if (a->len != 0) {-        if (tag != JS_TAG_BIG_DECIMAL) {-            i = 0;-            while (i < a->len && a->tab[i] == 0)-                i++;-            assert(i < a->len);-            v = a->tab[i];-            n1 = sizeof(limb_t);-            while ((v & 0xff) == 0) {-                n1--;-                v >>= 8;-            }-            i++;-            len = (a->len - i) * sizeof(limb_t) + n1;-            if (len > INT32_MAX) {-                JS_ThrowInternalError(s->ctx, "bignum is too large");-                return -1;-            }-            bc_put_leb128(s, len);-            /* always saved in byte based little endian representation */-            for(j = 0; j < n1; j++) {-                dbuf_putc(&s->dbuf, v >> (j * 8));-            }-            for(; i < a->len; i++) {-                limb_t v = a->tab[i];-#if LIMB_BITS == 32-#ifdef WORDS_BIGENDIAN-                v = bswap32(v);-#endif-                dbuf_put_u32(&s->dbuf, v);-#else-#ifdef WORDS_BIGENDIAN-                v = bswap64(v);-#endif-                dbuf_put_u64(&s->dbuf, v);-#endif-            }-        } else {-            int bpos, d;-            uint8_t v8;-            size_t i0;-            -            /* little endian BCD */-            i = 0;-            while (i < a->len && a->tab[i] == 0)-                i++;-            assert(i < a->len);-            len = a->len * LIMB_DIGITS;-            v = a->tab[i];-            j = 0;-            while ((v % 10) == 0) {-                j++;-                v /= 10;-            }-            len -= j;-            assert(len > 0);-            if (len > INT32_MAX) {-                JS_ThrowInternalError(s->ctx, "bignum is too large");-                return -1;-            }-            bc_put_leb128(s, len);-            -            bpos = 0;-            v8 = 0;-            i0 = i;-            for(; i < a->len; i++) {-                if (i != i0) {-                    v = a->tab[i];-                    j = 0;-                }-                for(; j < LIMB_DIGITS; j++) {-                    d = v % 10;-                    v /= 10;-                    if (bpos == 0) {-                        v8 = d;-                        bpos = 1;-                    } else {-                        dbuf_putc(&s->dbuf, v8 | (d << 4));-                        bpos = 0;-                    }-                }-            }-            /* flush the last digit */-            if (bpos) {-                dbuf_putc(&s->dbuf, v8);-            }-        }-    }-    return 0;-}-#endif /* CONFIG_BIGNUM */--static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);--static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)-{-    JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);-    uint32_t flags;-    int idx, i;-    -    bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);-    flags = idx = 0;-    bc_set_flags(&flags, &idx, b->has_prototype, 1);-    bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1);-    bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1);-    bc_set_flags(&flags, &idx, b->need_home_object, 1);-    bc_set_flags(&flags, &idx, b->func_kind, 2);-    bc_set_flags(&flags, &idx, b->new_target_allowed, 1);-    bc_set_flags(&flags, &idx, b->super_call_allowed, 1);-    bc_set_flags(&flags, &idx, b->super_allowed, 1);-    bc_set_flags(&flags, &idx, b->arguments_allowed, 1);-    bc_set_flags(&flags, &idx, b->has_debug, 1);-    bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);-    assert(idx <= 16);-    bc_put_u16(s, flags);-    bc_put_u8(s, b->js_mode);-    bc_put_atom(s, b->func_name);-    -    bc_put_leb128(s, b->arg_count);-    bc_put_leb128(s, b->var_count);-    bc_put_leb128(s, b->defined_arg_count);-    bc_put_leb128(s, b->stack_size);-    bc_put_leb128(s, b->closure_var_count);-    bc_put_leb128(s, b->cpool_count);-    bc_put_leb128(s, b->byte_code_len);-    if (b->vardefs) {-        bc_put_leb128(s, b->arg_count + b->var_count);-        for(i = 0; i < b->arg_count + b->var_count; i++) {-            JSVarDef *vd = &b->vardefs[i];-            bc_put_atom(s, vd->var_name);-            bc_put_leb128(s, vd->scope_level);-            bc_put_leb128(s, vd->scope_next + 1);-            flags = idx = 0;-            bc_set_flags(&flags, &idx, vd->var_kind, 4);-            bc_set_flags(&flags, &idx, vd->is_func_var, 1);-            bc_set_flags(&flags, &idx, vd->is_const, 1);-            bc_set_flags(&flags, &idx, vd->is_lexical, 1);-            bc_set_flags(&flags, &idx, vd->is_captured, 1);-            assert(idx <= 8);-            bc_put_u8(s, flags);-        }-    } else {-        bc_put_leb128(s, 0);-    }-    -    for(i = 0; i < b->closure_var_count; i++) {-        JSClosureVar *cv = &b->closure_var[i];-        bc_put_atom(s, cv->var_name);-        bc_put_leb128(s, cv->var_idx);-        flags = idx = 0;-        bc_set_flags(&flags, &idx, cv->is_local, 1);-        bc_set_flags(&flags, &idx, cv->is_arg, 1);-        bc_set_flags(&flags, &idx, cv->is_const, 1);-        bc_set_flags(&flags, &idx, cv->is_lexical, 1);-        bc_set_flags(&flags, &idx, cv->var_kind, 4);-        assert(idx <= 8);-        bc_put_u8(s, flags);-    }-    -    if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))-        goto fail;-    -    if (b->has_debug) {-        bc_put_atom(s, b->debug.filename);-        bc_put_leb128(s, b->debug.line_num);-        bc_put_leb128(s, b->debug.pc2line_len);-        dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);-    }-    -    for(i = 0; i < b->cpool_count; i++) {-        if (JS_WriteObjectRec(s, b->cpool[i]))-            goto fail;-    }-    return 0;- fail:-    return -1;-}--static int JS_WriteModule(BCWriterState *s, JSValueConst obj)-{-    JSModuleDef *m = JS_VALUE_GET_PTR(obj);-    int i;-    -    bc_put_u8(s, BC_TAG_MODULE);-    bc_put_atom(s, m->module_name);-    -    bc_put_leb128(s, m->req_module_entries_count);-    for(i = 0; i < m->req_module_entries_count; i++) {-        JSReqModuleEntry *rme = &m->req_module_entries[i];-        bc_put_atom(s, rme->module_name);-    }-    -    bc_put_leb128(s, m->export_entries_count);-    for(i = 0; i < m->export_entries_count; i++) {-        JSExportEntry *me = &m->export_entries[i];-        bc_put_u8(s, me->export_type);-        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-            bc_put_leb128(s, me->u.local.var_idx);-        } else {-            bc_put_leb128(s, me->u.req_module_idx);-            bc_put_atom(s, me->local_name);-        }-        bc_put_atom(s, me->export_name);-    }-    -    bc_put_leb128(s, m->star_export_entries_count);-    for(i = 0; i < m->star_export_entries_count; i++) {-        JSStarExportEntry *se = &m->star_export_entries[i];-        bc_put_leb128(s, se->req_module_idx);-    }-    -    bc_put_leb128(s, m->import_entries_count);-    for(i = 0; i < m->import_entries_count; i++) {-        JSImportEntry *mi = &m->import_entries[i];-        bc_put_leb128(s, mi->var_idx);-        bc_put_atom(s, mi->import_name);-        bc_put_leb128(s, mi->req_module_idx);-    }-    -    if (JS_WriteObjectRec(s, m->func_obj))-        goto fail;-    return 0;- fail:-    return -1;-}--static int JS_WriteArray(BCWriterState *s, JSValueConst obj)-{-    JSObject *p = JS_VALUE_GET_OBJ(obj);-    uint32_t i, len;-    JSValue val;-    int ret;-    BOOL is_template;-    -    if (s->allow_bytecode && !p->extensible) {-        /* not extensible array: we consider it is a-           template when we are saving bytecode */-        bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);-        is_template = TRUE;-    } else {-        bc_put_u8(s, BC_TAG_ARRAY);-        is_template = FALSE;-    }-    if (js_get_length32(s->ctx, &len, obj))-        goto fail1;-    bc_put_leb128(s, len);-    for(i = 0; i < len; i++) {-        val = JS_GetPropertyUint32(s->ctx, obj, i);-        if (JS_IsException(val))-            goto fail1;-        ret = JS_WriteObjectRec(s, val);-        JS_FreeValue(s->ctx, val);-        if (ret)-            goto fail1;-    }-    if (is_template) {-        val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);-        if (JS_IsException(val))-            goto fail1;-        ret = JS_WriteObjectRec(s, val);-        JS_FreeValue(s->ctx, val);-        if (ret)-            goto fail1;-    }-    return 0;- fail1:-    return -1;-}--static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)-{-    JSObject *p = JS_VALUE_GET_OBJ(obj);-    uint32_t i, prop_count;-    JSShape *sh;-    JSShapeProperty *pr;-    int pass;-    JSAtom atom;--    bc_put_u8(s, BC_TAG_OBJECT);-    prop_count = 0;-    sh = p->shape;-    for(pass = 0; pass < 2; pass++) {-        if (pass == 1)-            bc_put_leb128(s, prop_count);-        for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {-            atom = pr->atom;-            if (atom != JS_ATOM_NULL &&-                JS_AtomIsString(s->ctx, atom) &&-                (pr->flags & JS_PROP_ENUMERABLE)) {-                if (pr->flags & JS_PROP_TMASK) {-                    JS_ThrowTypeError(s->ctx, "only value properties are supported");-                    goto fail;-                }-                if (pass == 0) {-                    prop_count++;-                } else {-                    bc_put_atom(s, atom);-                    if (JS_WriteObjectRec(s, p->prop[i].u.value))-                        goto fail;-                }-            }-        }-    }-    return 0;- fail:-    return -1;-}--static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj)-{-    JSObject *p = JS_VALUE_GET_OBJ(obj);-    JSTypedArray *ta = p->u.typed_array;--    bc_put_u8(s, BC_TAG_TYPED_ARRAY);-    bc_put_u8(s, p->class_id - JS_CLASS_UINT8C_ARRAY);-    bc_put_leb128(s, p->u.array.count);-    bc_put_leb128(s, ta->offset);-    if (JS_WriteObjectRec(s, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)))-        return -1;-    return 0;-}--static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj)-{-    JSObject *p = JS_VALUE_GET_OBJ(obj);-    JSArrayBuffer *abuf = p->u.array_buffer;-    if (abuf->detached) {-        JS_ThrowTypeErrorDetachedArrayBuffer(s->ctx);-        return -1;-    }-    bc_put_u8(s, BC_TAG_ARRAY_BUFFER);-    bc_put_leb128(s, abuf->byte_length);-    dbuf_put(&s->dbuf, abuf->data, abuf->byte_length);-    return 0;-}--static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj)-{-    JSObject *p = JS_VALUE_GET_OBJ(obj);-    JSArrayBuffer *abuf = p->u.array_buffer;-    assert(!abuf->detached); /* SharedArrayBuffer are never detached */-    bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER);-    bc_put_leb128(s, abuf->byte_length);-    bc_put_u64(s, (uintptr_t)abuf->data);-    if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]),-                        &s->sab_tab_size, s->sab_tab_len + 1))-        return -1;-    /* keep the SAB pointer so that the user can clone it or free it */-    s->sab_tab[s->sab_tab_len++] = abuf->data;-    return 0;-}--static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)-{-    uint32_t tag;--    if (js_check_stack_overflow(s->ctx->rt, 0)) {-        JS_ThrowStackOverflow(s->ctx);-        return -1;-    }--    tag = JS_VALUE_GET_NORM_TAG(obj);-    switch(tag) {-    case JS_TAG_NULL:-        bc_put_u8(s, BC_TAG_NULL);-        break;-    case JS_TAG_UNDEFINED:-        bc_put_u8(s, BC_TAG_UNDEFINED);-        break;-    case JS_TAG_BOOL:-        bc_put_u8(s, BC_TAG_BOOL_FALSE + JS_VALUE_GET_INT(obj));-        break;-    case JS_TAG_INT:-        bc_put_u8(s, BC_TAG_INT32);-        bc_put_sleb128(s, JS_VALUE_GET_INT(obj));-        break;-    case JS_TAG_FLOAT64:-        {-            JSFloat64Union u;-            bc_put_u8(s, BC_TAG_FLOAT64);-            u.d = JS_VALUE_GET_FLOAT64(obj);-            bc_put_u64(s, u.u64);-        }-        break;-    case JS_TAG_STRING:-        {-            JSString *p = JS_VALUE_GET_STRING(obj);-            bc_put_u8(s, BC_TAG_STRING);-            JS_WriteString(s, p);-        }-        break;-    case JS_TAG_FUNCTION_BYTECODE:-        if (!s->allow_bytecode)-            goto invalid_tag;-        if (JS_WriteFunctionTag(s, obj))-            goto fail;-        break;-    case JS_TAG_MODULE:-        if (!s->allow_bytecode)-            goto invalid_tag;-        if (JS_WriteModule(s, obj))-            goto fail;-        break;-    case JS_TAG_OBJECT:-        {-            JSObject *p = JS_VALUE_GET_OBJ(obj);-            int ret, idx;-            -            if (s->allow_reference) {-                idx = js_object_list_find(s->ctx, &s->object_list, p);-                if (idx >= 0) {-                    bc_put_u8(s, BC_TAG_OBJECT_REFERENCE);-                    bc_put_leb128(s, idx);-                    break;-                } else {-                    if (js_object_list_add(s->ctx, &s->object_list, p))-                        goto fail;-                }-            } else {-                if (p->tmp_mark) {-                    JS_ThrowTypeError(s->ctx, "circular reference");-                    goto fail;-                }-                p->tmp_mark = 1;-            }-            switch(p->class_id) {-            case JS_CLASS_ARRAY:-                ret = JS_WriteArray(s, obj);-                break;-            case JS_CLASS_OBJECT:-                ret = JS_WriteObjectTag(s, obj);-                break;-            case JS_CLASS_ARRAY_BUFFER:-                ret = JS_WriteArrayBuffer(s, obj);-                break;-            case JS_CLASS_SHARED_ARRAY_BUFFER:-                if (!s->allow_sab)-                    goto invalid_tag;-                ret = JS_WriteSharedArrayBuffer(s, obj);-                break;-            case JS_CLASS_DATE:-                bc_put_u8(s, BC_TAG_DATE);-                ret = JS_WriteObjectRec(s, p->u.object_data);-                break;-            case JS_CLASS_NUMBER:-            case JS_CLASS_STRING:-            case JS_CLASS_BOOLEAN:-#ifdef CONFIG_BIGNUM-            case JS_CLASS_BIG_INT:-            case JS_CLASS_BIG_FLOAT:-            case JS_CLASS_BIG_DECIMAL:-#endif-                bc_put_u8(s, BC_TAG_OBJECT_VALUE);-                ret = JS_WriteObjectRec(s, p->u.object_data);-                break;-            default:-                if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-                    p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-                    ret = JS_WriteTypedArray(s, obj);-                } else {-                    JS_ThrowTypeError(s->ctx, "unsupported object class");-                    ret = -1;-                }-                break;-            }-            p->tmp_mark = 0;-            if (ret)-                goto fail;-        }-        break;-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-    case JS_TAG_BIG_DECIMAL:-        if (JS_WriteBigNum(s, obj))-            goto fail;-        break;-#endif-    default:-    invalid_tag:-        JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag);-        goto fail;-    }-    return 0;-- fail:-    return -1;-}--/* create the atom table */-static int JS_WriteObjectAtoms(BCWriterState *s)-{-    JSRuntime *rt = s->ctx->rt;-    DynBuf dbuf1;-    int i, atoms_size;-    uint8_t version;--    dbuf1 = s->dbuf;-    js_dbuf_init(s->ctx, &s->dbuf);--    version = BC_VERSION;-    if (s->byte_swap)-        version ^= BC_BE_VERSION;-    bc_put_u8(s, version);--    bc_put_leb128(s, s->idx_to_atom_count);-    for(i = 0; i < s->idx_to_atom_count; i++) {-        JSAtomStruct *p = rt->atom_array[s->idx_to_atom[i]];-        JS_WriteString(s, p);-    }-    /* XXX: should check for OOM in above phase */--    /* move the atoms at the start */-    /* XXX: could just append dbuf1 data, but it uses more memory if-       dbuf1 is larger than dbuf */-    atoms_size = s->dbuf.size;-    if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size))-        goto fail;-    memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size);-    memcpy(dbuf1.buf, s->dbuf.buf, atoms_size);-    dbuf1.size += atoms_size;-    dbuf_free(&s->dbuf);-    s->dbuf = dbuf1;-    return 0;- fail:-    dbuf_free(&dbuf1);-    return -1;-}--uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,-                         int flags, uint8_t ***psab_tab, size_t *psab_tab_len)-{-    BCWriterState ss, *s = &ss;--    memset(s, 0, sizeof(*s));-    s->ctx = ctx;-    /* XXX: byte swapped output is untested */-    s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);-    s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);-    s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);-    s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);-    /* XXX: could use a different version when bytecode is included */-    if (s->allow_bytecode)-        s->first_atom = JS_ATOM_END;-    else-        s->first_atom = 1;-    js_dbuf_init(ctx, &s->dbuf);-    js_object_list_init(&s->object_list);-    -    if (JS_WriteObjectRec(s, obj))-        goto fail;-    if (JS_WriteObjectAtoms(s))-        goto fail;-    js_object_list_end(ctx, &s->object_list);-    js_free(ctx, s->atom_to_idx);-    js_free(ctx, s->idx_to_atom);-    *psize = s->dbuf.size;-    if (psab_tab)-        *psab_tab = s->sab_tab;-    if (psab_tab_len)-        *psab_tab_len = s->sab_tab_len;-    return s->dbuf.buf;- fail:-    js_object_list_end(ctx, &s->object_list);-    js_free(ctx, s->atom_to_idx);-    js_free(ctx, s->idx_to_atom);-    dbuf_free(&s->dbuf);-    *psize = 0;-    if (psab_tab)-        *psab_tab = NULL;-    if (psab_tab_len)-        *psab_tab_len = 0;-    return NULL;-}--uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,-                        int flags)-{-    return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL);-}--typedef struct BCReaderState {-    JSContext *ctx;-    const uint8_t *buf_start, *ptr, *buf_end;-    uint32_t first_atom;-    uint32_t idx_to_atom_count;-    JSAtom *idx_to_atom;-    int error_state;-    BOOL allow_sab : 8;-    BOOL allow_bytecode : 8;-    BOOL is_rom_data : 8;-    BOOL allow_reference : 8;-    /* object references */-    JSObject **objects;-    int objects_count;-    int objects_size;-    -#ifdef DUMP_READ_OBJECT-    const uint8_t *ptr_last;-    int level;-#endif-} BCReaderState;--#ifdef DUMP_READ_OBJECT-static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s, const char *fmt, ...) {-    va_list ap;-    int i, n, n0;--    if (!s->ptr_last)-        s->ptr_last = s->buf_start;--    n = n0 = 0;-    if (s->ptr > s->ptr_last || s->ptr == s->buf_start) {-        n0 = printf("%04x: ", (int)(s->ptr_last - s->buf_start));-        n += n0;-    }-    for (i = 0; s->ptr_last < s->ptr; i++) {-        if ((i & 7) == 0 && i > 0) {-            printf("\n%*s", n0, "");-            n = n0;-        }-        n += printf(" %02x", *s->ptr_last++);-    }-    if (*fmt == '}')-        s->level--;-    if (n < 32 + s->level * 2) {-        printf("%*s", 32 + s->level * 2 - n, "");-    }-    va_start(ap, fmt);-    vfprintf(stdout, fmt, ap);-    va_end(ap);-    if (strchr(fmt, '{'))-        s->level++;-}-#else-#define bc_read_trace(...)-#endif--static int bc_read_error_end(BCReaderState *s)-{-    if (!s->error_state) {-        JS_ThrowSyntaxError(s->ctx, "read after the end of the buffer");-    }-    return s->error_state = -1;-}--static int bc_get_u8(BCReaderState *s, uint8_t *pval)-{-    if (unlikely(s->buf_end - s->ptr < 1)) {-        *pval = 0; /* avoid warning */-        return bc_read_error_end(s);-    }-    *pval = *s->ptr++;-    return 0;-}--static int bc_get_u16(BCReaderState *s, uint16_t *pval)-{-    if (unlikely(s->buf_end - s->ptr < 2)) {-        *pval = 0; /* avoid warning */-        return bc_read_error_end(s);-    }-    *pval = get_u16(s->ptr);-    s->ptr += 2;-    return 0;-}--static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)-{-    if (unlikely(s->buf_end - s->ptr < 4)) {-        *pval = 0; /* avoid warning */-        return bc_read_error_end(s);-    }-    *pval = get_u32(s->ptr);-    s->ptr += 4;-    return 0;-}--static int bc_get_u64(BCReaderState *s, uint64_t *pval)-{-    if (unlikely(s->buf_end - s->ptr < 8)) {-        *pval = 0; /* avoid warning */-        return bc_read_error_end(s);-    }-    *pval = get_u64(s->ptr);-    s->ptr += 8;-    return 0;-}--static int bc_get_leb128(BCReaderState *s, uint32_t *pval)-{-    int ret;-    ret = get_leb128(pval, s->ptr, s->buf_end);-    if (unlikely(ret < 0))-        return bc_read_error_end(s);-    s->ptr += ret;-    return 0;-}--static int bc_get_sleb128(BCReaderState *s, int32_t *pval)-{-    int ret;-    ret = get_sleb128(pval, s->ptr, s->buf_end);-    if (unlikely(ret < 0))-        return bc_read_error_end(s);-    s->ptr += ret;-    return 0;-}--/* XXX: used to read an `int` with a positive value */-static int bc_get_leb128_int(BCReaderState *s, int *pval)-{-    return bc_get_leb128(s, (uint32_t *)pval);-}--static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval)-{-    uint32_t val;-    if (bc_get_leb128(s, &val)) {-        *pval = 0;-        return -1;-    }-    *pval = val;-    return 0;-}--static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len)-{-    if (buf_len != 0) {-        if (unlikely(!buf || s->buf_end - s->ptr < buf_len))-            return bc_read_error_end(s);-        memcpy(buf, s->ptr, buf_len);-        s->ptr += buf_len;-    }-    return 0;-}--static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)-{-    JSAtom atom;--    if (__JS_AtomIsTaggedInt(idx)) {-        atom = idx;-    } else if (idx < s->first_atom) {-        atom = JS_DupAtom(s->ctx, idx);-    } else {-        idx -= s->first_atom;-        if (idx >= s->idx_to_atom_count) {-            JS_ThrowSyntaxError(s->ctx, "invalid atom index (pos=%u)",-                                (unsigned int)(s->ptr - s->buf_start));-            *patom = JS_ATOM_NULL;-            return s->error_state = -1;-        }-        atom = JS_DupAtom(s->ctx, s->idx_to_atom[idx]);-    }-    *patom = atom;-    return 0;-}--static int bc_get_atom(BCReaderState *s, JSAtom *patom)-{-    uint32_t v;-    if (bc_get_leb128(s, &v))-        return -1;-    if (v & 1) {-        *patom = __JS_AtomFromUInt32(v >> 1);-        return 0;-    } else {-        return bc_idx_to_atom(s, patom, v >> 1);-    }-}--static JSString *JS_ReadString(BCReaderState *s)-{-    uint32_t len;-    size_t size;-    BOOL is_wide_char;-    JSString *p;--    if (bc_get_leb128(s, &len))-        return NULL;-    is_wide_char = len & 1;-    len >>= 1;-    p = js_alloc_string(s->ctx, len, is_wide_char);-    if (!p) {-        s->error_state = -1;-        return NULL;-    }-    size = (size_t)len << is_wide_char;-    if ((s->buf_end - s->ptr) < size) {-        bc_read_error_end(s);-        js_free_string(s->ctx->rt, p);-        return NULL;-    }-    memcpy(p->u.str8, s->ptr, size);-    s->ptr += size;-    if (!is_wide_char) {-        p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */-    }-#ifdef DUMP_READ_OBJECT-    JS_DumpString(s->ctx->rt, p); printf("\n");-#endif-    return p;-}--static uint32_t bc_get_flags(uint32_t flags, int *pidx, int n)-{-    uint32_t val;-    /* XXX: this does not work for n == 32 */-    val = (flags >> *pidx) & ((1U << n) - 1);-    *pidx += n;-    return val;-}--static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,-                                   int byte_code_offset, uint32_t bc_len)-{-    uint8_t *bc_buf;-    int pos, len, op;-    JSAtom atom;-    uint32_t idx;--    if (s->is_rom_data) {-        /* directly use the input buffer */-        if (unlikely(s->buf_end - s->ptr < bc_len))-            return bc_read_error_end(s);-        bc_buf = (uint8_t *)s->ptr;-        s->ptr += bc_len;-    } else {-        bc_buf = (void *)((uint8_t*)b + byte_code_offset);-        if (bc_get_buf(s, bc_buf, bc_len))-            return -1;-    }-    b->byte_code_buf = bc_buf;--    pos = 0;-    while (pos < bc_len) {-        op = bc_buf[pos];-        len = short_opcode_info(op).size;-        switch(short_opcode_info(op).fmt) {-        case OP_FMT_atom:-        case OP_FMT_atom_u8:-        case OP_FMT_atom_u16:-        case OP_FMT_atom_label_u8:-        case OP_FMT_atom_label_u16:-            idx = get_u32(bc_buf + pos + 1);-            if (s->is_rom_data) {-                /* just increment the reference count of the atom */-                JS_DupAtom(s->ctx, (JSAtom)idx);-            } else {-                if (bc_idx_to_atom(s, &atom, idx)) {-                    /* Note: the atoms will be freed up to this position */-                    b->byte_code_len = pos;-                    return -1;-                }-                put_u32(bc_buf + pos + 1, atom);-#ifdef DUMP_READ_OBJECT-                bc_read_trace(s, "at %d, fixup atom: ", pos + 1); print_atom(s->ctx, atom); printf("\n");-#endif-            }-            break;-        default:-            break;-        }-        pos += len;-    }-    return 0;-}--#ifdef CONFIG_BIGNUM-static JSValue JS_ReadBigNum(BCReaderState *s, int tag)-{-    JSValue obj = JS_UNDEFINED;-    uint8_t v8;-    int32_t e;-    uint32_t len;-    limb_t l, i, n, j;-    JSBigFloat *p;-    limb_t v;-    bf_t *a;-    int bpos, d;-    -    p = js_new_bf(s->ctx);-    if (!p)-        goto fail;-    switch(tag) {-    case BC_TAG_BIG_INT:-        obj = JS_MKPTR(JS_TAG_BIG_INT, p);-        break;-    case BC_TAG_BIG_FLOAT:-        obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p);-        break;-    case BC_TAG_BIG_DECIMAL:-        obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);-        break;-    default:-        abort();-    }--    /* sign + exponent */-    if (bc_get_sleb128(s, &e))-        goto fail;--    a = &p->num;-    a->sign = e & 1;-    e >>= 1;-    if (e == 0)-        a->expn = BF_EXP_ZERO;-    else if (e == 1)-        a->expn = BF_EXP_INF;-    else if (e == 2)-        a->expn = BF_EXP_NAN;-    else if (e >= 3)-        a->expn = e - 3;-    else-        a->expn = e;--    /* mantissa */-    if (a->expn != BF_EXP_ZERO &&-        a->expn != BF_EXP_INF &&-        a->expn != BF_EXP_NAN) {-        if (bc_get_leb128(s, &len))-            goto fail;-        bc_read_trace(s, "len=%" PRId64 "\n", (int64_t)len);-        if (len == 0) {-            JS_ThrowInternalError(s->ctx, "invalid bignum length");-            goto fail;-        }-        if (tag != BC_TAG_BIG_DECIMAL)-            l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);-        else-            l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS;-        if (bf_resize(a, l)) {-            JS_ThrowOutOfMemory(s->ctx);-            goto fail;-        }-        if (tag != BC_TAG_BIG_DECIMAL) {-            n = len & (sizeof(limb_t) - 1);-            if (n != 0) {-                v = 0;-                for(i = 0; i < n; i++) {-                    if (bc_get_u8(s, &v8))-                        goto fail;-                    v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);-                }-                a->tab[0] = v;-                i = 1;-            } else {-                i = 0;-            }-            for(; i < l; i++) {-#if LIMB_BITS == 32-                if (bc_get_u32(s, &v))-                    goto fail;-#ifdef WORDS_BIGENDIAN-                v = bswap32(v);-#endif-#else-                if (bc_get_u64(s, &v))-                    goto fail;-#ifdef WORDS_BIGENDIAN-                v = bswap64(v);-#endif-#endif-                a->tab[i] = v;-            }-        } else {-            bpos = 0;-            for(i = 0; i < l; i++) {-                if (i == 0 && (n = len % LIMB_DIGITS) != 0) {-                    j = LIMB_DIGITS - n;-                } else {-                    j = 0;-                }-                v = 0;-                for(; j < LIMB_DIGITS; j++) {-                    if (bpos == 0) {-                        if (bc_get_u8(s, &v8))-                            goto fail;-                        d = v8 & 0xf;-                        bpos = 1;-                    } else {-                        d = v8 >> 4;-                        bpos = 0;-                    }-                    if (d >= 10) {-                        JS_ThrowInternalError(s->ctx, "invalid digit");-                        goto fail;-                    }-                    v += mp_pow_dec[j] * d;-                }-                a->tab[i] = v;-            }-        }-    }-    bc_read_trace(s, "}\n");-    return obj;- fail:-    JS_FreeValue(s->ctx, obj);-    return JS_EXCEPTION;-}-#endif /* CONFIG_BIGNUM */--static JSValue JS_ReadObjectRec(BCReaderState *s);--static int BC_add_object_ref1(BCReaderState *s, JSObject *p)-{-    if (s->allow_reference) {-        if (js_resize_array(s->ctx, (void *)&s->objects,-                            sizeof(s->objects[0]),-                            &s->objects_size, s->objects_count + 1))-            return -1;-        s->objects[s->objects_count++] = p;-    }-    return 0;-}--static int BC_add_object_ref(BCReaderState *s, JSValueConst obj)-{-    return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj));-}--static JSValue JS_ReadFunctionTag(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSFunctionBytecode bc, *b;-    JSValue obj = JS_UNDEFINED;-    uint16_t v16;-    uint8_t v8;-    int idx, i, local_count;-    int function_size, cpool_offset, byte_code_offset;-    int closure_var_offset, vardefs_offset;--    memset(&bc, 0, sizeof(bc));-    bc.header.ref_count = 1;-    //bc.gc_header.mark = 0;--    if (bc_get_u16(s, &v16))-        goto fail;-    idx = 0;-    bc.has_prototype = bc_get_flags(v16, &idx, 1);-    bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1);-    bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1);-    bc.need_home_object = bc_get_flags(v16, &idx, 1);-    bc.func_kind = bc_get_flags(v16, &idx, 2);-    bc.new_target_allowed = bc_get_flags(v16, &idx, 1);-    bc.super_call_allowed = bc_get_flags(v16, &idx, 1);-    bc.super_allowed = bc_get_flags(v16, &idx, 1);-    bc.arguments_allowed = bc_get_flags(v16, &idx, 1);-    bc.has_debug = bc_get_flags(v16, &idx, 1);-    bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);-    bc.read_only_bytecode = s->is_rom_data;-    if (bc_get_u8(s, &v8))-        goto fail;-    bc.js_mode = v8;-    if (bc_get_atom(s, &bc.func_name))  //@ atom leak if failure-        goto fail;-    if (bc_get_leb128_u16(s, &bc.arg_count))-        goto fail;-    if (bc_get_leb128_u16(s, &bc.var_count))-        goto fail;-    if (bc_get_leb128_u16(s, &bc.defined_arg_count))-        goto fail;-    if (bc_get_leb128_u16(s, &bc.stack_size))-        goto fail;-    if (bc_get_leb128_int(s, &bc.closure_var_count))-        goto fail;-    if (bc_get_leb128_int(s, &bc.cpool_count))-        goto fail;-    if (bc_get_leb128_int(s, &bc.byte_code_len))-        goto fail;-    if (bc_get_leb128_int(s, &local_count))-        goto fail;--    if (bc.has_debug) {-        function_size = sizeof(*b);-    } else {-        function_size = offsetof(JSFunctionBytecode, debug);-    }-    cpool_offset = function_size;-    function_size += bc.cpool_count * sizeof(*bc.cpool);-    vardefs_offset = function_size;-    function_size += local_count * sizeof(*bc.vardefs);-    closure_var_offset = function_size;-    function_size += bc.closure_var_count * sizeof(*bc.closure_var);-    byte_code_offset = function_size;-    if (!bc.read_only_bytecode) {-        function_size += bc.byte_code_len;-    }--    b = js_mallocz(ctx, function_size);-    if (!b)-        return JS_EXCEPTION;-            -    memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));-    b->header.ref_count = 1;-    add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);-            -    obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);--#ifdef DUMP_READ_OBJECT-    bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n");-#endif-    bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n",-                  b->arg_count, b->var_count, b->defined_arg_count,-                  b->closure_var_count, b->cpool_count);-    bc_read_trace(s, "stack=%d bclen=%d locals=%d\n",-                  b->stack_size, b->byte_code_len, local_count);--    if (local_count != 0) {-        bc_read_trace(s, "vars {\n");-        b->vardefs = (void *)((uint8_t*)b + vardefs_offset);-        for(i = 0; i < local_count; i++) {-            JSVarDef *vd = &b->vardefs[i];-            if (bc_get_atom(s, &vd->var_name))-                goto fail;-            if (bc_get_leb128_int(s, &vd->scope_level))-                goto fail;-            if (bc_get_leb128_int(s, &vd->scope_next))-                goto fail;-            vd->scope_next--;-            if (bc_get_u8(s, &v8))-                goto fail;-            idx = 0;-            vd->var_kind = bc_get_flags(v8, &idx, 4);-            vd->is_func_var = bc_get_flags(v8, &idx, 1);-            vd->is_const = bc_get_flags(v8, &idx, 1);-            vd->is_lexical = bc_get_flags(v8, &idx, 1);-            vd->is_captured = bc_get_flags(v8, &idx, 1);-#ifdef DUMP_READ_OBJECT-            bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n");-#endif-        }-        bc_read_trace(s, "}\n");-    }-    if (b->closure_var_count != 0) {-        bc_read_trace(s, "closure vars {\n");-        b->closure_var = (void *)((uint8_t*)b + closure_var_offset);-        for(i = 0; i < b->closure_var_count; i++) {-            JSClosureVar *cv = &b->closure_var[i];-            int var_idx;-            if (bc_get_atom(s, &cv->var_name))-                goto fail;-            if (bc_get_leb128_int(s, &var_idx))-                goto fail;-            cv->var_idx = var_idx;-            if (bc_get_u8(s, &v8))-                goto fail;-            idx = 0;-            cv->is_local = bc_get_flags(v8, &idx, 1);-            cv->is_arg = bc_get_flags(v8, &idx, 1);-            cv->is_const = bc_get_flags(v8, &idx, 1);-            cv->is_lexical = bc_get_flags(v8, &idx, 1);-            cv->var_kind = bc_get_flags(v8, &idx, 4);-#ifdef DUMP_READ_OBJECT-            bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n");-#endif-        }-        bc_read_trace(s, "}\n");-    }-    {-        bc_read_trace(s, "bytecode {\n");-        if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))-            goto fail;-        bc_read_trace(s, "}\n");-    }-    if (b->has_debug) {-        /* read optional debug information */-        bc_read_trace(s, "debug {\n");-        if (bc_get_atom(s, &b->debug.filename))-            goto fail;-        if (bc_get_leb128_int(s, &b->debug.line_num))-            goto fail;-        if (bc_get_leb128_int(s, &b->debug.pc2line_len))-            goto fail;-        if (b->debug.pc2line_len) {-            b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len);-            if (!b->debug.pc2line_buf)-                goto fail;-            if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len))-                goto fail;-        }-#ifdef DUMP_READ_OBJECT-        bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n");-#endif-        bc_read_trace(s, "}\n");-    }-    if (b->cpool_count != 0) {-        bc_read_trace(s, "cpool {\n");-        b->cpool = (void *)((uint8_t*)b + cpool_offset);-        for(i = 0; i < b->cpool_count; i++) {-            JSValue val;-            val = JS_ReadObjectRec(s);-            if (JS_IsException(val))-                goto fail;-            b->cpool[i] = val;-        }-        bc_read_trace(s, "}\n");-    }-    b->realm = JS_DupContext(ctx);-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadModule(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSValue obj;-    JSModuleDef *m = NULL;-    JSAtom module_name;-    int i;-    uint8_t v8;-    -    if (bc_get_atom(s, &module_name))-        goto fail;-#ifdef DUMP_READ_OBJECT-    bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n");-#endif-    m = js_new_module_def(ctx, module_name);-    if (!m)-        goto fail;-    obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));-    if (bc_get_leb128_int(s, &m->req_module_entries_count))-        goto fail;-    if (m->req_module_entries_count != 0) {-        m->req_module_entries_size = m->req_module_entries_count;-        m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size);-        if (!m->req_module_entries)-            goto fail;-        for(i = 0; i < m->req_module_entries_count; i++) {-            JSReqModuleEntry *rme = &m->req_module_entries[i];-            if (bc_get_atom(s, &rme->module_name))-                goto fail;-        }-    }--    if (bc_get_leb128_int(s, &m->export_entries_count))-        goto fail;-    if (m->export_entries_count != 0) {-        m->export_entries_size = m->export_entries_count;-        m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size);-        if (!m->export_entries)-            goto fail;-        for(i = 0; i < m->export_entries_count; i++) {-            JSExportEntry *me = &m->export_entries[i];-            if (bc_get_u8(s, &v8))-                goto fail;-            me->export_type = v8;-            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {-                if (bc_get_leb128_int(s, &me->u.local.var_idx))-                    goto fail;-            } else {-                if (bc_get_leb128_int(s, &me->u.req_module_idx))-                    goto fail;-                if (bc_get_atom(s, &me->local_name))-                    goto fail;-            }-            if (bc_get_atom(s, &me->export_name))-                goto fail;-        }-    }--    if (bc_get_leb128_int(s, &m->star_export_entries_count))-        goto fail;-    if (m->star_export_entries_count != 0) {-        m->star_export_entries_size = m->star_export_entries_count;-        m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size);-        if (!m->star_export_entries)-            goto fail;-        for(i = 0; i < m->star_export_entries_count; i++) {-            JSStarExportEntry *se = &m->star_export_entries[i];-            if (bc_get_leb128_int(s, &se->req_module_idx))-                goto fail;-        }-    }--    if (bc_get_leb128_int(s, &m->import_entries_count))-        goto fail;-    if (m->import_entries_count != 0) {-        m->import_entries_size = m->import_entries_count;-        m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size);-        if (!m->import_entries)-            goto fail;-        for(i = 0; i < m->import_entries_count; i++) {-            JSImportEntry *mi = &m->import_entries[i];-            if (bc_get_leb128_int(s, &mi->var_idx))-                goto fail;-            if (bc_get_atom(s, &mi->import_name))-                goto fail;-            if (bc_get_leb128_int(s, &mi->req_module_idx))-                goto fail;-        }-    }--    m->func_obj = JS_ReadObjectRec(s);-    if (JS_IsException(m->func_obj))-        goto fail;-    return obj;- fail:-    if (m) {-        js_free_module_def(ctx, m);-    }-    return JS_EXCEPTION;-}--static JSValue JS_ReadObjectTag(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSValue obj;-    uint32_t prop_count, i;-    JSAtom atom;-    JSValue val;-    int ret;-    -    obj = JS_NewObject(ctx);-    if (BC_add_object_ref(s, obj))-        goto fail;-    if (bc_get_leb128(s, &prop_count))-        goto fail;-    for(i = 0; i < prop_count; i++) {-        if (bc_get_atom(s, &atom))-            goto fail;-#ifdef DUMP_READ_OBJECT-        bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n");-#endif-        val = JS_ReadObjectRec(s);-        if (JS_IsException(val)) {-            JS_FreeAtom(ctx, atom);-            goto fail;-        }-        ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E);-        JS_FreeAtom(ctx, atom);-        if (ret < 0)-            goto fail;-    }-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadArray(BCReaderState *s, int tag)-{-    JSContext *ctx = s->ctx;-    JSValue obj;-    uint32_t len, i;-    JSValue val;-    int ret, prop_flags;-    BOOL is_template;--    obj = JS_NewArray(ctx);-    if (BC_add_object_ref(s, obj))-        goto fail;-    is_template = (tag == BC_TAG_TEMPLATE_OBJECT);-    if (bc_get_leb128(s, &len))-        goto fail;-    for(i = 0; i < len; i++) {-        val = JS_ReadObjectRec(s);-        if (JS_IsException(val))-            goto fail;-        if (is_template)-            prop_flags = JS_PROP_ENUMERABLE;-        else-            prop_flags = JS_PROP_C_W_E;-        ret = JS_DefinePropertyValueUint32(ctx, obj, i, val,-                                           prop_flags);-        if (ret < 0)-            goto fail;-    }-    if (is_template) {-        val = JS_ReadObjectRec(s);-        if (JS_IsException(val))-            goto fail;-        if (!JS_IsUndefined(val)) {-            ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0);-            if (ret < 0)-                goto fail;-        }-        JS_PreventExtensions(ctx, obj);-    }-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadTypedArray(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED;-    uint8_t array_tag;-    JSValueConst args[3];-    uint32_t offset, len, idx;-    -    if (bc_get_u8(s, &array_tag))-        return JS_EXCEPTION;-    if (array_tag >= JS_TYPED_ARRAY_COUNT)-        return JS_ThrowTypeError(ctx, "invalid typed array");-    if (bc_get_leb128(s, &len))-        return JS_EXCEPTION;-    if (bc_get_leb128(s, &offset))-        return JS_EXCEPTION;-    /* XXX: this hack could be avoided if the typed array could be-       created before the array buffer */-    idx = s->objects_count;-    if (BC_add_object_ref1(s, NULL))-        goto fail;-    array_buffer = JS_ReadObjectRec(s);-    if (JS_IsException(array_buffer))-        return JS_EXCEPTION;-    if (!js_get_array_buffer(ctx, array_buffer)) {-        JS_FreeValue(ctx, array_buffer);-        return JS_EXCEPTION;-    }-    args[0] = array_buffer;-    args[1] = JS_NewInt64(ctx, offset);-    args[2] = JS_NewInt64(ctx, len);-    obj = js_typed_array_constructor(ctx, JS_UNDEFINED,-                                     3, args,-                                     JS_CLASS_UINT8C_ARRAY + array_tag);-    if (JS_IsException(obj))-        goto fail;-    if (s->allow_reference) {-        s->objects[idx] = JS_VALUE_GET_OBJ(obj);-    }-    JS_FreeValue(ctx, array_buffer);-    return obj;- fail:-    JS_FreeValue(ctx, array_buffer);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadArrayBuffer(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    uint32_t byte_length;-    JSValue obj;-    -    if (bc_get_leb128(s, &byte_length))-        return JS_EXCEPTION;-    if (unlikely(s->buf_end - s->ptr < byte_length)) {-        bc_read_error_end(s);-        return JS_EXCEPTION;-    }-    obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length);-    if (JS_IsException(obj))-        goto fail;-    if (BC_add_object_ref(s, obj))-        goto fail;-    s->ptr += byte_length;-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    uint32_t byte_length;-    uint8_t *data_ptr;-    JSValue obj;-    uint64_t u64;-    -    if (bc_get_leb128(s, &byte_length))-        return JS_EXCEPTION;-    if (bc_get_u64(s, &u64))-        return JS_EXCEPTION;-    data_ptr = (uint8_t *)(uintptr_t)u64;-    /* the SharedArrayBuffer is cloned */-    obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length,-                                       JS_CLASS_SHARED_ARRAY_BUFFER,-                                       data_ptr,-                                       NULL, NULL, FALSE);-    if (JS_IsException(obj))-        goto fail;-    if (BC_add_object_ref(s, obj))-        goto fail;-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadDate(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSValue val, obj = JS_UNDEFINED;--    val = JS_ReadObjectRec(s);-    if (JS_IsException(val))-        goto fail;-    if (!JS_IsNumber(val)) {-        JS_ThrowTypeError(ctx, "Number tag expected for date");-        goto fail;-    }-    obj = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_DATE],-                                 JS_CLASS_DATE);-    if (JS_IsException(obj))-        goto fail;-    if (BC_add_object_ref(s, obj))-        goto fail;-    JS_SetObjectData(ctx, obj, val);-    return obj;- fail:-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadObjectValue(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    JSValue val, obj = JS_UNDEFINED;--    val = JS_ReadObjectRec(s);-    if (JS_IsException(val))-        goto fail;-    obj = JS_ToObject(ctx, val);-    if (JS_IsException(obj))-        goto fail;-    if (BC_add_object_ref(s, obj))-        goto fail;-    JS_FreeValue(ctx, val);-    return obj;- fail:-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue JS_ReadObjectRec(BCReaderState *s)-{-    JSContext *ctx = s->ctx;-    uint8_t tag;-    JSValue obj = JS_UNDEFINED;--    if (js_check_stack_overflow(ctx->rt, 0))-        return JS_ThrowStackOverflow(ctx);--    if (bc_get_u8(s, &tag))-        return JS_EXCEPTION;--    bc_read_trace(s, "%s {\n", bc_tag_str[tag]);--    switch(tag) {-    case BC_TAG_NULL:-        obj = JS_NULL;-        break;-    case BC_TAG_UNDEFINED:-        obj = JS_UNDEFINED;-        break;-    case BC_TAG_BOOL_FALSE:-    case BC_TAG_BOOL_TRUE:-        obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE);-        break;-    case BC_TAG_INT32:-        {-            int32_t val;-            if (bc_get_sleb128(s, &val))-                return JS_EXCEPTION;-            bc_read_trace(s, "%d\n", val);-            obj = JS_NewInt32(ctx, val);-        }-        break;-    case BC_TAG_FLOAT64:-        {-            JSFloat64Union u;-            if (bc_get_u64(s, &u.u64))-                return JS_EXCEPTION;-            bc_read_trace(s, "%g\n", u.d);-            obj = __JS_NewFloat64(ctx, u.d);-        }-        break;-    case BC_TAG_STRING:-        {-            JSString *p;-            p = JS_ReadString(s);-            if (!p)-                return JS_EXCEPTION;-            obj = JS_MKPTR(JS_TAG_STRING, p);-        }-        break;-    case BC_TAG_FUNCTION_BYTECODE:-        if (!s->allow_bytecode)-            goto invalid_tag;-        obj = JS_ReadFunctionTag(s);-        break;-    case BC_TAG_MODULE:-        if (!s->allow_bytecode)-            goto invalid_tag;-        obj = JS_ReadModule(s);-        break;-    case BC_TAG_OBJECT:-        obj = JS_ReadObjectTag(s);-        break;-    case BC_TAG_ARRAY:-    case BC_TAG_TEMPLATE_OBJECT:-        obj = JS_ReadArray(s, tag);-        break;-    case BC_TAG_TYPED_ARRAY:-        obj = JS_ReadTypedArray(s);-        break;-    case BC_TAG_ARRAY_BUFFER:-        obj = JS_ReadArrayBuffer(s);-        break;-    case BC_TAG_SHARED_ARRAY_BUFFER:-        if (!s->allow_sab || !ctx->rt->sab_funcs.sab_dup)-            goto invalid_tag;-        obj = JS_ReadSharedArrayBuffer(s);-        break;-    case BC_TAG_DATE:-        obj = JS_ReadDate(s);-        break;-    case BC_TAG_OBJECT_VALUE:-        obj = JS_ReadObjectValue(s);-        break;-#ifdef CONFIG_BIGNUM-    case BC_TAG_BIG_INT:-    case BC_TAG_BIG_FLOAT:-    case BC_TAG_BIG_DECIMAL:-        obj = JS_ReadBigNum(s, tag);-        break;-#endif-    case BC_TAG_OBJECT_REFERENCE:-        {-            uint32_t val;-            if (!s->allow_reference)-                return JS_ThrowSyntaxError(ctx, "object references are not allowed");-            if (bc_get_leb128(s, &val))-                return JS_EXCEPTION;-            bc_read_trace(s, "%u\n", val);-            if (val >= s->objects_count) {-                return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)",-                                           val, s->objects_count);-            }-            obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));-        }-        break;-    default:-    invalid_tag:-        return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",-                                   tag, (unsigned int)(s->ptr - s->buf_start));-    }-    bc_read_trace(s, "}\n");-    return obj;-}--static int JS_ReadObjectAtoms(BCReaderState *s)-{-    uint8_t v8;-    JSString *p;-    int i;-    JSAtom atom;--    if (bc_get_u8(s, &v8))-        return -1;-    /* XXX: could support byte swapped input */-    if (v8 != BC_VERSION) {-        JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",-                            v8, BC_VERSION);-        return -1;-    }-    if (bc_get_leb128(s, &s->idx_to_atom_count))-        return -1;--    bc_read_trace(s, "%d atom indexes {\n", s->idx_to_atom_count);--    if (s->idx_to_atom_count != 0) {-        s->idx_to_atom = js_mallocz(s->ctx, s->idx_to_atom_count *-                                    sizeof(s->idx_to_atom[0]));-        if (!s->idx_to_atom)-            return s->error_state = -1;-    }-    for(i = 0; i < s->idx_to_atom_count; i++) {-        p = JS_ReadString(s);-        if (!p)-            return -1;-        atom = JS_NewAtomStr(s->ctx, p);-        if (atom == JS_ATOM_NULL)-            return s->error_state = -1;-        s->idx_to_atom[i] = atom;-        if (s->is_rom_data && (atom != (i + s->first_atom)))-            s->is_rom_data = FALSE; /* atoms must be relocated */-    }-    bc_read_trace(s, "}\n");-    return 0;-}--static void bc_reader_free(BCReaderState *s)-{-    int i;-    if (s->idx_to_atom) {-        for(i = 0; i < s->idx_to_atom_count; i++) {-            JS_FreeAtom(s->ctx, s->idx_to_atom[i]);-        }-        js_free(s->ctx, s->idx_to_atom);-    }-    js_free(s->ctx, s->objects);-}--JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,-                       int flags)-{-    BCReaderState ss, *s = &ss;-    JSValue obj;--    ctx->binary_object_count += 1;-    ctx->binary_object_size += buf_len;--    memset(s, 0, sizeof(*s));-    s->ctx = ctx;-    s->buf_start = buf;-    s->buf_end = buf + buf_len;-    s->ptr = buf;-    s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0);-    s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0);-    s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0);-    s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0);-    if (s->allow_bytecode)-        s->first_atom = JS_ATOM_END;-    else-        s->first_atom = 1;-    if (JS_ReadObjectAtoms(s)) {-        obj = JS_EXCEPTION;-    } else {-        obj = JS_ReadObjectRec(s);-    }-    bc_reader_free(s);-    return obj;-}--/*******************************************************************/-/* runtime functions & objects */--static JSValue js_string_constructor(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv);-static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv);-static JSValue js_number_constructor(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv);--static int check_function(JSContext *ctx, JSValueConst obj)-{-    if (likely(JS_IsFunction(ctx, obj)))-        return 0;-    JS_ThrowTypeError(ctx, "not a function");-    return -1;-}--static int check_exception_free(JSContext *ctx, JSValue obj)-{-    JS_FreeValue(ctx, obj);-    return JS_IsException(obj);-}--static JSAtom find_atom(JSContext *ctx, const char *name)-{-    JSAtom atom;-    int len;--    if (*name == '[') {-        name++;-        len = strlen(name) - 1;-        /* We assume 8 bit non null strings, which is the case for these-           symbols */-        for(atom = JS_ATOM_Symbol_toPrimitive; atom < JS_ATOM_END; atom++) {-            JSAtomStruct *p = ctx->rt->atom_array[atom];-            JSString *str = p;-            if (str->len == len && !memcmp(str->u.str8, name, len))-                return JS_DupAtom(ctx, atom);-        }-        abort();-    } else {-        atom = JS_NewAtom(ctx, name);-    }-    return atom;-}--static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,-                                          JSAtom atom, void *opaque)-{-    const JSCFunctionListEntry *e = opaque;-    JSValueConst obj = JS_MKPTR(JS_TAG_OBJECT, p);-    JSValue val;-    int prop_flags = e->prop_flags;--    switch(e->def_type) {-    case JS_DEF_ALIAS:-        {-            JSAtom atom1 = find_atom(ctx, e->u.alias.name);-            switch (e->u.alias.base) {-            case -1:-                val = JS_GetProperty(ctx, obj, atom1);-                break;-            case 0:-                val = JS_GetProperty(ctx, ctx->global_obj, atom1);-                break;-            case 1:-                val = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], atom1);-                break;-            default:-                abort();-            }-            JS_FreeAtom(ctx, atom1);-            goto setval;-        }-    case JS_DEF_CFUNC:-        val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,-                               e->name, e->u.func.length, e->u.func.cproto, e->magic);-    setval:-        if (atom == JS_ATOM_Symbol_toPrimitive) {-            /* Symbol.toPrimitive functions are not writable */-            prop_flags = JS_PROP_CONFIGURABLE;-        } else if (atom == JS_ATOM_Symbol_hasInstance) {-            /* Function.prototype[Symbol.hasInstance] is not writable nor configurable */-            prop_flags = 0;-        }-        break;-    case JS_DEF_CGETSET:-    case JS_DEF_CGETSET_MAGIC:-        {-            JSValue getter, setter;-            char buf[64];--            getter = JS_UNDEFINED;-            if (e->u.getset.get.generic) {-                snprintf(buf, sizeof(buf), "get %s", e->name);-                getter = JS_NewCFunction2(ctx, e->u.getset.get.generic,-                                          buf, 0, e->def_type == JS_DEF_CGETSET_MAGIC ? JS_CFUNC_getter_magic : JS_CFUNC_getter,-                                          e->magic);-            }-            setter = JS_UNDEFINED;-            if (e->u.getset.set.generic) {-                snprintf(buf, sizeof(buf), "set %s", e->name);-                setter = JS_NewCFunction2(ctx, e->u.getset.set.generic,-                                          buf, 1, e->def_type == JS_DEF_CGETSET_MAGIC ? JS_CFUNC_setter_magic : JS_CFUNC_setter,-                                          e->magic);-            }-            JS_DefinePropertyGetSet(ctx, obj, atom, getter, setter, prop_flags);-            return 0;-        }-        break;-    case JS_DEF_PROP_STRING:-        val = JS_NewAtomString(ctx, e->u.str);-        break;-    case JS_DEF_PROP_INT32:-        val = JS_NewInt32(ctx, e->u.i32);-        break;-    case JS_DEF_PROP_INT64:-        val = JS_NewInt64(ctx, e->u.i64);-        break;-    case JS_DEF_PROP_DOUBLE:-        val = __JS_NewFloat64(ctx, e->u.f64);-        break;-    case JS_DEF_PROP_UNDEFINED:-        val = JS_UNDEFINED;-        break;-    case JS_DEF_OBJECT:-        val = JS_NewObject(ctx);-        JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);-        break;-    default:-        abort();-    }-    JS_DefinePropertyValue(ctx, obj, atom, val, prop_flags);-    return 0;-}--void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,-                                const JSCFunctionListEntry *tab, int len)-{-    int i, prop_flags;--    for (i = 0; i < len; i++) {-        const JSCFunctionListEntry *e = &tab[i];-        JSAtom atom = find_atom(ctx, e->name);--        switch (e->def_type) {-        case JS_DEF_CFUNC:-        case JS_DEF_CGETSET:-        case JS_DEF_CGETSET_MAGIC:-        case JS_DEF_PROP_STRING:-        case JS_DEF_ALIAS:-        case JS_DEF_OBJECT:-            prop_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | (e->prop_flags & JS_PROP_ENUMERABLE);-            JS_DefineAutoInitProperty(ctx, obj, atom,-                                      JS_AUTOINIT_ID_PROP,-                                      (void *)e, prop_flags);-            break;-        case JS_DEF_PROP_INT32:-        case JS_DEF_PROP_INT64:-        case JS_DEF_PROP_DOUBLE:-        case JS_DEF_PROP_UNDEFINED:-            {-                JSObject *p = JS_VALUE_GET_OBJ(obj);-                JS_InstantiateFunctionListItem(ctx, p, atom, (void *)e);-            }-            break;-        default:-            abort();-        }-        JS_FreeAtom(ctx, atom);-    }-}--int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,-                           const JSCFunctionListEntry *tab, int len)-{-    int i;-    for(i = 0; i < len; i++) {-        if (JS_AddModuleExport(ctx, m, tab[i].name))-            return -1;-    }-    return 0;-}--int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,-                           const JSCFunctionListEntry *tab, int len)-{-    int i;-    JSValue val;--    for(i = 0; i < len; i++) {-        const JSCFunctionListEntry *e = &tab[i];-        switch(e->def_type) {-        case JS_DEF_CFUNC:-            val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,-                                   e->name, e->u.func.length, e->u.func.cproto, e->magic);-            break;-        case JS_DEF_PROP_STRING:-            val = JS_NewString(ctx, e->u.str);-            break;-        case JS_DEF_PROP_INT32:-            val = JS_NewInt32(ctx, e->u.i32);-            break;-        case JS_DEF_PROP_INT64:-            val = JS_NewInt64(ctx, e->u.i64);-            break;-        case JS_DEF_PROP_DOUBLE:-            val = __JS_NewFloat64(ctx, e->u.f64);-            break;-        case JS_DEF_OBJECT:-            val = JS_NewObject(ctx);-            JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);-            break;-        default:-            abort();-        }-        if (JS_SetModuleExport(ctx, m, e->name, val))-            return -1;-    }-    return 0;-}--/* Note: 'func_obj' is not necessarily a constructor */-static void JS_SetConstructor2(JSContext *ctx,-                               JSValueConst func_obj,-                               JSValueConst proto,-                               int proto_flags, int ctor_flags)-{-    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype,-                           JS_DupValue(ctx, proto), proto_flags);-    JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,-                           JS_DupValue(ctx, func_obj),-                           ctor_flags);-    set_cycle_flag(ctx, func_obj);-    set_cycle_flag(ctx, proto);-}--void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, -                       JSValueConst proto)-{-    JS_SetConstructor2(ctx, func_obj, proto,-                       0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-}--static void JS_NewGlobalCConstructor2(JSContext *ctx,-                                      JSValue func_obj,-                                      const char *name,-                                      JSValueConst proto)-{-    JS_DefinePropertyValueStr(ctx, ctx->global_obj, name,-                           JS_DupValue(ctx, func_obj),-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    JS_SetConstructor(ctx, func_obj, proto);-    JS_FreeValue(ctx, func_obj);-}--static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name,-                                             JSCFunction *func, int length,-                                             JSValueConst proto)-{-    JSValue func_obj;-    func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0);-    JS_NewGlobalCConstructor2(ctx, func_obj, name, proto);-    return func_obj;-}--static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name,-                                                 JSCFunction *func, int length,-                                                 JSValueConst proto)-{-    JSValue func_obj;-    func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0);-    JS_NewGlobalCConstructor2(ctx, func_obj, name, proto);-    return func_obj;-}--static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    return JS_EvalObject(ctx, ctx->global_obj, argv[0], JS_EVAL_TYPE_INDIRECT, -1);-}--static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    double d;--    /* XXX: does this work for bigfloat? */-    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))-        return JS_EXCEPTION;-    return JS_NewBool(ctx, isnan(d));-}--static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    BOOL res;-    double d;-    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))-        return JS_EXCEPTION;-    res = isfinite(d);-    return JS_NewBool(ctx, res);-}--/* Object class */--static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)-{-    int tag = JS_VALUE_GET_NORM_TAG(val);-    JSValue obj;--    switch(tag) {-    default:-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-        return JS_ThrowTypeError(ctx, "cannot convert to object");-    case JS_TAG_OBJECT:-    case JS_TAG_EXCEPTION:-        return JS_DupValue(ctx, val);-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT);-        goto set_value;-    case JS_TAG_BIG_FLOAT:-        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT);-        goto set_value;-    case JS_TAG_BIG_DECIMAL:-        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_DECIMAL);-        goto set_value;-#endif-    case JS_TAG_INT:-    case JS_TAG_FLOAT64:-        obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER);-        goto set_value;-    case JS_TAG_STRING:-        /* XXX: should call the string constructor */-        {-            JSString *p1 = JS_VALUE_GET_STRING(val);-            obj = JS_NewObjectClass(ctx, JS_CLASS_STRING);-            JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);-        }-        goto set_value;-    case JS_TAG_BOOL:-        obj = JS_NewObjectClass(ctx, JS_CLASS_BOOLEAN);-        goto set_value;-    case JS_TAG_SYMBOL:-        obj = JS_NewObjectClass(ctx, JS_CLASS_SYMBOL);-    set_value:-        if (!JS_IsException(obj))-            JS_SetObjectData(ctx, obj, JS_DupValue(ctx, val));-        return obj;-    }-}--static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val)-{-    JSValue obj = JS_ToObject(ctx, val);-    JS_FreeValue(ctx, val);-    return obj;-}--static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,-                          JSValueConst desc)-{-    JSValue val, getter, setter;-    int flags;--    if (!JS_IsObject(desc)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    flags = 0;-    val = JS_UNDEFINED;-    getter = JS_UNDEFINED;-    setter = JS_UNDEFINED;-    if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) {-        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable);-        if (JS_IsException(prop))-            goto fail;-        flags |= JS_PROP_HAS_CONFIGURABLE;-        if (JS_ToBoolFree(ctx, prop))-            flags |= JS_PROP_CONFIGURABLE;-    }-    if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) {-        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable);-        if (JS_IsException(prop))-            goto fail;-        flags |= JS_PROP_HAS_WRITABLE;-        if (JS_ToBoolFree(ctx, prop))-            flags |= JS_PROP_WRITABLE;-    }-    if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) {-        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);-        if (JS_IsException(prop))-            goto fail;-        flags |= JS_PROP_HAS_ENUMERABLE;-        if (JS_ToBoolFree(ctx, prop))-            flags |= JS_PROP_ENUMERABLE;-    }-    if (JS_HasProperty(ctx, desc, JS_ATOM_value)) {-        flags |= JS_PROP_HAS_VALUE;-        val = JS_GetProperty(ctx, desc, JS_ATOM_value);-        if (JS_IsException(val))-            goto fail;-    }-    if (JS_HasProperty(ctx, desc, JS_ATOM_get)) {-        flags |= JS_PROP_HAS_GET;-        getter = JS_GetProperty(ctx, desc, JS_ATOM_get);-        if (JS_IsException(getter) ||-            !(JS_IsUndefined(getter) || JS_IsFunction(ctx, getter))) {-            JS_ThrowTypeError(ctx, "invalid getter");-            goto fail;-        }-    }-    if (JS_HasProperty(ctx, desc, JS_ATOM_set)) {-        flags |= JS_PROP_HAS_SET;-        setter = JS_GetProperty(ctx, desc, JS_ATOM_set);-        if (JS_IsException(setter) ||-            !(JS_IsUndefined(setter) || JS_IsFunction(ctx, setter))) {-            JS_ThrowTypeError(ctx, "invalid setter");-            goto fail;-        }-    }-    if ((flags & (JS_PROP_HAS_SET | JS_PROP_HAS_GET)) &&-        (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE))) {-        JS_ThrowTypeError(ctx, "cannot have setter/getter and value or writable");-        goto fail;-    }-    d->flags = flags;-    d->value = val;-    d->getter = getter;-    d->setter = setter;-    return 0;- fail:-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, getter);-    JS_FreeValue(ctx, setter);-    return -1;-}--static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,-                                             JSAtom prop, JSValueConst desc,-                                             int flags)-{-    JSPropertyDescriptor d;-    int ret;--    if (js_obj_to_desc(ctx, &d, desc) < 0)-        return -1;--    ret = JS_DefineProperty(ctx, obj, prop,-                            d.value, d.getter, d.setter, d.flags | flags);-    js_free_desc(ctx, &d);-    return ret;-}--static __exception int JS_ObjectDefineProperties(JSContext *ctx,-                                                 JSValueConst obj,-                                                 JSValueConst properties)-{-    JSValue props, desc;-    JSObject *p;-    JSPropertyEnum *atoms;-    uint32_t len, i;-    int ret = -1;--    if (!JS_IsObject(obj)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    desc = JS_UNDEFINED;-    props = JS_ToObject(ctx, properties);-    if (JS_IsException(props))-        return -1;-    p = JS_VALUE_GET_OBJ(props);-    if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0)-        goto exception;-    for(i = 0; i < len; i++) {-        JS_FreeValue(ctx, desc);-        desc = JS_GetProperty(ctx, props, atoms[i].atom);-        if (JS_IsException(desc))-            goto exception;-        if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, JS_PROP_THROW) < 0)-            goto exception;-    }-    ret = 0;--exception:-    js_free_prop_enum(ctx, atoms, len);-    JS_FreeValue(ctx, props);-    JS_FreeValue(ctx, desc);-    return ret;-}--static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue ret;-    if (!JS_IsUndefined(new_target) &&-        JS_VALUE_GET_OBJ(new_target) !=-        JS_VALUE_GET_OBJ(JS_GetActiveFunction(ctx))) {-        ret = js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);-    } else {-        int tag = JS_VALUE_GET_NORM_TAG(argv[0]);-        switch(tag) {-        case JS_TAG_NULL:-        case JS_TAG_UNDEFINED:-            ret = JS_NewObject(ctx);-            break;-        default:-            ret = JS_ToObject(ctx, argv[0]);-            break;-        }-    }-    return ret;-}--static JSValue js_object_create(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValueConst proto, props;-    JSValue obj;--    proto = argv[0];-    if (!JS_IsObject(proto) && !JS_IsNull(proto))-        return JS_ThrowTypeError(ctx, "not a prototype");-    obj = JS_NewObjectProto(ctx, proto);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    props = argv[1];-    if (!JS_IsUndefined(props)) {-        if (JS_ObjectDefineProperties(ctx, obj, props)) {-            JS_FreeValue(ctx, obj);-            return JS_EXCEPTION;-        }-    }-    return obj;-}--static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv, int magic)-{-    JSValueConst val;--    val = argv[0];-    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) {-        /* ES6 feature non compatible with ES5.1: primitive types are-           accepted */-        if (magic || JS_VALUE_GET_TAG(val) == JS_TAG_NULL ||-            JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED)-            return JS_ThrowTypeErrorNotAnObject(ctx);-    }-    return JS_GetPrototype(ctx, val);-}--static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    JSValueConst obj;-    obj = argv[0];-    if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0)-        return JS_EXCEPTION;-    return JS_DupValue(ctx, obj);-}--/* magic = 1 if called as Reflect.defineProperty */-static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv, int magic)-{-    JSValueConst obj, prop, desc;-    int ret, flags;-    JSAtom atom;--    obj = argv[0];-    prop = argv[1];-    desc = argv[2];--    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    flags = 0;-    if (!magic)-        flags |= JS_PROP_THROW;-    ret = JS_DefinePropertyDesc(ctx, obj, atom, desc, flags);-    JS_FreeAtom(ctx, atom);-    if (ret < 0) {-        return JS_EXCEPTION;-    } else if (magic) {-        return JS_NewBool(ctx, ret);-    } else {-        return JS_DupValue(ctx, obj);-    }-}--static JSValue js_object_defineProperties(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv)-{-    // defineProperties(obj, properties)-    JSValueConst obj = argv[0];--    if (JS_ObjectDefineProperties(ctx, obj, argv[1]))-        return JS_EXCEPTION;-    else-        return JS_DupValue(ctx, obj);-}--/* magic = 1 if called as __defineSetter__ */-static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv, int magic)-{-    JSValue obj;-    JSValueConst prop, value, get, set;-    int ret, flags;-    JSAtom atom;--    prop = argv[0];-    value = argv[1];--    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        return JS_EXCEPTION;--    if (check_function(ctx, value)) {-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL)) {-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    flags = JS_PROP_THROW |-        JS_PROP_HAS_ENUMERABLE | JS_PROP_ENUMERABLE |-        JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE;-    if (magic) {-        get = JS_UNDEFINED;-        set = value;-        flags |= JS_PROP_HAS_SET;-    } else {-        get = value;-        set = JS_UNDEFINED;-        flags |= JS_PROP_HAS_GET;-    }-    ret = JS_DefineProperty(ctx, obj, atom, JS_UNDEFINED, get, set, flags);-    JS_FreeValue(ctx, obj);-    JS_FreeAtom(ctx, atom);-    if (ret < 0) {-        return JS_EXCEPTION;-    } else {-        return JS_UNDEFINED;-    }-}--static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val,-                                                  int argc, JSValueConst *argv, int magic)-{-    JSValueConst prop;-    JSAtom atom;-    JSValue ret, obj;-    JSPropertyDescriptor desc;-    int res, flags;--    if (magic) {-        /* Reflect.getOwnPropertyDescriptor case */-        if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)-            return JS_ThrowTypeErrorNotAnObject(ctx);-        obj = JS_DupValue(ctx, argv[0]);-    } else {-        obj = JS_ToObject(ctx, argv[0]);-        if (JS_IsException(obj))-            return obj;-    }-    prop = argv[1];-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL))-        goto exception;-    ret = JS_UNDEFINED;-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), atom);-        if (res < 0)-            goto exception;-        if (res) {-            ret = JS_NewObject(ctx);-            if (JS_IsException(ret))-                goto exception1;-            flags = JS_PROP_C_W_E | JS_PROP_THROW;-            if (desc.flags & JS_PROP_GETSET) {-                if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, desc.getter), flags) < 0-                ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, desc.setter), flags) < 0)-                    goto exception1;-            } else {-                if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0-                ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,-                                           JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0)-                    goto exception1;-            }-            if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,-                                       JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0), flags) < 0-            ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,-                                       JS_NewBool(ctx, (desc.flags & JS_PROP_CONFIGURABLE) != 0), flags) < 0)-                goto exception1;-            js_free_desc(ctx, &desc);-        }-    }-    JS_FreeAtom(ctx, atom);-    JS_FreeValue(ctx, obj);-    return ret;--exception1:-    js_free_desc(ctx, &desc);-    JS_FreeValue(ctx, ret);-exception:-    JS_FreeAtom(ctx, atom);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst this_val,-                                                   int argc, JSValueConst *argv)-{-    //getOwnPropertyDescriptors(obj)-    JSValue obj, r;-    JSObject *p;-    JSPropertyEnum *props;-    uint32_t len, i;--    r = JS_UNDEFINED;-    obj = JS_ToObject(ctx, argv[0]);-    if (JS_IsException(obj))-        return JS_EXCEPTION;--    p = JS_VALUE_GET_OBJ(obj);-    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p,-                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK))-        goto exception;-    r = JS_NewObject(ctx);-    if (JS_IsException(r))-        goto exception;-    for(i = 0; i < len; i++) {-        JSValue atomValue, desc;-        JSValueConst args[2];--        atomValue = JS_AtomToValue(ctx, props[i].atom);-        if (JS_IsException(atomValue))-            goto exception;-        args[0] = obj;-        args[1] = atomValue;-        desc = js_object_getOwnPropertyDescriptor(ctx, JS_UNDEFINED, 2, args, 0);-        JS_FreeValue(ctx, atomValue);-        if (JS_IsException(desc))-            goto exception;-        if (!JS_IsUndefined(desc)) {-            if (JS_DefinePropertyValue(ctx, r, props[i].atom, desc,-                                       JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    js_free_prop_enum(ctx, props, len);-    JS_FreeValue(ctx, obj);-    return r;--exception:-    js_free_prop_enum(ctx, props, len);-    JS_FreeValue(ctx, obj);-    JS_FreeValue(ctx, r);-    return JS_EXCEPTION;-}--static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,-                                       int flags, int kind)-{-    JSValue obj, r, val, key, value;-    JSObject *p;-    JSPropertyEnum *atoms;-    uint32_t len, i, j;--    r = JS_UNDEFINED;-    val = JS_UNDEFINED;-    obj = JS_ToObject(ctx, obj1);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    p = JS_VALUE_GET_OBJ(obj);-    if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, flags & ~JS_GPN_ENUM_ONLY))-        goto exception;-    r = JS_NewArray(ctx);-    if (JS_IsException(r))-        goto exception;-    for(j = i = 0; i < len; i++) {-        JSAtom atom = atoms[i].atom;-        if (flags & JS_GPN_ENUM_ONLY) {-            JSPropertyDescriptor desc;-            int res;--            /* Check if property is still enumerable */-            res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);-            if (res < 0)-                goto exception;-            if (!res)-                continue;-            js_free_desc(ctx, &desc);-            if (!(desc.flags & JS_PROP_ENUMERABLE))-                continue;-        }-        switch(kind) {-        default:-        case JS_ITERATOR_KIND_KEY:-            val = JS_AtomToValue(ctx, atom);-            if (JS_IsException(val))-                goto exception;-            break;-        case JS_ITERATOR_KIND_VALUE:-            val = JS_GetProperty(ctx, obj, atom);-            if (JS_IsException(val))-                goto exception;-            break;-        case JS_ITERATOR_KIND_KEY_AND_VALUE:-            val = JS_NewArray(ctx);-            if (JS_IsException(val))-                goto exception;-            key = JS_AtomToValue(ctx, atom);-            if (JS_IsException(key))-                goto exception1;-            if (JS_CreateDataPropertyUint32(ctx, val, 0, key, JS_PROP_THROW) < 0)-                goto exception1;-            value = JS_GetProperty(ctx, obj, atom);-            if (JS_IsException(value))-                goto exception1;-            if (JS_CreateDataPropertyUint32(ctx, val, 1, value, JS_PROP_THROW) < 0)-                goto exception1;-            break;-        }-        if (JS_CreateDataPropertyUint32(ctx, r, j++, val, 0) < 0)-            goto exception;-    }-    goto done;--exception1:-    JS_FreeValue(ctx, val);-exception:-    JS_FreeValue(ctx, r);-    r = JS_EXCEPTION;-done:-    js_free_prop_enum(ctx, atoms, len);-    JS_FreeValue(ctx, obj);-    return r;-}--static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValueConst this_val,-                                             int argc, JSValueConst *argv)-{-    return JS_GetOwnPropertyNames2(ctx, argv[0],-                                   JS_GPN_STRING_MASK, JS_ITERATOR_KIND_KEY);-}--static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValueConst this_val,-                                             int argc, JSValueConst *argv)-{-    return JS_GetOwnPropertyNames2(ctx, argv[0],-                                   JS_GPN_SYMBOL_MASK, JS_ITERATOR_KIND_KEY);-}--static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int kind)-{-    return JS_GetOwnPropertyNames2(ctx, argv[0],-                                   JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind);-}--static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv, int reflect)-{-    JSValueConst obj;-    int ret;--    obj = argv[0];-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {-        if (reflect)-            return JS_ThrowTypeErrorNotAnObject(ctx);-        else-            return JS_FALSE;-    }-    ret = JS_IsExtensible(ctx, obj);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val,-                                           int argc, JSValueConst *argv, int reflect)-{-    JSValueConst obj;-    int ret;--    obj = argv[0];-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {-        if (reflect)-            return JS_ThrowTypeErrorNotAnObject(ctx);-        else-            return JS_DupValue(ctx, obj);-    }-    ret = JS_PreventExtensions(ctx, obj);-    if (ret < 0)-        return JS_EXCEPTION;-    if (reflect) {-        return JS_NewBool(ctx, ret);-    } else {-        if (!ret)-            return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");-        return JS_DupValue(ctx, obj);-    }-}--static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    JSValue obj;-    JSAtom atom;-    JSObject *p;-    BOOL ret;--    atom = JS_ValueToAtom(ctx, argv[0]); /* must be done first */-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj)) {-        JS_FreeAtom(ctx, atom);-        return obj;-    }-    p = JS_VALUE_GET_OBJ(obj);-    ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);-    JS_FreeAtom(ctx, atom);-    JS_FreeValue(ctx, obj);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return JS_ToObject(ctx, this_val);-}--static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValue obj, tag;-    int is_array;-    JSAtom atom;-    JSObject *p;--    if (JS_IsNull(this_val)) {-        tag = JS_NewString(ctx, "Null");-    } else if (JS_IsUndefined(this_val)) {-        tag = JS_NewString(ctx, "Undefined");-    } else {-        obj = JS_ToObject(ctx, this_val);-        if (JS_IsException(obj))-            return obj;-        is_array = JS_IsArray(ctx, obj);-        if (is_array < 0) {-            JS_FreeValue(ctx, obj);-            return JS_EXCEPTION;-        }-        if (is_array) {-            atom = JS_ATOM_Array;-        } else if (JS_IsFunction(ctx, obj)) {-            atom = JS_ATOM_Function;-        } else {-            p = JS_VALUE_GET_OBJ(obj);-            switch(p->class_id) {-            case JS_CLASS_STRING:-            case JS_CLASS_ARGUMENTS:-            case JS_CLASS_MAPPED_ARGUMENTS:-            case JS_CLASS_ERROR:-            case JS_CLASS_BOOLEAN:-            case JS_CLASS_NUMBER:-            case JS_CLASS_DATE:-            case JS_CLASS_REGEXP:-                atom = ctx->rt->class_array[p->class_id].class_name;-                break;-            default:-                atom = JS_ATOM_Object;-                break;-            }-        }-        tag = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_toStringTag);-        JS_FreeValue(ctx, obj);-        if (JS_IsException(tag))-            return JS_EXCEPTION;-        if (!JS_IsString(tag)) {-            JS_FreeValue(ctx, tag);-            tag = JS_AtomToString(ctx, atom);-        }-    }-    return JS_ConcatString3(ctx, "[object ", tag, "]");-}--static JSValue js_object_toLocaleString(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    return JS_Invoke(ctx, this_val, JS_ATOM_toString, 0, NULL);-}--static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    // Object.assign(obj, source1)-    JSValue obj, s;-    int i;--    s = JS_UNDEFINED;-    obj = JS_ToObject(ctx, argv[0]);-    if (JS_IsException(obj))-        goto exception;-    for (i = 1; i < argc; i++) {-        if (!JS_IsNull(argv[i]) && !JS_IsUndefined(argv[i])) {-            s = JS_ToObject(ctx, argv[i]);-            if (JS_IsException(s))-                goto exception;-            if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, TRUE))-                goto exception;-            JS_FreeValue(ctx, s);-        }-    }-    return obj;-exception:-    JS_FreeValue(ctx, obj);-    JS_FreeValue(ctx, s);-    return JS_EXCEPTION;-}--static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int freeze_flag)-{-    JSValueConst obj = argv[0];-    JSObject *p;-    JSPropertyEnum *props;-    uint32_t len, i;-    int flags, desc_flags, res;--    if (!JS_IsObject(obj))-        return JS_DupValue(ctx, obj);--    res = JS_PreventExtensions(ctx, obj);-    if (res < 0)-        return JS_EXCEPTION;-    if (!res) {-        return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");-    }-    -    p = JS_VALUE_GET_OBJ(obj);-    flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;-    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))-        return JS_EXCEPTION;--    for(i = 0; i < len; i++) {-        JSPropertyDescriptor desc;-        JSAtom prop = props[i].atom;--        desc_flags = JS_PROP_THROW | JS_PROP_HAS_CONFIGURABLE;-        if (freeze_flag) {-            res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);-            if (res < 0)-                goto exception;-            if (res) {-                if (desc.flags & JS_PROP_WRITABLE)-                    desc_flags |= JS_PROP_HAS_WRITABLE;-                js_free_desc(ctx, &desc);-            }-        }-        if (JS_DefineProperty(ctx, obj, prop, JS_UNDEFINED,-                              JS_UNDEFINED, JS_UNDEFINED, desc_flags) < 0)-            goto exception;-    }-    js_free_prop_enum(ctx, props, len);-    return JS_DupValue(ctx, obj);-- exception:-    js_free_prop_enum(ctx, props, len);-    return JS_EXCEPTION;-}--static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv, int is_frozen)-{-    JSValueConst obj = argv[0];-    JSObject *p;-    JSPropertyEnum *props;-    uint32_t len, i;-    int flags, res;-    -    if (!JS_IsObject(obj))-        return JS_TRUE;--    p = JS_VALUE_GET_OBJ(obj);-    flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;-    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))-        return JS_EXCEPTION;--    for(i = 0; i < len; i++) {-        JSPropertyDescriptor desc;-        JSAtom prop = props[i].atom;--        res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);-        if (res < 0)-            goto exception;-        if (res) {-            js_free_desc(ctx, &desc);-            if ((desc.flags & JS_PROP_CONFIGURABLE)-            ||  (is_frozen && (desc.flags & JS_PROP_WRITABLE))) {-                res = FALSE;-                goto done;-            }-        }-    }-    res = JS_IsExtensible(ctx, obj);-    if (res < 0)-        return JS_EXCEPTION;-    res ^= 1;-done:        -    js_free_prop_enum(ctx, props, len);-    return JS_NewBool(ctx, res);--exception:-    js_free_prop_enum(ctx, props, len);-    return JS_EXCEPTION;-}--static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue obj, iter, next_method = JS_UNDEFINED;-    JSValueConst iterable;-    BOOL done;--    /*  RequireObjectCoercible() not necessary because it is tested in-        JS_GetIterator() by JS_GetProperty() */-    iterable = argv[0];--    obj = JS_NewObject(ctx);-    if (JS_IsException(obj))-        return obj;-    -    iter = JS_GetIterator(ctx, iterable, FALSE);-    if (JS_IsException(iter))-        goto fail;-    next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);-    if (JS_IsException(next_method))-        goto fail;-    -    for(;;) {-        JSValue key, value, item;-        item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);-        if (JS_IsException(item))-            goto fail;-        if (done) {-            JS_FreeValue(ctx, item);-            break;-        }-        -        key = JS_UNDEFINED;-        value = JS_UNDEFINED;-        if (!JS_IsObject(item)) {-            JS_ThrowTypeErrorNotAnObject(ctx);-            goto fail1;-        }-        key = JS_GetPropertyUint32(ctx, item, 0);-        if (JS_IsException(key))-            goto fail1;-        value = JS_GetPropertyUint32(ctx, item, 1);-        if (JS_IsException(value)) {-            JS_FreeValue(ctx, key);-            goto fail1;-        }-        if (JS_DefinePropertyValueValue(ctx, obj, key, value,-                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0) {-        fail1:-            JS_FreeValue(ctx, item);-            goto fail;-        }-        JS_FreeValue(ctx, item);-    }-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    return obj;- fail:-    if (JS_IsObject(iter)) {-        /* close the iterator object, preserving pending exception */-        JS_IteratorClose(ctx, iter, TRUE);-    }-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--#if 0-/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */-static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv)-{-    int ret;-    ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]),-                                      JS_DupValue(ctx, argv[2]),-                                      JS_PROP_C_W_E | JS_PROP_THROW);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    return JS_ToObject(ctx, argv[0]);-}--static JSValue js_object___toPrimitive(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    int hint = HINT_NONE;--    if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT)-        hint = JS_VALUE_GET_INT(argv[1]);--    return JS_ToPrimitive(ctx, argv[0], hint);-}-#endif--/* return an empty string if not an object */-static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSAtom atom;-    JSObject *p;-    uint32_t tag;-    int class_id;--    tag = JS_VALUE_GET_NORM_TAG(argv[0]);-    if (tag == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(argv[0]);-        class_id = p->class_id;-        if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0]))-            class_id = JS_CLASS_BYTECODE_FUNCTION;-        atom = ctx->rt->class_array[class_id].class_name;-    } else {-        atom = JS_ATOM_empty_string;-    }-    return JS_AtomToString(ctx, atom);-}--static JSValue js_object_is(JSContext *ctx, JSValueConst this_val,-                            int argc, JSValueConst *argv)-{-    return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1]));-}--#if 0-static JSValue js_object___getObjectData(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    return JS_GetObjectData(ctx, argv[0]);-}--static JSValue js_object___setObjectData(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    if (JS_SetObjectData(ctx, argv[0], JS_DupValue(ctx, argv[1])))-        return JS_EXCEPTION;-    return JS_DupValue(ctx, argv[1]);-}--static JSValue js_object___toPropertyKey(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    return JS_ToPropertyKey(ctx, argv[0]);-}--static JSValue js_object___isObject(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    return JS_NewBool(ctx, JS_IsObject(argv[0]));-}--static JSValue js_object___isSameValueZero(JSContext *ctx, JSValueConst this_val,-                                           int argc, JSValueConst *argv)-{-    return JS_NewBool(ctx, js_same_value_zero(ctx, argv[0], argv[1]));-}--static JSValue js_object___isConstructor(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    return JS_NewBool(ctx, JS_IsConstructor(ctx, argv[0]));-}-#endif--static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,-                                     JSValueConst defaultConstructor)-{-    JSValue ctor, species;--    if (!JS_IsObject(obj))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    ctor = JS_GetProperty(ctx, obj, JS_ATOM_constructor);-    if (JS_IsException(ctor))-        return ctor;-    if (JS_IsUndefined(ctor))-        return JS_DupValue(ctx, defaultConstructor);-    if (!JS_IsObject(ctor)) {-        JS_FreeValue(ctx, ctor);-        return JS_ThrowTypeErrorNotAnObject(ctx);-    }-    species = JS_GetProperty(ctx, ctor, JS_ATOM_Symbol_species);-    JS_FreeValue(ctx, ctor);-    if (JS_IsException(species))-        return species;-    if (JS_IsUndefined(species) || JS_IsNull(species))-        return JS_DupValue(ctx, defaultConstructor);-    if (!JS_IsConstructor(ctx, species)) {-        JS_FreeValue(ctx, species);-        return JS_ThrowTypeError(ctx, "not a constructor");-    }-    return species;-}--#if 0-static JSValue js_object___speciesConstructor(JSContext *ctx, JSValueConst this_val,-                                              int argc, JSValueConst *argv)-{-    return JS_SpeciesConstructor(ctx, argv[0], argv[1]);-}-#endif--static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val)-{-    JSValue val, ret;--    val = JS_ToObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    ret = JS_GetPrototype(ctx, val);-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val,-                                       JSValueConst proto)-{-    if (JS_IsUndefined(this_val) || JS_IsNull(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    if (!JS_IsObject(proto) && !JS_IsNull(proto))-        return JS_UNDEFINED;-    if (JS_SetPrototypeInternal(ctx, this_val, proto, TRUE) < 0)-        return JS_EXCEPTION;-    else-        return JS_UNDEFINED;-}--static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue obj, v1;-    JSValueConst v;-    int res;--    v = argv[0];-    if (!JS_IsObject(v))-        return JS_FALSE;-    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    v1 = JS_DupValue(ctx, v);-    for(;;) {-        v1 = JS_GetPrototypeFree(ctx, v1);-        if (JS_IsException(v1))-            goto exception;-        if (JS_IsNull(v1)) {-            res = FALSE;-            break;-        }-        if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) {-            res = TRUE;-            break;-        }-        /* avoid infinite loop (possible with proxies) */-        if (js_poll_interrupts(ctx))-            goto exception;-    }-    JS_FreeValue(ctx, v1);-    JS_FreeValue(ctx, obj);-    return JS_NewBool(ctx, res);--exception:-    JS_FreeValue(ctx, v1);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_val,-                                              int argc, JSValueConst *argv)-{-    JSValue obj, res = JS_EXCEPTION;-    JSAtom prop = JS_ATOM_NULL;-    JSPropertyDescriptor desc;-    int has_prop;--    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        goto exception;-    prop = JS_ValueToAtom(ctx, argv[0]);-    if (unlikely(prop == JS_ATOM_NULL))-        goto exception;--    has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop);-    if (has_prop < 0)-        goto exception;-    if (has_prop) {-        res = JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0);-        js_free_desc(ctx, &desc);-    } else {-        res = JS_FALSE;-    }--exception:-    JS_FreeAtom(ctx, prop);-    JS_FreeValue(ctx, obj);-    return res;-}--static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv, int setter)-{-    JSValue obj, res = JS_EXCEPTION;-    JSAtom prop = JS_ATOM_NULL;-    JSPropertyDescriptor desc;-    int has_prop;--    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        goto exception;-    prop = JS_ValueToAtom(ctx, argv[0]);-    if (unlikely(prop == JS_ATOM_NULL))-        goto exception;--    for (;;) {-        has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop);-        if (has_prop < 0)-            goto exception;-        if (has_prop) {-            if (desc.flags & JS_PROP_GETSET)-                res = JS_DupValue(ctx, setter ? desc.setter : desc.getter);-            else-                res = JS_UNDEFINED;-            js_free_desc(ctx, &desc);-            break;-        }-        obj = JS_GetPrototypeFree(ctx, obj);-        if (JS_IsException(obj))-            goto exception;-        if (JS_IsNull(obj)) {-            res = JS_UNDEFINED;-            break;-        }-        /* avoid infinite loop (possible with proxies) */-        if (js_poll_interrupts(ctx))-            goto exception;-    }--exception:-    JS_FreeAtom(ctx, prop);-    JS_FreeValue(ctx, obj);-    return res;-}--static const JSCFunctionListEntry js_object_funcs[] = {-    JS_CFUNC_DEF("create", 2, js_object_create ),-    JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),-    JS_CFUNC_DEF("setPrototypeOf", 2, js_object_setPrototypeOf ),-    JS_CFUNC_MAGIC_DEF("defineProperty", 3, js_object_defineProperty, 0 ),-    JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ),-    JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ),-    JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ),-    JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ),-    JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ),-    JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ),-    JS_CFUNC_MAGIC_DEF("isExtensible", 1, js_object_isExtensible, 0 ),-    JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 0 ),-    JS_CFUNC_MAGIC_DEF("getOwnPropertyDescriptor", 2, js_object_getOwnPropertyDescriptor, 0 ),-    JS_CFUNC_DEF("getOwnPropertyDescriptors", 1, js_object_getOwnPropertyDescriptors ),-    JS_CFUNC_DEF("is", 2, js_object_is ),-    JS_CFUNC_DEF("assign", 2, js_object_assign ),-    JS_CFUNC_MAGIC_DEF("seal", 1, js_object_seal, 0 ),-    JS_CFUNC_MAGIC_DEF("freeze", 1, js_object_seal, 1 ),-    JS_CFUNC_MAGIC_DEF("isSealed", 1, js_object_isSealed, 0 ),-    JS_CFUNC_MAGIC_DEF("isFrozen", 1, js_object_isSealed, 1 ),-    JS_CFUNC_DEF("__getClass", 1, js_object___getClass ),-    //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ),-    //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ),-    //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ),-    //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ),-    //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ),-    //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ),-    //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ),-    //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ),-    //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ),-    //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ),-    JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ),-};--static const JSCFunctionListEntry js_object_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_object_toString ),-    JS_CFUNC_DEF("toLocaleString", 0, js_object_toLocaleString ),-    JS_CFUNC_DEF("valueOf", 0, js_object_valueOf ),-    JS_CFUNC_DEF("hasOwnProperty", 1, js_object_hasOwnProperty ),-    JS_CFUNC_DEF("isPrototypeOf", 1, js_object_isPrototypeOf ),-    JS_CFUNC_DEF("propertyIsEnumerable", 1, js_object_propertyIsEnumerable ),-    JS_CGETSET_DEF("__proto__", js_object_get___proto__, js_object_set___proto__ ),-    JS_CFUNC_MAGIC_DEF("__defineGetter__", 2, js_object___defineGetter__, 0 ),-    JS_CFUNC_MAGIC_DEF("__defineSetter__", 2, js_object___defineGetter__, 1 ),-    JS_CFUNC_MAGIC_DEF("__lookupGetter__", 1, js_object___lookupGetter__, 0 ),-    JS_CFUNC_MAGIC_DEF("__lookupSetter__", 1, js_object___lookupGetter__, 1 ),-};--/* Function class */--static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return JS_UNDEFINED;-}--/* XXX: add a specific eval mode so that Function("}), ({") is rejected */-static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,-                                       int argc, JSValueConst *argv, int magic)-{-    JSFunctionKindEnum func_kind = magic;-    int i, n, ret;-    JSValue s, proto, obj = JS_UNDEFINED;-    StringBuffer b_s, *b = &b_s;--    string_buffer_init(ctx, b, 0);-    string_buffer_putc8(b, '(');-    -    if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) {-        string_buffer_puts8(b, "async ");-    }-    string_buffer_puts8(b, "function");--    if (func_kind == JS_FUNC_GENERATOR || func_kind == JS_FUNC_ASYNC_GENERATOR) {-        string_buffer_putc8(b, '*');-    }-    string_buffer_puts8(b, " anonymous(");--    n = argc - 1;-    for(i = 0; i < n; i++) {-        if (i != 0) {-            string_buffer_putc8(b, ',');-        }-        if (string_buffer_concat_value(b, argv[i]))-            goto fail;-    }-    string_buffer_puts8(b, "\n) {\n");-    if (n >= 0) {-        if (string_buffer_concat_value(b, argv[n]))-            goto fail;-    }-    string_buffer_puts8(b, "\n})");-    s = string_buffer_end(b);-    if (JS_IsException(s))-        goto fail1;--    obj = JS_EvalObject(ctx, ctx->global_obj, s, JS_EVAL_TYPE_INDIRECT, -1);-    JS_FreeValue(ctx, s);-    if (JS_IsException(obj))-        goto fail1;-    if (!JS_IsUndefined(new_target)) {-        /* set the prototype */-        proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);-        if (JS_IsException(proto))-            goto fail1;-        if (!JS_IsObject(proto)) {-            JSContext *realm;-            JS_FreeValue(ctx, proto);-            realm = JS_GetFunctionRealm(ctx, new_target);-            if (!realm)-                goto fail1;-            proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]);-        }-        ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);-        JS_FreeValue(ctx, proto);-        if (ret < 0)-            goto fail1;-    }-    return obj;-- fail:-    string_buffer_free(b);- fail1:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,-                                       JSValueConst obj)-{-    JSValue len_val;-    len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);-    if (JS_IsException(len_val)) {-        *pres = 0;-        return -1;-    }-    return JS_ToUint32Free(ctx, pres, len_val);-}--static __exception int js_get_length64(JSContext *ctx, int64_t *pres,-                                       JSValueConst obj)-{-    JSValue len_val;-    len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);-    if (JS_IsException(len_val)) {-        *pres = 0;-        return -1;-    }-    return JS_ToLengthFree(ctx, pres, len_val);-}--static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)-{-    uint32_t i;-    for(i = 0; i < len; i++) {-        JS_FreeValue(ctx, tab[i]);-    }-    js_free(ctx, tab);-}--/* XXX: should use ValueArray */-static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,-                               JSValueConst array_arg)-{-    uint32_t len, i;-    JSValue *tab, ret;-    JSObject *p;--    if (JS_VALUE_GET_TAG(array_arg) != JS_TAG_OBJECT) {-        JS_ThrowTypeError(ctx, "not a object");-        return NULL;-    }-    if (js_get_length32(ctx, &len, array_arg))-        return NULL;-    /* avoid allocating 0 bytes */-    tab = js_mallocz(ctx, sizeof(tab[0]) * max_uint32(1, len));-    if (!tab)-        return NULL;-    p = JS_VALUE_GET_OBJ(array_arg);-    if ((p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) &&-        p->fast_array &&-        len == p->u.array.count) {-        for(i = 0; i < len; i++) {-            tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]);-        }-    } else {-        for(i = 0; i < len; i++) {-            ret = JS_GetPropertyUint32(ctx, array_arg, i);-            if (JS_IsException(ret)) {-                free_arg_list(ctx, tab, i);-                return NULL;-            }-            tab[i] = ret;-        }-    }-    *plen = len;-    return tab;-}--static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv, int magic)-{-    JSValueConst this_arg, array_arg;-    uint32_t len;-    JSValue *tab, ret;--    if (check_function(ctx, this_val))-        return JS_EXCEPTION;-    this_arg = argv[0];-    array_arg = argv[1];-    if (JS_VALUE_GET_TAG(array_arg) == JS_TAG_UNDEFINED ||-        JS_VALUE_GET_TAG(array_arg) == JS_TAG_NULL) {-        return JS_Call(ctx, this_val, this_arg, 0, NULL);-    }-    tab = build_arg_list(ctx, &len, array_arg);-    if (!tab)-        return JS_EXCEPTION;-    if (magic) {-        ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);-    } else {-        ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);-    }-    free_arg_list(ctx, tab, len);-    return ret;-}--static JSValue js_function_call(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    if (argc <= 0) {-        return JS_Call(ctx, this_val, JS_UNDEFINED, 0, NULL);-    } else {-        return JS_Call(ctx, this_val, argv[0], argc - 1, argv + 1);-    }-}--static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSBoundFunction *bf;-    JSValue func_obj, name1, len_val;-    JSObject *p;-    int arg_count, i, ret;--    if (check_function(ctx, this_val))-        return JS_EXCEPTION;--    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,-                                 JS_CLASS_BOUND_FUNCTION);-    if (JS_IsException(func_obj))-        return JS_EXCEPTION;-    p = JS_VALUE_GET_OBJ(func_obj);-    p->is_constructor = JS_IsConstructor(ctx, this_val);-    arg_count = max_int(0, argc - 1);-    bf = js_malloc(ctx, sizeof(*bf) + arg_count * sizeof(JSValue));-    if (!bf)-        goto exception;-    bf->func_obj = JS_DupValue(ctx, this_val);-    bf->this_val = JS_DupValue(ctx, argv[0]);-    bf->argc = arg_count;-    for(i = 0; i < arg_count; i++) {-        bf->argv[i] = JS_DupValue(ctx, argv[i + 1]);-    }-    p->u.bound_function = bf;--    /* XXX: the spec could be simpler by only using GetOwnProperty */-    ret = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_length);-    if (ret < 0)-        goto exception;-    if (!ret) {-        len_val = JS_NewInt32(ctx, 0);-    } else {-        len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length);-        if (JS_IsException(len_val))-            goto exception;-        if (JS_VALUE_GET_TAG(len_val) == JS_TAG_INT) {-            /* most common case */-            int len1 = JS_VALUE_GET_INT(len_val);-            if (len1 <= arg_count)-                len1 = 0;-            else-                len1 -= arg_count;-            len_val = JS_NewInt32(ctx, len1);-        } else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) {-            double d = JS_VALUE_GET_FLOAT64(len_val);-            if (isnan(d)) {-                d = 0.0;-            } else {-                d = trunc(d);-                if (d <= (double)arg_count)-                    d = 0.0;-                else-                    d -= (double)arg_count; /* also converts -0 to +0 */-            }-            len_val = JS_NewFloat64(ctx, d);-        } else {-            JS_FreeValue(ctx, len_val);-            len_val = JS_NewInt32(ctx, 0);-        }-    }-    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length,-                           len_val, JS_PROP_CONFIGURABLE);--    name1 = JS_GetProperty(ctx, this_val, JS_ATOM_name);-    if (JS_IsException(name1))-        goto exception;-    if (!JS_IsString(name1)) {-        JS_FreeValue(ctx, name1);-        name1 = JS_AtomToString(ctx, JS_ATOM_empty_string);-    }-    name1 = JS_ConcatString3(ctx, "bound ", name1, "");-    if (JS_IsException(name1))-        goto exception;-    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name1,-                           JS_PROP_CONFIGURABLE);-    return func_obj;- exception:-    JS_FreeValue(ctx, func_obj);-    return JS_EXCEPTION;-}--static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSObject *p;-    JSFunctionKindEnum func_kind = JS_FUNC_NORMAL;--    if (check_function(ctx, this_val))-        return JS_EXCEPTION;--    p = JS_VALUE_GET_OBJ(this_val);-    if (js_class_has_bytecode(p->class_id)) {-        JSFunctionBytecode *b = p->u.func.function_bytecode;-        if (b->has_debug && b->debug.source) {-            return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);-        }-        func_kind = b->func_kind;-    }-    {-        JSValue name;-        const char *pref, *suff;--        switch(func_kind) {-        default:-        case JS_FUNC_NORMAL:-            pref = "function ";-            break;-        case JS_FUNC_GENERATOR:-            pref = "function *";-            break;-        case JS_FUNC_ASYNC:-            pref = "async function ";-            break;-        case JS_FUNC_ASYNC_GENERATOR:-            pref = "async function *";-            break;-        }-        suff = "() {\n    [native code]\n}";-        name = JS_GetProperty(ctx, this_val, JS_ATOM_name);-        if (JS_IsUndefined(name))-            name = JS_AtomToString(ctx, JS_ATOM_empty_string);-        return JS_ConcatString3(ctx, pref, name, suff);-    }-}--static JSValue js_function_hasInstance(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    int ret;-    ret = JS_OrdinaryIsInstanceOf(ctx, argv[0], this_val);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static const JSCFunctionListEntry js_function_proto_funcs[] = {-    JS_CFUNC_DEF("call", 1, js_function_call ),-    JS_CFUNC_MAGIC_DEF("apply", 2, js_function_apply, 0 ),-    JS_CFUNC_DEF("bind", 1, js_function_bind ),-    JS_CFUNC_DEF("toString", 0, js_function_toString ),-    JS_CFUNC_DEF("[Symbol.hasInstance]", 1, js_function_hasInstance ),-    JS_CGETSET_DEF("fileName", js_function_proto_fileName, NULL ),-    JS_CGETSET_DEF("lineNumber", js_function_proto_lineNumber, NULL ),-};--/* Error class */--static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)-{-    JSValue iter, next_method = JS_UNDEFINED;-    JSValue v, r = JS_UNDEFINED;-    int64_t k;-    BOOL done;-    -    iter = JS_GetIterator(ctx, items, FALSE);-    if (JS_IsException(iter))-        goto exception;-    next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);-    if (JS_IsException(next_method))-        goto exception;-    r = JS_NewArray(ctx);-    if (JS_IsException(r))-        goto exception;-    for (k = 0;; k++) {-        v = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);-        if (JS_IsException(v))-            goto exception_close;-        if (done)-            break;-        if (JS_DefinePropertyValueInt64(ctx, r, k, v,-                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)-            goto exception_close;-    }- done:-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    return r;- exception_close:-    JS_IteratorClose(ctx, iter, TRUE);- exception:-    JS_FreeValue(ctx, r);-    r = JS_EXCEPTION;-    goto done;-}--static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,-                                    int argc, JSValueConst *argv, int magic)-{-    JSValue obj, msg, proto;-    JSValueConst message;--    if (JS_IsUndefined(new_target))-        new_target = JS_GetActiveFunction(ctx);-    proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);-    if (JS_IsException(proto))-        return proto;-    if (!JS_IsObject(proto)) {-        JSContext *realm;-        JSValueConst proto1;-        -        JS_FreeValue(ctx, proto);-        realm = JS_GetFunctionRealm(ctx, new_target);-        if (!realm)-            return JS_EXCEPTION;-        if (magic < 0) {-            proto1 = realm->class_proto[JS_CLASS_ERROR];-        } else {-            proto1 = realm->native_error_proto[magic];-        }-        proto = JS_DupValue(ctx, proto1);-    }-    obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR);-    JS_FreeValue(ctx, proto);-    if (JS_IsException(obj))-        return obj;-    if (magic == JS_AGGREGATE_ERROR) {-        message = argv[1];-    } else {-        message = argv[0];-    }--    if (!JS_IsUndefined(message)) {-        msg = JS_ToString(ctx, message);-        if (unlikely(JS_IsException(msg)))-            goto exception;-        JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg,-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    }--    if (magic == JS_AGGREGATE_ERROR) {-        JSValue error_list = iterator_to_array(ctx, argv[0]);-        if (JS_IsException(error_list))-            goto exception;-        JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, error_list,-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    }--    /* skip the Error() function in the backtrace */-    build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);-    return obj;- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue name, msg;--    if (!JS_IsObject(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    name = JS_GetProperty(ctx, this_val, JS_ATOM_name);-    if (JS_IsUndefined(name))-        name = JS_AtomToString(ctx, JS_ATOM_Error);-    else-        name = JS_ToStringFree(ctx, name);-    if (JS_IsException(name))-        return JS_EXCEPTION;--    msg = JS_GetProperty(ctx, this_val, JS_ATOM_message);-    if (JS_IsUndefined(msg))-        msg = JS_AtomToString(ctx, JS_ATOM_empty_string);-    else-        msg = JS_ToStringFree(ctx, msg);-    if (JS_IsException(msg)) {-        JS_FreeValue(ctx, name);-        return JS_EXCEPTION;-    }-    if (!JS_IsEmptyString(name) && !JS_IsEmptyString(msg))-        name = JS_ConcatString3(ctx, "", name, ": ");-    return JS_ConcatString(ctx, name, msg);-}--static const JSCFunctionListEntry js_error_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_error_toString ),-    JS_PROP_STRING_DEF("name", "Error", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),-    JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),-};--/* AggregateError */--/* used by C code. */-static JSValue js_aggregate_error_constructor(JSContext *ctx,-                                              JSValueConst errors)-{-    JSValue obj;-    -    obj = JS_NewObjectProtoClass(ctx,-                                 ctx->native_error_proto[JS_AGGREGATE_ERROR],-                                 JS_CLASS_ERROR);-    if (JS_IsException(obj))-        return obj;-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors),-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    return obj;-}--/* Array */--static int JS_CopySubArray(JSContext *ctx,-                           JSValueConst obj, int64_t to_pos,-                           int64_t from_pos, int64_t count, int dir)-{-    int64_t i, from, to;-    JSValue val;-    int fromPresent;--    /* XXX: should special case fast arrays */-    for (i = 0; i < count; i++) {-        if (dir < 0) {-            from = from_pos + count - i - 1;-            to = to_pos + count - i - 1;-        } else {-            from = from_pos + i;-            to = to_pos + i;-        }-        fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val);-        if (fromPresent < 0)-            goto exception;--        if (fromPresent) {-            if (JS_SetPropertyInt64(ctx, obj, to, val) < 0)-                goto exception;-        } else {-            if (JS_DeletePropertyInt64(ctx, obj, to, JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    return 0;-- exception:-    return -1;-}--static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target,-                                    int argc, JSValueConst *argv)-{-    JSValue obj;-    int i;--    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_ARRAY);-    if (JS_IsException(obj))-        return obj;-    if (argc == 1 && JS_IsNumber(argv[0])) {-        uint32_t len;-        if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0])))-            goto fail;-        if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0)-            goto fail;-    } else {-        for(i = 0; i < argc; i++) {-            if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0)-                goto fail;-        }-    }-    return obj;-fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    // from(items, mapfn = void 0, this_arg = void 0)-    JSValueConst items = argv[0], mapfn, this_arg;-    JSValueConst args[2];-    JSValue stack[2];-    JSValue iter, r, v, v2, arrayLike;-    int64_t k, len;-    int done, mapping;--    mapping = FALSE;-    mapfn = JS_UNDEFINED;-    this_arg = JS_UNDEFINED;-    r = JS_UNDEFINED;-    arrayLike = JS_UNDEFINED;-    stack[0] = JS_UNDEFINED;-    stack[1] = JS_UNDEFINED;--    if (argc > 1) {-        mapfn = argv[1];-        if (!JS_IsUndefined(mapfn)) {-            if (check_function(ctx, mapfn))-                goto exception;-            mapping = 1;-            if (argc > 2)-                this_arg = argv[2];-        }-    }-    iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator);-    if (JS_IsException(iter))-        goto exception;-    if (!JS_IsUndefined(iter)) {-        JS_FreeValue(ctx, iter);-        if (JS_IsConstructor(ctx, this_val))-            r = JS_CallConstructor(ctx, this_val, 0, NULL);-        else-            r = JS_NewArray(ctx);-        if (JS_IsException(r))-            goto exception;-        stack[0] = JS_DupValue(ctx, items);-        if (js_for_of_start(ctx, &stack[1], FALSE))-            goto exception;-        for (k = 0;; k++) {-            v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);-            if (JS_IsException(v))-                goto exception_close;-            if (done)-                break;-            if (mapping) {-                args[0] = v;-                args[1] = JS_NewInt32(ctx, k);-                v2 = JS_Call(ctx, mapfn, this_arg, 2, args);-                JS_FreeValue(ctx, v);-                v = v2;-                if (JS_IsException(v))-                    goto exception_close;-            }-            if (JS_DefinePropertyValueInt64(ctx, r, k, v,-                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                goto exception_close;-        }-    } else {-        arrayLike = JS_ToObject(ctx, items);-        if (JS_IsException(arrayLike))-            goto exception;-        if (js_get_length64(ctx, &len, arrayLike) < 0)-            goto exception;-        v = JS_NewInt64(ctx, len);-        args[0] = v;-        if (JS_IsConstructor(ctx, this_val)) {-            r = JS_CallConstructor(ctx, this_val, 1, args);-        } else {-            r = js_array_constructor(ctx, JS_UNDEFINED, 1, args);-        }-        JS_FreeValue(ctx, v);-        if (JS_IsException(r))-            goto exception;-        for(k = 0; k < len; k++) {-            v = JS_GetPropertyInt64(ctx, arrayLike, k);-            if (JS_IsException(v))-                goto exception;-            if (mapping) {-                args[0] = v;-                args[1] = JS_NewInt32(ctx, k);-                v2 = JS_Call(ctx, mapfn, this_arg, 2, args);-                JS_FreeValue(ctx, v);-                v = v2;-                if (JS_IsException(v))-                    goto exception;-            }-            if (JS_DefinePropertyValueInt64(ctx, r, k, v,-                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0)-        goto exception;-    goto done;-- exception_close:-    if (!JS_IsUndefined(stack[0]))-        JS_IteratorClose(ctx, stack[0], TRUE);- exception:-    JS_FreeValue(ctx, r);-    r = JS_EXCEPTION;- done:-    JS_FreeValue(ctx, arrayLike);-    JS_FreeValue(ctx, stack[0]);-    JS_FreeValue(ctx, stack[1]);-    return r;-}--static JSValue js_array_of(JSContext *ctx, JSValueConst this_val,-                           int argc, JSValueConst *argv)-{-    JSValue obj, args[1];-    int i;--    if (JS_IsConstructor(ctx, this_val)) {-        args[0] = JS_NewInt32(ctx, argc);-        obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args);-    } else {-        obj = JS_NewArray(ctx);-    }-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    for(i = 0; i < argc; i++) {-        if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i]),-                                        JS_PROP_THROW) < 0) {-            goto fail;-        }-    }-    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) {-    fail:-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    return obj;-}--static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    int ret;-    ret = JS_IsArray(ctx, argv[0]);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_get_this(JSContext *ctx,-                           JSValueConst this_val)-{-    return JS_DupValue(ctx, this_val);-}--static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,-                                     JSValueConst len_val)-{-    JSValue ctor, ret, species;-    int res;-    JSContext *realm;-    -    res = JS_IsArray(ctx, obj);-    if (res < 0)-        return JS_EXCEPTION;-    if (!res)-        return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);-    ctor = JS_GetProperty(ctx, obj, JS_ATOM_constructor);-    if (JS_IsException(ctor))-        return ctor;-    if (JS_IsConstructor(ctx, ctor)) {-        /* legacy web compatibility */-        realm = JS_GetFunctionRealm(ctx, ctor);-        if (!realm) {-            JS_FreeValue(ctx, ctor);-            return JS_EXCEPTION;-        }-        if (realm != ctx &&-            js_same_value(ctx, ctor, realm->array_ctor)) {-            JS_FreeValue(ctx, ctor);-            ctor = JS_UNDEFINED;-        }-    }-    if (JS_IsObject(ctor)) {-        species = JS_GetProperty(ctx, ctor, JS_ATOM_Symbol_species);-        JS_FreeValue(ctx, ctor);-        if (JS_IsException(species))-            return species;-        ctor = species;-        if (JS_IsNull(ctor))-            ctor = JS_UNDEFINED;-    }-    if (JS_IsUndefined(ctor)) {-        return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);-    } else {-        ret = JS_CallConstructor(ctx, ctor, 1, &len_val);-        JS_FreeValue(ctx, ctor);-        return ret;-    }-}--static const JSCFunctionListEntry js_array_funcs[] = {-    JS_CFUNC_DEF("isArray", 1, js_array_isArray ),-    JS_CFUNC_DEF("from", 1, js_array_from ),-    JS_CFUNC_DEF("of", 0, js_array_of ),-    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),-};--static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)-{-    JSValue val;--    if (!JS_IsObject(obj))-        return FALSE;-    val = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_isConcatSpreadable);-    if (JS_IsException(val))-        return -1;-    if (!JS_IsUndefined(val))-        return JS_ToBoolFree(ctx, val);-    return JS_IsArray(ctx, obj);-}--static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    JSValue obj, arr, val;-    JSValueConst e;-    int64_t len, k, n;-    int i, res;--    arr = JS_UNDEFINED;-    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        goto exception;--    arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));-    if (JS_IsException(arr))-        goto exception;-    n = 0;-    for (i = -1; i < argc; i++) {-        if (i < 0)-            e = obj;-        else-            e = argv[i];--        res = JS_isConcatSpreadable(ctx, e);-        if (res < 0)-            goto exception;-        if (res) {-            if (js_get_length64(ctx, &len, e))-                goto exception;-            if (n + len > MAX_SAFE_INTEGER) {-                JS_ThrowTypeError(ctx, "Array loo long");-                goto exception;-            }-            for (k = 0; k < len; k++, n++) {-                res = JS_TryGetPropertyInt64(ctx, e, k, &val);-                if (res < 0)-                    goto exception;-                if (res) {-                    if (JS_DefinePropertyValueInt64(ctx, arr, n, val,-                                                    JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                        goto exception;-                }-            }-        } else {-            if (n >= MAX_SAFE_INTEGER) {-                JS_ThrowTypeError(ctx, "Array loo long");-                goto exception;-            }-            if (JS_DefinePropertyValueInt64(ctx, arr, n, JS_DupValue(ctx, e),-                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                goto exception;-            n++;-        }-    }-    if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)-        goto exception;--    JS_FreeValue(ctx, obj);-    return arr;--exception:-    JS_FreeValue(ctx, arr);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--#define special_every    0-#define special_some     1-#define special_forEach  2-#define special_map      3-#define special_filter   4-#define special_TA       8--static int js_typed_array_get_length_internal(JSContext *ctx, JSValueConst obj);--static JSValue js_typed_array___speciesCreate(JSContext *ctx,-                                              JSValueConst this_val,-                                              int argc, JSValueConst *argv);--static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int special)-{-    JSValue obj, val, index_val, res, ret;-    JSValueConst args[3];-    JSValueConst func, this_arg;-    int64_t len, k, n;-    int present;--    ret = JS_UNDEFINED;-    val = JS_UNDEFINED;-    if (special & special_TA) {-        obj = JS_DupValue(ctx, this_val);-        len = js_typed_array_get_length_internal(ctx, obj);-        if (len < 0)-            goto exception;-    } else {-        obj = JS_ToObject(ctx, this_val);-        if (js_get_length64(ctx, &len, obj))-            goto exception;-    }-    func = argv[0];-    this_arg = JS_UNDEFINED;-    if (argc > 1)-        this_arg = argv[1];-        -    if (check_function(ctx, func))-        goto exception;--    switch (special) {-    case special_every:-    case special_every | special_TA:-        ret = JS_TRUE;-        break;-    case special_some:-    case special_some | special_TA:-        ret = JS_FALSE;-        break;-    case special_map:-        /* XXX: JS_ArraySpeciesCreate should take int64_t */-        ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt64(ctx, len));-        if (JS_IsException(ret))-            goto exception;-        break;-    case special_filter:-        ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));-        if (JS_IsException(ret))-            goto exception;-        break;-    case special_map | special_TA:-        args[0] = obj;-        args[1] = JS_NewInt32(ctx, len);-        ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);-        if (JS_IsException(ret))-            goto exception;-        break;-    case special_filter | special_TA:-        ret = JS_NewArray(ctx);-        if (JS_IsException(ret))-            goto exception;-        break;-    }-    n = 0;--    for(k = 0; k < len; k++) {-        present = JS_TryGetPropertyInt64(ctx, obj, k, &val);-        if (present < 0)-            goto exception;-        if (present) {-            index_val = JS_NewInt64(ctx, k);-            if (JS_IsException(index_val))-                goto exception;-            args[0] = val;-            args[1] = index_val;-            args[2] = obj;-            res = JS_Call(ctx, func, this_arg, 3, args);-            JS_FreeValue(ctx, index_val);-            if (JS_IsException(res))-                goto exception;-            switch (special) {-            case special_every:-            case special_every | special_TA:-                if (!JS_ToBoolFree(ctx, res)) {-                    ret = JS_FALSE;-                    goto done;-                }-                break;-            case special_some:-            case special_some | special_TA:-                if (JS_ToBoolFree(ctx, res)) {-                    ret = JS_TRUE;-                    goto done;-                }-                break;-            case special_map:-                if (JS_DefinePropertyValueInt64(ctx, ret, k, res,-                                                JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                    goto exception;-                break;-            case special_map | special_TA:-                if (JS_SetPropertyValue(ctx, ret, JS_NewInt32(ctx, k), res, JS_PROP_THROW) < 0)-                    goto exception;-                break;-            case special_filter:-            case special_filter | special_TA:-                if (JS_ToBoolFree(ctx, res)) {-                    if (JS_DefinePropertyValueInt64(ctx, ret, n++, JS_DupValue(ctx, val),-                                                    JS_PROP_C_W_E | JS_PROP_THROW) < 0)-                        goto exception;-                }-                break;-            default:-                JS_FreeValue(ctx, res);-                break;-            }-            JS_FreeValue(ctx, val);-            val = JS_UNDEFINED;-        }-    }-done:-    if (special == (special_filter | special_TA)) {-        JSValue arr;-        args[0] = obj;-        args[1] = JS_NewInt32(ctx, n);-        arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);-        if (JS_IsException(arr))-            goto exception;-        args[0] = ret;-        res = JS_Invoke(ctx, arr, JS_ATOM_set, 1, args);-        if (check_exception_free(ctx, res))-            goto exception;-        JS_FreeValue(ctx, ret);-        ret = arr;-    }-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return ret;--exception:-    JS_FreeValue(ctx, ret);-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--#define special_reduce       0-#define special_reduceRight  1--static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv, int special)-{-    JSValue obj, val, index_val, acc, acc1;-    JSValueConst args[4];-    JSValueConst func;-    int64_t len, k, k1;-    int present;--    acc = JS_UNDEFINED;-    val = JS_UNDEFINED;-    if (special & special_TA) {-        obj = JS_DupValue(ctx, this_val);-        len = js_typed_array_get_length_internal(ctx, obj);-        if (len < 0)-            goto exception;-    } else {-        obj = JS_ToObject(ctx, this_val);-        if (js_get_length64(ctx, &len, obj))-            goto exception;-    }-    func = argv[0];--    if (check_function(ctx, func))-        goto exception;--    k = 0;-    if (argc > 1) {-        acc = JS_DupValue(ctx, argv[1]);-    } else {-        for(;;) {-            if (k >= len) {-                JS_ThrowTypeError(ctx, "empty array");-                goto exception;-            }-            k1 = (special & special_reduceRight) ? len - k - 1 : k;-            k++;-            present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc);-            if (present < 0)-                goto exception;-            if (present)-                break;-        }-    }-    for (; k < len; k++) {-        k1 = (special & special_reduceRight) ? len - k - 1 : k;-        present = JS_TryGetPropertyInt64(ctx, obj, k1, &val);-        if (present < 0)-            goto exception;-        if (present) {-            index_val = JS_NewInt64(ctx, k1);-            if (JS_IsException(index_val))-                goto exception;-            args[0] = acc;-            args[1] = val;-            args[2] = index_val;-            args[3] = obj;-            acc1 = JS_Call(ctx, func, JS_UNDEFINED, 4, args);-            JS_FreeValue(ctx, index_val);-            JS_FreeValue(ctx, val);-            val = JS_UNDEFINED;-            if (JS_IsException(acc1))-                goto exception;-            JS_FreeValue(ctx, acc);-            acc = acc1;-        }-    }-    JS_FreeValue(ctx, obj);-    return acc;--exception:-    JS_FreeValue(ctx, acc);-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    JSValue obj;-    int64_t len, start, end;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    start = 0;-    if (argc > 1 && !JS_IsUndefined(argv[1])) {-        if (JS_ToInt64Clamp(ctx, &start, argv[1], 0, len, len))-            goto exception;-    }--    end = len;-    if (argc > 2 && !JS_IsUndefined(argv[2])) {-        if (JS_ToInt64Clamp(ctx, &end, argv[2], 0, len, len))-            goto exception;-    }--    /* XXX: should special case fast arrays */-    while (start < end) {-        if (JS_SetPropertyInt64(ctx, obj, start,-                                JS_DupValue(ctx, argv[0])) < 0)-            goto exception;-        start++;-    }-    return obj;-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue obj, val;-    int64_t len, n, res;-    JSValue *arrp;-    uint32_t count;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    res = FALSE;-    if (len > 0) {-        n = 0;-        if (argc > 1) {-            if (JS_ToInt64Clamp(ctx, &n, argv[1], 0, len, len))-                goto exception;-        }-        if (js_get_fast_array(ctx, obj, &arrp, &count)) {-            for (; n < count; n++) {-                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),-                                  JS_DupValue(ctx, arrp[n]),-                                  JS_EQ_SAME_VALUE_ZERO)) {-                    res = TRUE;-                    goto done;-                }-            }-        }-        for (; n < len; n++) {-            val = JS_GetPropertyInt64(ctx, obj, n);-            if (JS_IsException(val))-                goto exception;-            if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val,-                              JS_EQ_SAME_VALUE_ZERO)) {-                res = TRUE;-                break;-            }-        }-    }- done:-    JS_FreeValue(ctx, obj);-    return JS_NewBool(ctx, res);-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue obj, val;-    int64_t len, n, res;-    JSValue *arrp;-    uint32_t count;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    res = -1;-    if (len > 0) {-        n = 0;-        if (argc > 1) {-            if (JS_ToInt64Clamp(ctx, &n, argv[1], 0, len, len))-                goto exception;-        }-        if (js_get_fast_array(ctx, obj, &arrp, &count)) {-            for (; n < count; n++) {-                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),-                                  JS_DupValue(ctx, arrp[n]), JS_EQ_STRICT)) {-                    res = n;-                    goto done;-                }-            }-        }-        for (; n < len; n++) {-            int present = JS_TryGetPropertyInt64(ctx, obj, n, &val);-            if (present < 0)-                goto exception;-            if (present) {-                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {-                    res = n;-                    break;-                }-            }-        }-    }- done:-    JS_FreeValue(ctx, obj);-    return JS_NewInt64(ctx, res);-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValue obj, val;-    int64_t len, n, res;-    int present;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    res = -1;-    if (len > 0) {-        n = len - 1;-        if (argc > 1) {-            if (JS_ToInt64Clamp(ctx, &n, argv[1], -1, len - 1, len))-                goto exception;-        }-        /* XXX: should special case fast arrays */-        for (; n >= 0; n--) {-            present = JS_TryGetPropertyInt64(ctx, obj, n, &val);-            if (present < 0)-                goto exception;-            if (present) {-                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {-                    res = n;-                    break;-                }-            }-        }-    }-    JS_FreeValue(ctx, obj);-    return JS_NewInt64(ctx, res);-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv, int findIndex)-{-    JSValueConst func, this_arg;-    JSValueConst args[3];-    JSValue obj, val, index_val, res;-    int64_t len, k;--    index_val = JS_UNDEFINED;-    val = JS_UNDEFINED;-    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    func = argv[0];-    if (check_function(ctx, func))-        goto exception;--    this_arg = JS_UNDEFINED;-    if (argc > 1)-        this_arg = argv[1];--    for(k = 0; k < len; k++) {-        index_val = JS_NewInt64(ctx, k);-        if (JS_IsException(index_val))-            goto exception;-        val = JS_GetPropertyValue(ctx, obj, index_val);-        if (JS_IsException(val))-            goto exception;-        args[0] = val;-        args[1] = index_val;-        args[2] = this_val;-        res = JS_Call(ctx, func, this_arg, 3, args);-        if (JS_IsException(res))-            goto exception;-        if (JS_ToBoolFree(ctx, res)) {-            if (findIndex) {-                JS_FreeValue(ctx, val);-                JS_FreeValue(ctx, obj);-                return index_val;-            } else {-                JS_FreeValue(ctx, index_val);-                JS_FreeValue(ctx, obj);-                return val;-            }-        }-        JS_FreeValue(ctx, val);-        JS_FreeValue(ctx, index_val);-    }-    JS_FreeValue(ctx, obj);-    if (findIndex)-        return JS_NewInt32(ctx, -1);-    else-        return JS_UNDEFINED;--exception:-    JS_FreeValue(ctx, index_val);-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue obj, method, ret;--    obj = JS_ToObject(ctx, this_val);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    method = JS_GetProperty(ctx, obj, JS_ATOM_join);-    if (JS_IsException(method)) {-        ret = JS_EXCEPTION;-    } else-    if (!JS_IsFunction(ctx, method)) {-        /* Use intrinsic Object.prototype.toString */-        JS_FreeValue(ctx, method);-        ret = js_object_toString(ctx, obj, 0, NULL);-    } else {-        ret = JS_CallFree(ctx, method, obj, 0, NULL);-    }-    JS_FreeValue(ctx, obj);-    return ret;-}--static JSValue js_array_join(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv, int toLocaleString)-{-    JSValue obj, sep = JS_UNDEFINED, el;-    StringBuffer b_s, *b = &b_s;-    JSString *p = NULL;-    int64_t i, n;-    int c;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &n, obj))-        goto exception;--    c = ',';    /* default separator */-    if (!toLocaleString && argc > 0 && !JS_IsUndefined(argv[0])) {-        sep = JS_ToString(ctx, argv[0]);-        if (JS_IsException(sep))-            goto exception;-        p = JS_VALUE_GET_STRING(sep);-        if (p->len == 1 && !p->is_wide_char)-            c = p->u.str8[0];-        else-            c = -1;-    }-    string_buffer_init(ctx, b, 0);--    for(i = 0; i < n; i++) {-        if (i > 0) {-            if (c >= 0) {-                string_buffer_putc8(b, c);-            } else {-                string_buffer_concat(b, p, 0, p->len);-            }-        }-        el = JS_GetPropertyUint32(ctx, obj, i);-        if (JS_IsException(el))-            goto fail;-        if (!JS_IsNull(el) && !JS_IsUndefined(el)) {-            if (toLocaleString) {-                el = JS_ToLocaleStringFree(ctx, el);-            }-            if (string_buffer_concat_value_free(b, el))-                goto fail;-        }-    }-    JS_FreeValue(ctx, sep);-    JS_FreeValue(ctx, obj);-    return string_buffer_end(b);--fail:-    string_buffer_free(b);-    JS_FreeValue(ctx, sep);-exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val,-                            int argc, JSValueConst *argv, int shift)-{-    JSValue obj, res = JS_UNDEFINED;-    int64_t len, newLen;-    JSValue *arrp;-    uint32_t count32;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;-    newLen = 0;-    if (len > 0) {-        newLen = len - 1;-        /* Special case fast arrays */-        if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {-            JSObject *p = JS_VALUE_GET_OBJ(obj);-            if (shift) {-                res = arrp[0];-                memmove(arrp, arrp + 1, (count32 - 1) * sizeof(*arrp));-                p->u.array.count--;-            } else {-                res = arrp[count32 - 1];-                p->u.array.count--;-            }-        } else {-            if (shift) {-                res = JS_GetPropertyInt64(ctx, obj, 0);-                if (JS_IsException(res))-                    goto exception;-                if (JS_CopySubArray(ctx, obj, 0, 1, len - 1, +1))-                    goto exception;-            } else {-                res = JS_GetPropertyInt64(ctx, obj, newLen);-                if (JS_IsException(res))-                    goto exception;-            }-            if (JS_DeletePropertyInt64(ctx, obj, newLen, JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)-        goto exception;--    JS_FreeValue(ctx, obj);-    return res;-- exception:-    JS_FreeValue(ctx, res);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv, int unshift)-{-    JSValue obj;-    int i;-    int64_t len, from, newLen;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;-    newLen = len + argc;-    if (newLen > MAX_SAFE_INTEGER) {-        JS_ThrowTypeError(ctx, "Array loo long");-        goto exception;-    }-    from = len;-    if (unshift && argc > 0) {-        if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))-            goto exception;-        from = 0;-    }-    for(i = 0; i < argc; i++) {-        if (JS_SetPropertyInt64(ctx, obj, from + i,-                                JS_DupValue(ctx, argv[i])) < 0)-            goto exception;-    }-    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)-        goto exception;--    JS_FreeValue(ctx, obj);-    return JS_NewInt64(ctx, newLen);-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue obj, lval, hval;-    JSValue *arrp;-    int64_t len, l, h;-    int l_present, h_present;-    uint32_t count32;--    lval = JS_UNDEFINED;-    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    /* Special case fast arrays */-    if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {-        uint32_t ll, hh;--        if (count32 > 1) {-            for (ll = 0, hh = count32 - 1; ll < hh; ll++, hh--) {-                lval = arrp[ll];-                arrp[ll] = arrp[hh];-                arrp[hh] = lval;-            }-        }-        return obj;-    }--    for (l = 0, h = len - 1; l < h; l++, h--) {-        l_present = JS_TryGetPropertyInt64(ctx, obj, l, &lval);-        if (l_present < 0)-            goto exception;-        h_present = JS_TryGetPropertyInt64(ctx, obj, h, &hval);-        if (h_present < 0)-            goto exception;-        if (h_present) {-            if (JS_SetPropertyInt64(ctx, obj, l, hval) < 0)-                goto exception;--            if (l_present) {-                if (JS_SetPropertyInt64(ctx, obj, h, lval) < 0) {-                    lval = JS_UNDEFINED;-                    goto exception;-                }-                lval = JS_UNDEFINED;-            } else {-                if (JS_DeletePropertyInt64(ctx, obj, h, JS_PROP_THROW) < 0)-                    goto exception;-            }-        } else {-            if (l_present) {-                if (JS_DeletePropertyInt64(ctx, obj, l, JS_PROP_THROW) < 0)-                    goto exception;-                if (JS_SetPropertyInt64(ctx, obj, h, lval) < 0) {-                    lval = JS_UNDEFINED;-                    goto exception;-                }-                lval = JS_UNDEFINED;-            }-        }-    }-    return obj;-- exception:-    JS_FreeValue(ctx, lval);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int splice)-{-    JSValue obj, arr, val, len_val;-    int64_t len, start, k, final, n, count, del_count, new_len;-    int kPresent;-    JSValue *arrp;-    uint32_t count32, i, item_count;--    arr = JS_UNDEFINED;-    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len))-        goto exception;--    if (splice) {-        if (argc == 0) {-            item_count = 0;-            del_count = 0;-        } else-        if (argc == 1) {-            item_count = 0;-            del_count = len - start;-        } else {-            item_count = argc - 2;-            if (JS_ToInt64Clamp(ctx, &del_count, argv[1], 0, len - start, 0))-                goto exception;-        }-        if (len + item_count - del_count > MAX_SAFE_INTEGER) {-            JS_ThrowTypeError(ctx, "Array loo long");-            goto exception;-        }-        count = del_count;-    } else {-        item_count = 0; /* avoid warning */-        final = len;-        if (!JS_IsUndefined(argv[1])) {-            if (JS_ToInt64Clamp(ctx, &final, argv[1], 0, len, len))-                goto exception;-        }-        count = max_int64(final - start, 0);-    }-    len_val = JS_NewInt64(ctx, count);-    arr = JS_ArraySpeciesCreate(ctx, obj, len_val);-    JS_FreeValue(ctx, len_val);-    if (JS_IsException(arr))-        goto exception;--    k = start;-    final = start + count;-    n = 0;-    /* The fast array test on arr ensures that-       JS_CreateDataPropertyUint32() won't modify obj in case arr is-       an exotic object */-    /* Special case fast arrays */-    if (js_get_fast_array(ctx, obj, &arrp, &count32) &&-        js_is_fast_array(ctx, arr)) {-        /* XXX: should share code with fast array constructor */-        for (; k < final && k < count32; k++, n++) {-            if (JS_CreateDataPropertyUint32(ctx, arr, n, JS_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    /* Copy the remaining elements if any (handle case of inherited properties) */-    for (; k < final; k++, n++) {-        kPresent = JS_TryGetPropertyInt64(ctx, obj, k, &val);-        if (kPresent < 0)-            goto exception;-        if (kPresent) {-            if (JS_CreateDataPropertyUint32(ctx, arr, n, val, JS_PROP_THROW) < 0)-                goto exception;-        }-    }-    if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)-        goto exception;--    if (splice) {-        new_len = len + item_count - del_count;-        if (item_count != del_count) {-            if (JS_CopySubArray(ctx, obj, start + item_count,-                                start + del_count, len - (start + del_count),-                                item_count <= del_count ? +1 : -1) < 0)-                goto exception;--            for (k = len; k-- > new_len; ) {-                if (JS_DeletePropertyInt64(ctx, obj, k, JS_PROP_THROW) < 0)-                    goto exception;-            }-        }-        for (i = 0; i < item_count; i++) {-            if (JS_SetPropertyInt64(ctx, obj, start + i, JS_DupValue(ctx, argv[i + 2])) < 0)-                goto exception;-        }-        if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, new_len)) < 0)-            goto exception;-    }-    JS_FreeValue(ctx, obj);-    return arr;-- exception:-    JS_FreeValue(ctx, obj);-    JS_FreeValue(ctx, arr);-    return JS_EXCEPTION;-}--static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    JSValue obj;-    int64_t len, from, to, final, count;--    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    if (JS_ToInt64Clamp(ctx, &to, argv[0], 0, len, len))-        goto exception;--    if (JS_ToInt64Clamp(ctx, &from, argv[1], 0, len, len))-        goto exception;--    final = len;-    if (argc > 2 && !JS_IsUndefined(argv[2])) {-        if (JS_ToInt64Clamp(ctx, &final, argv[2], 0, len, len))-            goto exception;-    }--    count = min_int64(final - from, len - to);--    if (JS_CopySubArray(ctx, obj, to, from, count,-                        (from < to && to < from + count) ? -1 : +1))-        goto exception;--    return obj;-- exception:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,-                                   JSValueConst source, int64_t sourceLen,-                                   int64_t targetIndex, int depth,-                                   JSValueConst mapperFunction,-                                   JSValueConst thisArg)-{-    JSValue element;-    int64_t sourceIndex, elementLen;-    int present, is_array;--    for (sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {-        present = JS_TryGetPropertyInt64(ctx, source, sourceIndex, &element);-        if (present < 0)-            return -1;-        if (!present)-            continue;-        if (!JS_IsUndefined(mapperFunction)) {-            JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source };-            element = JS_Call(ctx, mapperFunction, thisArg, 3, args);-            JS_FreeValue(ctx, (JSValue)args[0]);-            JS_FreeValue(ctx, (JSValue)args[1]);-            if (JS_IsException(element))-                return -1;-        }-        if (depth > 0) {-            is_array = JS_IsArray(ctx, element);-            if (is_array < 0)-                goto fail;-            if (is_array) {-                if (js_get_length64(ctx, &elementLen, element) < 0)-                    goto fail;-                targetIndex = JS_FlattenIntoArray(ctx, target, element,-                                                  elementLen, targetIndex,-                                                  depth - 1,-                                                  JS_UNDEFINED, JS_UNDEFINED);-                if (targetIndex < 0)-                    goto fail;-                JS_FreeValue(ctx, element);-                continue;-            }-        }-        if (targetIndex >= MAX_SAFE_INTEGER) {-            JS_ThrowTypeError(ctx, "Array too long");-            goto fail;-        }-        if (JS_DefinePropertyValueInt64(ctx, target, targetIndex, element,-                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)-            return -1;-        targetIndex++;-    }-    return targetIndex;--fail:-    JS_FreeValue(ctx, element);-    return -1;-}--static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv, int map)-{-    JSValue obj, arr;-    JSValueConst mapperFunction, thisArg;-    int64_t sourceLen;-    int depthNum;--    arr = JS_UNDEFINED;-    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &sourceLen, obj))-        goto exception;--    depthNum = 1;-    mapperFunction = JS_UNDEFINED;-    thisArg = JS_UNDEFINED;-    if (map) {-        mapperFunction = argv[0];-        if (argc > 1) {-            thisArg = argv[1];-        }-        if (check_function(ctx, mapperFunction))-            goto exception;-    } else {-        if (argc > 0 && !JS_IsUndefined(argv[0])) {-            if (JS_ToInt32Sat(ctx, &depthNum, argv[0]) < 0)-                goto exception;-        }-    }-    arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));-    if (JS_IsException(arr))-        goto exception;-    if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum,-                            mapperFunction, thisArg) < 0)-        goto exception;-    JS_FreeValue(ctx, obj);-    return arr;--exception:-    JS_FreeValue(ctx, obj);-    JS_FreeValue(ctx, arr);-    return JS_EXCEPTION;-}--/* Array sort */--typedef struct ValueSlot {-    JSValue val;-    JSString *str;-    int64_t pos;-} ValueSlot;--struct array_sort_context {-    JSContext *ctx;-    int exception;-    int has_method;-    JSValueConst method;-};--static int js_array_cmp_generic(const void *a, const void *b, void *opaque) {-    struct array_sort_context *psc = opaque;-    JSContext *ctx = psc->ctx;-    JSValueConst argv[2];-    JSValue res;-    ValueSlot *ap = (ValueSlot *)(void *)a;-    ValueSlot *bp = (ValueSlot *)(void *)b;-    int cmp;--    if (psc->exception)-        return 0;--    if (psc->has_method) {-        /* custom sort function is specified as returning 0 for identical-         * objects: avoid method call overhead.-         */-        if (!memcmp(&ap->val, &bp->val, sizeof(ap->val)))-            goto cmp_same;-        argv[0] = ap->val;-        argv[1] = bp->val;-        res = JS_Call(ctx, psc->method, JS_UNDEFINED, 2, argv);-        if (JS_IsException(res))-            goto exception;-        if (JS_VALUE_GET_TAG(res) == JS_TAG_INT) {-            int val = JS_VALUE_GET_INT(res);-            cmp = (val > 0) - (val < 0);-        } else {-            double val;-            if (JS_ToFloat64Free(ctx, &val, res) < 0)-                goto exception;-            cmp = (val > 0) - (val < 0);-        }-    } else {-        /* Not supposed to bypass ToString even for identical objects as-         * tested in test262/test/built-ins/Array/prototype/sort/bug_596_1.js-         */-        if (!ap->str) {-            JSValue str = JS_ToString(ctx, ap->val);-            if (JS_IsException(str))-                goto exception;-            ap->str = JS_VALUE_GET_STRING(str);-        }-        if (!bp->str) {-            JSValue str = JS_ToString(ctx, bp->val);-            if (JS_IsException(str))-                goto exception;-            bp->str = JS_VALUE_GET_STRING(str);-        }-        cmp = js_string_compare(ctx, ap->str, bp->str);-    }-    if (cmp != 0)-        return cmp;-cmp_same:-    /* make sort stable: compare array offsets */-    return (ap->pos > bp->pos) - (ap->pos < bp->pos);--exception:-    psc->exception = 1;-    return 0;-}--static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    struct array_sort_context asc = { ctx, 0, 0, argv[0] };-    JSValue obj = JS_UNDEFINED;-    ValueSlot *array = NULL;-    size_t array_size = 0, pos = 0, n = 0;-    int64_t i, len, undefined_count = 0;-    int present;--    if (!JS_IsUndefined(asc.method)) {-        if (check_function(ctx, asc.method))-            goto exception;-        asc.has_method = 1;-    }-    obj = JS_ToObject(ctx, this_val);-    if (js_get_length64(ctx, &len, obj))-        goto exception;--    /* XXX: should special case fast arrays */-    for (i = 0; i < len; i++) {-        if (pos >= array_size) {-            size_t new_size, slack;-            ValueSlot *new_array;-            new_size = (array_size + (array_size >> 1) + 31) & ~15;-            new_array = js_realloc2(ctx, array, new_size * sizeof(*array), &slack);-            if (new_array == NULL)-                goto exception;-            new_size += slack / sizeof(*new_array);-            array = new_array;-            array_size = new_size;-        }-        present = JS_TryGetPropertyInt64(ctx, obj, i, &array[pos].val);-        if (present < 0)-            goto exception;-        if (present == 0)-            continue;-        if (JS_IsUndefined(array[pos].val)) {-            undefined_count++;-            continue;-        }-        array[pos].str = NULL;-        array[pos].pos = i;-        pos++;-    }-    rqsort(array, pos, sizeof(*array), js_array_cmp_generic, &asc);-    if (asc.exception)-        goto exception;--    /* XXX: should special case fast arrays */-    while (n < pos) {-        if (array[n].str)-            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, array[n].str));-        if (array[n].pos == n) {-            JS_FreeValue(ctx, array[n].val);-        } else {-            if (JS_SetPropertyInt64(ctx, obj, n, array[n].val) < 0) {-                n++;-                goto exception;-            }-        }-        n++;-    }-    js_free(ctx, array);-    for (i = n; undefined_count-- > 0; i++) {-        if (JS_SetPropertyInt64(ctx, obj, i, JS_UNDEFINED) < 0)-            goto fail;-    }-    for (; i < len; i++) {-        if (JS_DeletePropertyInt64(ctx, obj, i, JS_PROP_THROW) < 0)-            goto fail;-    }-    return obj;--exception:-    for (; n < pos; n++) {-        JS_FreeValue(ctx, array[n].val);-        if (array[n].str)-            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, array[n].str));-    }-    js_free(ctx, array);-fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--typedef struct JSArrayIteratorData {-    JSValue obj;-    JSIteratorKindEnum kind;-    uint32_t idx;-} JSArrayIteratorData;--static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSArrayIteratorData *it = p->u.array_iterator_data;-    if (it) {-        JS_FreeValueRT(rt, it->obj);-        js_free_rt(rt, it);-    }-}--static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,-                                   JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSArrayIteratorData *it = p->u.array_iterator_data;-    if (it) {-        JS_MarkValue(rt, it->obj, mark_func);-    }-}--static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)-{-    JSValue obj;-    int i;--    obj = JS_NewArray(ctx);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    for(i = 0; i < len; i++) {-        if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, tab[i]), 0) < 0) {-            JS_FreeValue(ctx, obj);-            return JS_EXCEPTION;-        }-    }-    return obj;-}--static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv, int magic)-{-    JSValue enum_obj, arr;-    JSArrayIteratorData *it;-    JSIteratorKindEnum kind;-    int class_id;--    kind = magic & 3;-    if (magic & 4) {-        /* string iterator case */-        arr = JS_ToStringCheckObject(ctx, this_val);-        class_id = JS_CLASS_STRING_ITERATOR;-    } else {-        arr = JS_ToObject(ctx, this_val);-        class_id = JS_CLASS_ARRAY_ITERATOR;-    }-    if (JS_IsException(arr))-        goto fail;-    enum_obj = JS_NewObjectClass(ctx, class_id);-    if (JS_IsException(enum_obj))-        goto fail;-    it = js_malloc(ctx, sizeof(*it));-    if (!it)-        goto fail1;-    it->obj = arr;-    it->kind = kind;-    it->idx = 0;-    JS_SetOpaque(enum_obj, it);-    return enum_obj;- fail1:-    JS_FreeValue(ctx, enum_obj);- fail:-    JS_FreeValue(ctx, arr);-    return JS_EXCEPTION;-}--static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv,-                                      BOOL *pdone, int magic)-{-    JSArrayIteratorData *it;-    uint32_t len, idx;-    JSValue val, obj;-    JSObject *p;--    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_ITERATOR);-    if (!it)-        goto fail1;-    if (JS_IsUndefined(it->obj))-        goto done;-    p = JS_VALUE_GET_OBJ(it->obj);-    if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-        p->class_id <= JS_CLASS_FLOAT64_ARRAY) {-        if (typed_array_is_detached(ctx, p)) {-            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);-            goto fail1;-        }-        len = p->u.array.count;-    } else {-        if (js_get_length32(ctx, &len, it->obj)) {-        fail1:-            *pdone = FALSE;-            return JS_EXCEPTION;-        }-    }-    idx = it->idx;-    if (idx >= len) {-        JS_FreeValue(ctx, it->obj);-        it->obj = JS_UNDEFINED;-    done:-        *pdone = TRUE;-        return JS_UNDEFINED;-    }-    it->idx = idx + 1;-    *pdone = FALSE;-    if (it->kind == JS_ITERATOR_KIND_KEY) {-        return JS_NewUint32(ctx, idx);-    } else {-        val = JS_GetPropertyUint32(ctx, it->obj, idx);-        if (JS_IsException(val))-            return JS_EXCEPTION;-        if (it->kind == JS_ITERATOR_KIND_VALUE) {-            return val;-        } else {-            JSValueConst args[2];-            JSValue num;-            num = JS_NewUint32(ctx, idx);-            args[0] = num;-            args[1] = val;-            obj = js_create_array(ctx, 2, args);-            JS_FreeValue(ctx, val);-            JS_FreeValue(ctx, num);-            return obj;-        }-    }-}--static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv)-{-    return JS_DupValue(ctx, this_val);-}--static const JSCFunctionListEntry js_iterator_proto_funcs[] = {-    JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ),-};--static const JSCFunctionListEntry js_array_proto_funcs[] = {-    JS_CFUNC_DEF("concat", 1, js_array_concat ),-    JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every ),-    JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some ),-    JS_CFUNC_MAGIC_DEF("forEach", 1, js_array_every, special_forEach ),-    JS_CFUNC_MAGIC_DEF("map", 1, js_array_every, special_map ),-    JS_CFUNC_MAGIC_DEF("filter", 1, js_array_every, special_filter ),-    JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ),-    JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ),-    JS_CFUNC_DEF("fill", 1, js_array_fill ),-    JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, 0 ),-    JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, 1 ),-    JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ),-    JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ),-    JS_CFUNC_DEF("includes", 1, js_array_includes ),-    JS_CFUNC_MAGIC_DEF("join", 1, js_array_join, 0 ),-    JS_CFUNC_DEF("toString", 0, js_array_toString ),-    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_array_join, 1 ),-    JS_CFUNC_MAGIC_DEF("pop", 0, js_array_pop, 0 ),-    JS_CFUNC_MAGIC_DEF("push", 1, js_array_push, 0 ),-    JS_CFUNC_MAGIC_DEF("shift", 0, js_array_pop, 1 ),-    JS_CFUNC_MAGIC_DEF("unshift", 1, js_array_push, 1 ),-    JS_CFUNC_DEF("reverse", 0, js_array_reverse ),-    JS_CFUNC_DEF("sort", 1, js_array_sort ),-    JS_CFUNC_MAGIC_DEF("slice", 2, js_array_slice, 0 ),-    JS_CFUNC_MAGIC_DEF("splice", 2, js_array_slice, 1 ),-    JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ),-    JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ),-    JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ),-    JS_CFUNC_MAGIC_DEF("values", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE ),-    JS_ALIAS_DEF("[Symbol.iterator]", "values" ),-    JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ),-    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ),-};--static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 0, js_array_iterator_next, 0 ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Array Iterator", JS_PROP_CONFIGURABLE ),-};--/* Number */--static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue val, obj;-    if (argc == 0) {-        val = JS_NewInt32(ctx, 0);-    } else {-        val = JS_ToNumeric(ctx, argv[0]);-        if (JS_IsException(val))-            return val;-        switch(JS_VALUE_GET_TAG(val)) {-#ifdef CONFIG_BIGNUM-        case JS_TAG_BIG_INT:-        case JS_TAG_BIG_FLOAT:-            {-                JSBigFloat *p = JS_VALUE_GET_PTR(val);-                double d;-                bf_get_float64(&p->num, &d, BF_RNDN);-                JS_FreeValue(ctx, val);-                val = __JS_NewFloat64(ctx, d);-            }-            break;-        case JS_TAG_BIG_DECIMAL:-            val = JS_ToStringFree(ctx, val);-            if (JS_IsException(val))-                return val;-            val = JS_ToNumberFree(ctx, val);-            if (JS_IsException(val))-                return val;-            break;-#endif-        default:-            break;-        }-    }-    if (!JS_IsUndefined(new_target)) {-        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_NUMBER);-        if (!JS_IsException(obj))-            JS_SetObjectData(ctx, obj, val);-        return obj;-    } else {-        return val;-    }-}--#if 0-static JSValue js_number___toInteger(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    return JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[0]));-}--static JSValue js_number___toLength(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    int64_t v;-    if (JS_ToLengthFree(ctx, &v, JS_DupValue(ctx, argv[0])))-        return JS_EXCEPTION;-    return JS_NewInt64(ctx, v);-}-#endif--static JSValue js_number_isNaN(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    if (!JS_IsNumber(argv[0]))-        return JS_FALSE;-    return js_global_isNaN(ctx, this_val, argc, argv);-}--static JSValue js_number_isFinite(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    if (!JS_IsNumber(argv[0]))-        return JS_FALSE;-    return js_global_isFinite(ctx, this_val, argc, argv);-}--static JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    int ret;-    ret = JS_NumberIsInteger(ctx, argv[0]);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    double d;-    if (!JS_IsNumber(argv[0]))-        return JS_FALSE;-    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))-        return JS_EXCEPTION;-    return JS_NewBool(ctx, is_safe_integer(d));-}--static const JSCFunctionListEntry js_number_funcs[] = {-    /* global ParseInt and parseFloat should be defined already or delayed */-    JS_ALIAS_BASE_DEF("parseInt", "parseInt", 0 ),-    JS_ALIAS_BASE_DEF("parseFloat", "parseFloat", 0 ),-    JS_CFUNC_DEF("isNaN", 1, js_number_isNaN ),-    JS_CFUNC_DEF("isFinite", 1, js_number_isFinite ),-    JS_CFUNC_DEF("isInteger", 1, js_number_isInteger ),-    JS_CFUNC_DEF("isSafeInteger", 1, js_number_isSafeInteger ),-    JS_PROP_DOUBLE_DEF("MAX_VALUE", 1.7976931348623157e+308, 0 ),-    JS_PROP_DOUBLE_DEF("MIN_VALUE", 5e-324, 0 ),-    JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),-    JS_PROP_DOUBLE_DEF("NEGATIVE_INFINITY", -INFINITY, 0 ),-    JS_PROP_DOUBLE_DEF("POSITIVE_INFINITY", INFINITY, 0 ),-    JS_PROP_DOUBLE_DEF("EPSILON", 2.220446049250313e-16, 0 ), /* ES6 */-    JS_PROP_DOUBLE_DEF("MAX_SAFE_INTEGER", 9007199254740991.0, 0 ), /* ES6 */-    JS_PROP_DOUBLE_DEF("MIN_SAFE_INTEGER", -9007199254740991.0, 0 ), /* ES6 */-    //JS_CFUNC_DEF("__toInteger", 1, js_number___toInteger ),-    //JS_CFUNC_DEF("__toLength", 1, js_number___toLength ),-};--static JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_IsNumber(this_val))-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_NUMBER) {-            if (JS_IsNumber(p->u.object_data))-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a number");-}--static JSValue js_number_valueOf(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return js_thisNumberValue(ctx, this_val);-}--static int js_get_radix(JSContext *ctx, JSValueConst val)-{-    int radix;-    if (JS_ToInt32Sat(ctx, &radix, val))-        return -1;-    if (radix < 2 || radix > 36) {-        JS_ThrowRangeError(ctx, "radix must be between 2 and 36");-        return -1;-    }-    return radix;-}--static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv, int magic)-{-    JSValue val;-    int base;-    double d;--    val = js_thisNumberValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (magic || JS_IsUndefined(argv[0])) {-        base = 10;-    } else {-        base = js_get_radix(ctx, argv[0]);-        if (base < 0)-            goto fail;-    }-    if (JS_ToFloat64Free(ctx, &d, val))-        return JS_EXCEPTION;-    return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT);- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue val;-    int f;-    double d;--    val = js_thisNumberValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToFloat64Free(ctx, &d, val))-        return JS_EXCEPTION;-    if (JS_ToInt32Sat(ctx, &f, argv[0]))-        return JS_EXCEPTION;-    if (f < 0 || f > 100)-        return JS_ThrowRangeError(ctx, "invalid number of digits");-    if (fabs(d) >= 1e21) {-        return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));-    } else {-        return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);-    }-}--static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue val;-    int f, flags;-    double d;--    val = js_thisNumberValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToFloat64Free(ctx, &d, val))-        return JS_EXCEPTION;-    if (JS_ToInt32Sat(ctx, &f, argv[0]))-        return JS_EXCEPTION;-    if (!isfinite(d)) {-        return JS_ToStringFree(ctx,  __JS_NewFloat64(ctx, d));-    }-    if (JS_IsUndefined(argv[0])) {-        flags = 0;-        f = 0;-    } else {-        if (f < 0 || f > 100)-            return JS_ThrowRangeError(ctx, "invalid number of digits");-        f++;-        flags = JS_DTOA_FIXED_FORMAT;-    }-    return js_dtoa(ctx, d, 10, f, flags | JS_DTOA_FORCE_EXP);-}--static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue val;-    int p;-    double d;--    val = js_thisNumberValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToFloat64Free(ctx, &d, val))-        return JS_EXCEPTION;-    if (JS_IsUndefined(argv[0]))-        goto to_string;-    if (JS_ToInt32Sat(ctx, &p, argv[0]))-        return JS_EXCEPTION;-    if (!isfinite(d)) {-    to_string:-        return JS_ToStringFree(ctx,  __JS_NewFloat64(ctx, d));-    }-    if (p < 1 || p > 100)-        return JS_ThrowRangeError(ctx, "invalid number of digits");-    return js_dtoa(ctx, d, 10, p, JS_DTOA_FIXED_FORMAT);-}--static const JSCFunctionListEntry js_number_proto_funcs[] = {-    JS_CFUNC_DEF("toExponential", 1, js_number_toExponential ),-    JS_CFUNC_DEF("toFixed", 1, js_number_toFixed ),-    JS_CFUNC_DEF("toPrecision", 1, js_number_toPrecision ),-    JS_CFUNC_MAGIC_DEF("toString", 1, js_number_toString, 0 ),-    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_number_toString, 1 ),-    JS_CFUNC_DEF("valueOf", 0, js_number_valueOf ),-};--static JSValue js_parseInt(JSContext *ctx, JSValueConst this_val,-                           int argc, JSValueConst *argv)-{-    const char *str, *p;-    int radix, flags;-    JSValue ret;--    str = JS_ToCString(ctx, argv[0]);-    if (!str)-        return JS_EXCEPTION;-    if (JS_ToInt32(ctx, &radix, argv[1])) {-        JS_FreeCString(ctx, str);-        return JS_EXCEPTION;-    }-    if (radix != 0 && (radix < 2 || radix > 36)) {-        ret = JS_NAN;-    } else {-        p = str;-        p += skip_spaces(p);-        flags = ATOD_INT_ONLY | ATOD_ACCEPT_PREFIX_AFTER_SIGN;-        ret = js_atof(ctx, p, NULL, radix, flags);-    }-    JS_FreeCString(ctx, str);-    return ret;-}--static JSValue js_parseFloat(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    const char *str, *p;-    JSValue ret;--    str = JS_ToCString(ctx, argv[0]);-    if (!str)-        return JS_EXCEPTION;-    p = str;-    p += skip_spaces(p);-    ret = js_atof(ctx, p, NULL, 10, 0);-    JS_FreeCString(ctx, str);-    return ret;-}--/* Boolean */-static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue val, obj;-    val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0]));-    if (!JS_IsUndefined(new_target)) {-        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_BOOLEAN);-        if (!JS_IsException(obj))-            JS_SetObjectData(ctx, obj, val);-        return obj;-    } else {-        return val;-    }-}--static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL)-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_BOOLEAN) {-            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_BOOL)-                return p->u.object_data;-        }-    }-    return JS_ThrowTypeError(ctx, "not a boolean");-}--static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    JSValue val = js_thisBooleanValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ?-                       JS_ATOM_true : JS_ATOM_false);-}--static JSValue js_boolean_valueOf(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    return js_thisBooleanValue(ctx, this_val);-}--static const JSCFunctionListEntry js_boolean_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_boolean_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_boolean_valueOf ),-};--/* String */--static int js_string_get_own_property(JSContext *ctx,-                                      JSPropertyDescriptor *desc,-                                      JSValueConst obj, JSAtom prop)-{-    JSObject *p;-    JSString *p1;-    uint32_t idx, ch;--    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */-    if (__JS_AtomIsTaggedInt(prop)) {-        p = JS_VALUE_GET_OBJ(obj);-        if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {-            p1 = JS_VALUE_GET_STRING(p->u.object_data);-            idx = __JS_AtomToUInt32(prop);-            if (idx < p1->len) {-                if (desc) {-                    if (p1->is_wide_char)-                        ch = p1->u.str16[idx];-                    else-                        ch = p1->u.str8[idx];-                    desc->flags = JS_PROP_ENUMERABLE;-                    desc->value = js_new_string_char(ctx, ch);-                    desc->getter = JS_UNDEFINED;-                    desc->setter = JS_UNDEFINED;-                }-                return TRUE;-            }-        }-    }-    return FALSE;-}--static uint32_t js_string_obj_get_length(JSContext *ctx,-                                         JSValueConst obj)-{-    JSObject *p;-    JSString *p1;-    uint32_t len = 0;--    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */-    p = JS_VALUE_GET_OBJ(obj);-    if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {-        p1 = JS_VALUE_GET_STRING(p->u.object_data);-        len = p1->len;-    }-    return len;-}--static int js_string_get_own_property_names(JSContext *ctx,-                                            JSPropertyEnum **ptab,-                                            uint32_t *plen,-                                            JSValueConst obj)-{-    JSPropertyEnum *tab;-    uint32_t len, i;--    len = js_string_obj_get_length(ctx, obj);-    tab = NULL;-    if (len > 0) {-        /* do not allocate 0 bytes */-        tab = js_malloc(ctx, sizeof(JSPropertyEnum) * len);-        if (!tab)-            return -1;-        for(i = 0; i < len; i++) {-            tab[i].atom = __JS_AtomFromUInt32(i);-        }-    }-    *ptab = tab;-    *plen = len;-    return 0;-}--static int js_string_define_own_property(JSContext *ctx,-                                         JSValueConst this_obj,-                                         JSAtom prop, JSValueConst val,-                                         JSValueConst getter,-                                         JSValueConst setter, int flags)-{-    uint32_t idx;-    JSObject *p;-    JSString *p1, *p2;-    -    if (__JS_AtomIsTaggedInt(prop)) {-        idx = __JS_AtomToUInt32(prop);-        p = JS_VALUE_GET_OBJ(this_obj);-        if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)-            goto def;-        p1 = JS_VALUE_GET_STRING(p->u.object_data);-        if (idx >= p1->len)-            goto def;-        if (!check_define_prop_flags(JS_PROP_ENUMERABLE, flags))-            goto fail;-        /* check that the same value is configured */-        if (flags & JS_PROP_HAS_VALUE) {-            if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)-                goto fail;-            p2 = JS_VALUE_GET_STRING(val);-            if (p2->len != 1)-                goto fail;-            if (string_get(p1, idx) != string_get(p2, 0)) {-            fail:-                return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");-            }-        }-        return TRUE;-    } else {-    def:-        return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,-                                 flags | JS_PROP_NO_EXOTIC);-    }-}--static int js_string_delete_property(JSContext *ctx,-                                     JSValueConst obj, JSAtom prop)-{-    uint32_t idx;--    if (__JS_AtomIsTaggedInt(prop)) {-        idx = __JS_AtomToUInt32(prop);-        if (idx < js_string_obj_get_length(ctx, obj)) {-            return FALSE;-        }-    }-    return TRUE;-}--static const JSClassExoticMethods js_string_exotic_methods = {-    .get_own_property = js_string_get_own_property,-    .get_own_property_names = js_string_get_own_property_names,-    .define_own_property = js_string_define_own_property,-    .delete_property = js_string_delete_property,-};--static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue val, obj;-    if (argc == 0) {-        val = JS_AtomToString(ctx, JS_ATOM_empty_string);-    } else {-        if (JS_IsUndefined(new_target) && JS_IsSymbol(argv[0])) {-            JSAtomStruct *p = JS_VALUE_GET_PTR(argv[0]);-            val = JS_ConcatString3(ctx, "Symbol(", JS_AtomToString(ctx, js_get_atom_index(ctx->rt, p)), ")");-        } else {-            val = JS_ToString(ctx, argv[0]);-        }-        if (JS_IsException(val))-            return val;-    }-    if (!JS_IsUndefined(new_target)) {-        JSString *p1 = JS_VALUE_GET_STRING(val);--        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_STRING);-        if (!JS_IsException(obj)) {-            JS_SetObjectData(ctx, obj, val);-            JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);-        }-        return obj;-    } else {-        return val;-    }-}--static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING)-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_STRING) {-            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING)-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a string");-}--static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    int i;-    StringBuffer b_s, *b = &b_s;--    string_buffer_init(ctx, b, argc);--    for(i = 0; i < argc; i++) {-        int32_t c;-        if (JS_ToInt32(ctx, &c, argv[i]) || string_buffer_putc16(b, c & 0xffff)) {-            string_buffer_free(b);-            return JS_EXCEPTION;-        }-    }-    return string_buffer_end(b);-}--static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    double d;-    int i, c;-    StringBuffer b_s, *b = &b_s;--    /* XXX: could pre-compute string length if all arguments are JS_TAG_INT */--    if (string_buffer_init(ctx, b, argc))-        goto fail;-    for(i = 0; i < argc; i++) {-        if (JS_VALUE_GET_TAG(argv[i]) == JS_TAG_INT) {-            c = JS_VALUE_GET_INT(argv[i]);-            if (c < 0 || c > 0x10ffff)-                goto range_error;-        } else {-            if (JS_ToFloat64(ctx, &d, argv[i]))-                goto fail;-            if (d < 0 || d > 0x10ffff || (c = (int)d) != d)-                goto range_error;-        }-        if (string_buffer_putc(b, c))-            goto fail;-    }-    return string_buffer_end(b);-- range_error:-    JS_ThrowRangeError(ctx, "invalid code point");- fail:-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    // raw(temp,...a)-    JSValue cooked, val, raw;-    StringBuffer b_s, *b = &b_s;-    int64_t i, n;--    string_buffer_init(ctx, b, 0);-    raw = JS_UNDEFINED;-    cooked = JS_ToObject(ctx, argv[0]);-    if (JS_IsException(cooked))-        goto exception;-    raw = JS_ToObjectFree(ctx, JS_GetProperty(ctx, cooked, JS_ATOM_raw));-    if (JS_IsException(raw))-        goto exception;-    if (js_get_length64(ctx, &n, raw) < 0)-        goto exception;-        -    for (i = 0; i < n; i++) {-        val = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, raw, i));-        if (JS_IsException(val))-            goto exception;-        string_buffer_concat_value_free(b, val);-        if (i < n - 1 && i + 1 < argc) {-            if (string_buffer_concat_value(b, argv[i + 1]))-                goto exception;-        }-    }-    JS_FreeValue(ctx, cooked);-    JS_FreeValue(ctx, raw);-    return string_buffer_end(b);--exception:-    JS_FreeValue(ctx, cooked);-    JS_FreeValue(ctx, raw);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--/* only used in test262 */-JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    uint32_t start, end, i, n;-    StringBuffer b_s, *b = &b_s;--    if (JS_ToUint32(ctx, &start, argv[0]) ||-        JS_ToUint32(ctx, &end, argv[1]))-        return JS_EXCEPTION;-    end = min_uint32(end, 0x10ffff + 1);--    if (start > end) {-        start = end;-    }-    n = end - start;-    if (end > 0x10000) {-        n += end - max_uint32(start, 0x10000);-    }-    if (string_buffer_init2(ctx, b, n, end >= 0x100))-        return JS_EXCEPTION;-    for(i = start; i < end; i++) {-        string_buffer_putc(b, i);-    }-    return string_buffer_end(b);-}--#if 0-static JSValue js_string___isSpace(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    int c;-    if (JS_ToInt32(ctx, &c, argv[0]))-        return JS_EXCEPTION;-    return JS_NewBool(ctx, lre_is_space(c));-}-#endif--static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue val, ret;-    JSString *p;-    int idx, c;--    val = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_STRING(val);-    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {-        JS_FreeValue(ctx, val);-        return JS_EXCEPTION;-    }-    if (idx < 0 || idx >= p->len) {-        ret = JS_NAN;-    } else {-        if (p->is_wide_char)-            c = p->u.str16[idx];-        else-            c = p->u.str8[idx];-        ret = JS_NewInt32(ctx, c);-    }-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue val, ret;-    JSString *p;-    int idx, c;--    val = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_STRING(val);-    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {-        JS_FreeValue(ctx, val);-        return JS_EXCEPTION;-    }-    if (idx < 0 || idx >= p->len) {-        ret = js_new_string8(ctx, NULL, 0);-    } else {-        if (p->is_wide_char)-            c = p->u.str16[idx];-        else-            c = p->u.str8[idx];-        ret = js_new_string_char(ctx, c);-    }-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue val, ret;-    JSString *p;-    int idx, c;--    val = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_STRING(val);-    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {-        JS_FreeValue(ctx, val);-        return JS_EXCEPTION;-    }-    if (idx < 0 || idx >= p->len) {-        ret = JS_UNDEFINED;-    } else {-        c = string_getc(p, &idx);-        ret = JS_NewInt32(ctx, c);-    }-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue r;-    int i;--    /* XXX: Use more efficient method */-    /* XXX: This method is OK if r has a single refcount */-    /* XXX: should use string_buffer? */-    r = JS_ToStringCheckObject(ctx, this_val);-    for (i = 0; i < argc; i++) {-        if (JS_IsException(r))-            break;-        r = JS_ConcatString(ctx, r, JS_DupValue(ctx, argv[i]));-    }-    return r;-}--static int string_cmp(JSString *p1, JSString *p2, int x1, int x2, int len)-{-    int i, c1, c2;-    for (i = 0; i < len; i++) {-        if ((c1 = string_get(p1, x1 + i)) != (c2 = string_get(p2, x2 + i)))-            return c1 - c2;-    }-    return 0;-}--static int string_indexof_char(JSString *p, int c, int from)-{-    /* assuming 0 <= from <= p->len */-    int i, len = p->len;-    if (p->is_wide_char) {-        for (i = from; i < len; i++) {-            if (p->u.str16[i] == c)-                return i;-        }-    } else {-        if ((c & ~0xff) == 0) {-            for (i = from; i < len; i++) {-                if (p->u.str8[i] == (uint8_t)c)-                    return i;-            }-        }-    }-    return -1;-}--static int string_indexof(JSString *p1, JSString *p2, int from)-{-    /* assuming 0 <= from <= p1->len */-    int c, i, j, len1 = p1->len, len2 = p2->len;-    if (len2 == 0)-        return from;-    for (i = from, c = string_get(p2, 0); i + len2 <= len1; i = j + 1) {-        j = string_indexof_char(p1, c, i);-        if (j < 0 || j + len2 > len1)-            break;-        if (!string_cmp(p1, p2, j + 1, 1, len2 - 1))-            return j;-    }-    return -1;-}--static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)-{-    if (!unicode || index >= p->len || !p->is_wide_char) {-        index++;-    } else {-        int index32 = (int)index;-        string_getc(p, &index32);-        index = index32;-    }-    return index;-}--static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv, int lastIndexOf)-{-    JSValue str, v;-    int i, len, v_len, pos, start, stop, ret, inc;-    JSString *p;-    JSString *p1;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    v = JS_ToString(ctx, argv[0]);-    if (JS_IsException(v))-        goto fail;-    p = JS_VALUE_GET_STRING(str);-    p1 = JS_VALUE_GET_STRING(v);-    len = p->len;-    v_len = p1->len;-    if (lastIndexOf) {-        pos = len - v_len;-        if (argc > 1) {-            double d;-            if (JS_ToFloat64(ctx, &d, argv[1]))-                goto fail;-            if (!isnan(d)) {-                if (d <= 0)-                    pos = 0;-                else if (d < pos)-                    pos = d;-            }-        }-        start = pos;-        stop = 0;-        inc = -1;-    } else {-        pos = 0;-        if (argc > 1) {-            if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))-                goto fail;-        }-        start = pos;-        stop = len - v_len;-        inc = 1;-    }-    ret = -1;-    if (len >= v_len && inc * (stop - start) >= 0) {-        for (i = start;; i += inc) {-            if (!string_cmp(p, p1, i, 0, v_len)) {-                ret = i;-                break;-            }-            if (i == stop)-                break;-        }-    }-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, v);-    return JS_NewInt32(ctx, ret);--fail:-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, v);-    return JS_EXCEPTION;-}--/* return < 0 if exception or TRUE/FALSE */-static int js_is_regexp(JSContext *ctx, JSValueConst obj);--static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv, int magic)-{-    JSValue str, v = JS_UNDEFINED;-    int i, len, v_len, pos, start, stop, ret;-    JSString *p;-    JSString *p1;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    ret = js_is_regexp(ctx, argv[0]);-    if (ret) {-        if (ret > 0)-            JS_ThrowTypeError(ctx, "regex not supported");-        goto fail;-    }-    v = JS_ToString(ctx, argv[0]);-    if (JS_IsException(v))-        goto fail;-    p = JS_VALUE_GET_STRING(str);-    p1 = JS_VALUE_GET_STRING(v);-    len = p->len;-    v_len = p1->len;-    pos = (magic == 2) ? len : 0;-    if (argc > 1 && !JS_IsUndefined(argv[1])) {-        if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))-            goto fail;-    }-    len -= v_len;-    ret = 0;-    if (magic == 0) {-        start = pos;-        stop = len;-    } else {-        if (magic == 1) {-            if (pos > len)-                goto done;-        } else {-            pos -= v_len;-        }-        start = stop = pos;-    }-    if (start >= 0 && start <= stop) {-        for (i = start;; i++) {-            if (!string_cmp(p, p1, i, 0, v_len)) {-                ret = 1;-                break;-            }-            if (i == stop)-                break;-        }-    }- done:-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, v);-    return JS_NewBool(ctx, ret);--fail:-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, v);-    return JS_EXCEPTION;-}--static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp)-{-    int ret;-    JSValue flags;-    -    ret = js_is_regexp(ctx, regexp);-    if (ret < 0)-        return -1;-    if (ret) {-        flags = JS_GetProperty(ctx, regexp, JS_ATOM_flags);-        if (JS_IsException(flags))-            return -1;-        if (JS_IsUndefined(flags) || JS_IsNull(flags)) {-            JS_ThrowTypeError(ctx, "cannot convert to object");-            return -1;-        }-        flags = JS_ToStringFree(ctx, flags);-        if (JS_IsException(flags))-            return -1;-        ret = string_indexof_char(JS_VALUE_GET_STRING(flags), 'g', 0);-        JS_FreeValue(ctx, flags);-        if (ret < 0) {-            JS_ThrowTypeError(ctx, "regexp must have the 'g' flag");-            return -1;-        }-    }-    return 0;-}--static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv, int atom)-{-    // match(rx), search(rx), matchAll(rx)-    // atom is JS_ATOM_Symbol_match, JS_ATOM_Symbol_search, or JS_ATOM_Symbol_matchAll-    JSValueConst O = this_val, regexp = argv[0], args[2];-    JSValue matcher, S, rx, result, str;-    int args_len;--    if (JS_IsUndefined(O) || JS_IsNull(O))-        return JS_ThrowTypeError(ctx, "cannot convert to object");--    if (!JS_IsUndefined(regexp) && !JS_IsNull(regexp)) {-        matcher = JS_GetProperty(ctx, regexp, atom);-        if (JS_IsException(matcher))-            return JS_EXCEPTION;-        if (atom == JS_ATOM_Symbol_matchAll) {-            if (check_regexp_g_flag(ctx, regexp) < 0) {-                JS_FreeValue(ctx, matcher);-                return JS_EXCEPTION;-            }-        }-        if (!JS_IsUndefined(matcher) && !JS_IsNull(matcher)) {-            return JS_CallFree(ctx, matcher, regexp, 1, &O);-        }-    }-    S = JS_ToString(ctx, O);-    if (JS_IsException(S))-        return JS_EXCEPTION;-    args_len = 1;-    args[0] = regexp;-    str = JS_UNDEFINED;-    if (atom == JS_ATOM_Symbol_matchAll) {-        str = JS_NewString(ctx, "g");-        if (JS_IsException(str))-            goto fail;-        args[args_len++] = (JSValueConst)str;-    }-    rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args);-    JS_FreeValue(ctx, str);-    if (JS_IsException(rx)) {-    fail:-        JS_FreeValue(ctx, S);-        return JS_EXCEPTION;-    }-    result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);-    JS_FreeValue(ctx, S);-    return result;-}--static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val,-                                           int argc, JSValueConst *argv)-{-    // GetSubstitution(matched, str, position, captures, namedCaptures, rep)-    JSValueConst matched, str, captures, namedCaptures, rep;-    JSValue capture, name, s;-    uint32_t position, len, matched_len, captures_len;-    int i, j, j0, k, k1;-    int c, c1;-    StringBuffer b_s, *b = &b_s;-    JSString *sp, *rp;--    matched = argv[0];-    str = argv[1];-    captures = argv[3];-    namedCaptures = argv[4];-    rep = argv[5];--    if (!JS_IsString(rep) || !JS_IsString(str))-        return JS_ThrowTypeError(ctx, "not a string");--    sp = JS_VALUE_GET_STRING(str);-    rp = JS_VALUE_GET_STRING(rep);--    string_buffer_init(ctx, b, 0);--    captures_len = 0;-    if (!JS_IsUndefined(captures)) {-        if (js_get_length32(ctx, &captures_len, captures))-            goto exception;-    }-    if (js_get_length32(ctx, &matched_len, matched))-        goto exception;-    if (JS_ToUint32(ctx, &position, argv[2]) < 0)-        goto exception;--    len = rp->len;-    i = 0;-    for(;;) {-        j = string_indexof_char(rp, '$', i);-        if (j < 0 || j + 1 >= len)-            break;-        string_buffer_concat(b, rp, i, j);-        j0 = j++;-        c = string_get(rp, j++);-        if (c == '$') {-            string_buffer_putc8(b, '$');-        } else if (c == '&') {-            if (string_buffer_concat_value(b, matched))-                goto exception;-        } else if (c == '`') {-            string_buffer_concat(b, sp, 0, position);-        } else if (c == '\'') {-            string_buffer_concat(b, sp, position + matched_len, sp->len);-        } else if (c >= '0' && c <= '9') {-            k = c - '0';-            c1 = string_get(rp, j);-            if (c1 >= '0' && c1 <= '9') {-                /* This behavior is specified in ES6 and refined in ECMA 2019 */-                /* ECMA 2019 does not have the extra test, but-                   Test262 S15.5.4.11_A3_T1..3 require this behavior */-                k1 = k * 10 + c1 - '0';-                if (k1 >= 1 && k1 < captures_len) {-                    k = k1;-                    j++;-                }-            }-            if (k >= 1 && k < captures_len) {-                s = JS_GetPropertyInt64(ctx, captures, k);-                if (JS_IsException(s))-                    goto exception;-                if (!JS_IsUndefined(s)) {-                    if (string_buffer_concat_value_free(b, s))-                        goto exception;-                }-            } else {-                goto norep;-            }-        } else if (c == '<' && !JS_IsUndefined(namedCaptures)) {-            k = string_indexof_char(rp, '>', j);-            if (k < 0)-                goto norep;-            name = js_sub_string(ctx, rp, j, k);-            if (JS_IsException(name))-                goto exception;-            capture = JS_GetPropertyValue(ctx, namedCaptures, name);-            if (JS_IsException(capture))-                goto exception;-            if (!JS_IsUndefined(capture)) {-                if (string_buffer_concat_value_free(b, capture))-                    goto exception;-            }-            j = k + 1;-        } else {-        norep:-            string_buffer_concat(b, rp, j0, j);-        }-        i = j;-    }-    string_buffer_concat(b, rp, i, rp->len);-    return string_buffer_end(b);-exception:-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv,-                                 int is_replaceAll)-{-    // replace(rx, rep)-    JSValueConst O = this_val, searchValue = argv[0], replaceValue = argv[1];-    JSValueConst args[6];-    JSValue str, search_str, replaceValue_str, repl_str;-    JSString *sp, *searchp;-    StringBuffer b_s, *b = &b_s;-    int pos, functionalReplace, endOfLastMatch;-    BOOL is_first;--    if (JS_IsUndefined(O) || JS_IsNull(O))-        return JS_ThrowTypeError(ctx, "cannot convert to object");--    search_str = JS_UNDEFINED;-    replaceValue_str = JS_UNDEFINED;-    repl_str = JS_UNDEFINED;--    if (!JS_IsUndefined(searchValue) && !JS_IsNull(searchValue)) {-        JSValue replacer;-        if (is_replaceAll) {-            if (check_regexp_g_flag(ctx, searchValue) < 0)-                return JS_EXCEPTION;-        }-        replacer = JS_GetProperty(ctx, searchValue, JS_ATOM_Symbol_replace);-        if (JS_IsException(replacer))-            return JS_EXCEPTION;-        if (!JS_IsUndefined(replacer) && !JS_IsNull(replacer)) {-            args[0] = O;-            args[1] = replaceValue;-            return JS_CallFree(ctx, replacer, searchValue, 2, args);-        }-    }-    string_buffer_init(ctx, b, 0);--    str = JS_ToString(ctx, O);-    if (JS_IsException(str))-        goto exception;-    search_str = JS_ToString(ctx, searchValue);-    if (JS_IsException(search_str))-        goto exception;-    functionalReplace = JS_IsFunction(ctx, replaceValue);-    if (!functionalReplace) {-        replaceValue_str = JS_ToString(ctx, replaceValue);-        if (JS_IsException(replaceValue_str))-            goto exception;-    }--    sp = JS_VALUE_GET_STRING(str);-    searchp = JS_VALUE_GET_STRING(search_str);-    endOfLastMatch = 0;-    is_first = TRUE;-    for(;;) {-        if (unlikely(searchp->len == 0)) {-            if (is_first)-                pos = 0;-            else if (endOfLastMatch >= sp->len)-                pos = -1;-            else-                pos = endOfLastMatch + 1;-        } else {-            pos = string_indexof(sp, searchp, endOfLastMatch);-        }-        if (pos < 0) {-            if (is_first) {-                string_buffer_free(b);-                JS_FreeValue(ctx, search_str);-                JS_FreeValue(ctx, replaceValue_str);-                return str;-            } else {-                break;-            }-        }-        if (functionalReplace) {-            args[0] = search_str;-            args[1] = JS_NewInt32(ctx, pos);-            args[2] = str;-            repl_str = JS_ToStringFree(ctx, JS_Call(ctx, replaceValue, JS_UNDEFINED, 3, args));-        } else {-            args[0] = search_str;-            args[1] = str;-            args[2] = JS_NewInt32(ctx, pos);-            args[3] = JS_UNDEFINED;-            args[4] = JS_UNDEFINED;-            args[5] = replaceValue_str;-            repl_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args);-        }-        if (JS_IsException(repl_str))-            goto exception;-        -        string_buffer_concat(b, sp, endOfLastMatch, pos);-        string_buffer_concat_value_free(b, repl_str);-        endOfLastMatch = pos + searchp->len;-        is_first = FALSE;-        if (!is_replaceAll)-            break;-    }-    string_buffer_concat(b, sp, endOfLastMatch, sp->len);-    JS_FreeValue(ctx, search_str);-    JS_FreeValue(ctx, replaceValue_str);-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);--exception:-    string_buffer_free(b);-    JS_FreeValue(ctx, search_str);-    JS_FreeValue(ctx, replaceValue_str);-    JS_FreeValue(ctx, str);-    return JS_EXCEPTION;-}--static JSValue js_string_split(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    // split(sep, limit)-    JSValueConst O = this_val, separator = argv[0], limit = argv[1];-    JSValueConst args[2];-    JSValue S, A, R, T;-    uint32_t lim, lengthA;-    int64_t p, q, s, r, e;-    JSString *sp, *rp;--    if (JS_IsUndefined(O) || JS_IsNull(O))-        return JS_ThrowTypeError(ctx, "cannot convert to object");--    S = JS_UNDEFINED;-    A = JS_UNDEFINED;-    R = JS_UNDEFINED;--    if (!JS_IsUndefined(separator) && !JS_IsNull(separator)) {-        JSValue splitter;-        splitter = JS_GetProperty(ctx, separator, JS_ATOM_Symbol_split);-        if (JS_IsException(splitter))-            return JS_EXCEPTION;-        if (!JS_IsUndefined(splitter) && !JS_IsNull(splitter)) {-            args[0] = O;-            args[1] = limit;-            return JS_CallFree(ctx, splitter, separator, 2, args);-        }-    }-    S = JS_ToString(ctx, O);-    if (JS_IsException(S))-        goto exception;-    A = JS_NewArray(ctx);-    if (JS_IsException(A))-        goto exception;-    lengthA = 0;-    if (JS_IsUndefined(limit)) {-        lim = 0xffffffff;-    } else {-        if (JS_ToUint32(ctx, &lim, limit) < 0)-            goto exception;-    }-    sp = JS_VALUE_GET_STRING(S);-    s = sp->len;-    R = JS_ToString(ctx, separator);-    if (JS_IsException(R))-        goto exception;-    rp = JS_VALUE_GET_STRING(R);-    r = rp->len;-    p = 0;-    if (lim == 0)-        goto done;-    if (JS_IsUndefined(separator))-        goto add_tail;-    if (s == 0) {-        if (r != 0)-            goto add_tail;-        goto done;-    }-    q = p;-    for (q = p; (q += !r) <= s - r - !r; q = p = e + r) {-        e = string_indexof(sp, rp, q);-        if (e < 0)-            break;-        T = js_sub_string(ctx, sp, p, e);-        if (JS_IsException(T))-            goto exception;-        if (JS_CreateDataPropertyUint32(ctx, A, lengthA++, T, 0) < 0)-            goto exception;-        if (lengthA == lim)-            goto done;-    }-add_tail:-    T = js_sub_string(ctx, sp, p, s);-    if (JS_IsException(T))-        goto exception;-    if (JS_CreateDataPropertyUint32(ctx, A, lengthA++, T,0 ) < 0)-        goto exception;-done:-    JS_FreeValue(ctx, S);-    JS_FreeValue(ctx, R);-    return A;--exception:-    JS_FreeValue(ctx, A);-    JS_FreeValue(ctx, S);-    JS_FreeValue(ctx, R);-    return JS_EXCEPTION;-}--static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    JSValue str, ret;-    int a, b, start, end;-    JSString *p;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    p = JS_VALUE_GET_STRING(str);-    if (JS_ToInt32Clamp(ctx, &a, argv[0], 0, p->len, 0)) {-        JS_FreeValue(ctx, str);-        return JS_EXCEPTION;-    }-    b = p->len;-    if (!JS_IsUndefined(argv[1])) {-        if (JS_ToInt32Clamp(ctx, &b, argv[1], 0, p->len, 0)) {-            JS_FreeValue(ctx, str);-            return JS_EXCEPTION;-        }-    }-    if (a < b) {-        start = a;-        end = b;-    } else {-        start = b;-        end = a;-    }-    ret = js_sub_string(ctx, p, start, end);-    JS_FreeValue(ctx, str);-    return ret;-}--static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue str, ret;-    int a, len, n;-    JSString *p;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    p = JS_VALUE_GET_STRING(str);-    len = p->len;-    if (JS_ToInt32Clamp(ctx, &a, argv[0], 0, len, len)) {-        JS_FreeValue(ctx, str);-        return JS_EXCEPTION;-    }-    n = len - a;-    if (!JS_IsUndefined(argv[1])) {-        if (JS_ToInt32Clamp(ctx, &n, argv[1], 0, len - a, 0)) {-            JS_FreeValue(ctx, str);-            return JS_EXCEPTION;-        }-    }-    ret = js_sub_string(ctx, p, a, a + n);-    JS_FreeValue(ctx, str);-    return ret;-}--static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    JSValue str, ret;-    int len, start, end;-    JSString *p;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    p = JS_VALUE_GET_STRING(str);-    len = p->len;-    if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) {-        JS_FreeValue(ctx, str);-        return JS_EXCEPTION;-    }-    end = len;-    if (!JS_IsUndefined(argv[1])) {-        if (JS_ToInt32Clamp(ctx, &end, argv[1], 0, len, len)) {-            JS_FreeValue(ctx, str);-            return JS_EXCEPTION;-        }-    }-    ret = js_sub_string(ctx, p, start, max_int(end, start));-    JS_FreeValue(ctx, str);-    return ret;-}--static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv, int padEnd)-{-    JSValue str, v = JS_UNDEFINED;-    StringBuffer b_s, *b = &b_s;-    JSString *p, *p1 = NULL;-    int n, len, c = ' ';--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        goto fail1;-    if (JS_ToInt32Sat(ctx, &n, argv[0]))-        goto fail2;-    p = JS_VALUE_GET_STRING(str);-    len = p->len;-    if (len >= n)-        return str;-    if (argc > 1 && !JS_IsUndefined(argv[1])) {-        v = JS_ToString(ctx, argv[1]);-        if (JS_IsException(v))-            goto fail2;-        p1 = JS_VALUE_GET_STRING(v);-        if (p1->len == 0) {-            JS_FreeValue(ctx, v);-            return str;-        }-        if (p1->len == 1) {-            c = string_get(p1, 0);-            p1 = NULL;-        }-    }-    if (n > JS_STRING_LEN_MAX) {-        JS_ThrowInternalError(ctx, "string too long");-        goto fail2;-    }-    if (string_buffer_init(ctx, b, n))-        goto fail3;-    n -= len;-    if (padEnd) {-        if (string_buffer_concat(b, p, 0, len))-            goto fail;-    }-    if (p1) {-        while (n > 0) {-            int chunk = min_int(n, p1->len);-            if (string_buffer_concat(b, p1, 0, chunk))-                goto fail;-            n -= chunk;-        }-    } else {-        if (string_buffer_fill(b, c, n))-            goto fail;-    }-    if (!padEnd) {-        if (string_buffer_concat(b, p, 0, len))-            goto fail;-    }-    JS_FreeValue(ctx, v);-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);--fail:-    string_buffer_free(b);-fail3:-    JS_FreeValue(ctx, v);-fail2:-    JS_FreeValue(ctx, str);-fail1:-    return JS_EXCEPTION;-}--static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue str;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int64_t val;-    int n, len;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        goto fail;-    if (JS_ToInt64Sat(ctx, &val, argv[0]))-        goto fail;-    if (val < 0 || val > 2147483647) {-        JS_ThrowRangeError(ctx, "invalid repeat count");-        goto fail;-    }-    n = val;-    p = JS_VALUE_GET_STRING(str);-    len = p->len;-    if (len == 0 || n == 1)-        return str;-    if (val * len > JS_STRING_LEN_MAX) {-        JS_ThrowInternalError(ctx, "string too long");-        goto fail;-    }-    if (string_buffer_init2(ctx, b, n * len, p->is_wide_char))-        goto fail;-    if (len == 1) {-        string_buffer_fill(b, string_get(p, 0), n);-    } else {-        while (n-- > 0) {-            string_buffer_concat(b, p, 0, len);-        }-    }-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);--fail:-    JS_FreeValue(ctx, str);-    return JS_EXCEPTION;-}--static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    JSValue str, ret;-    int a, b, len;-    JSString *p;--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return str;-    p = JS_VALUE_GET_STRING(str);-    a = 0;-    b = len = p->len;-    if (magic & 1) {-        while (a < len && lre_is_space(string_get(p, a)))-            a++;-    }-    if (magic & 2) {-        while (b > a && lre_is_space(string_get(p, b - 1)))-            b--;-    }-    ret = js_sub_string(ctx, p, a, b);-    JS_FreeValue(ctx, str);-    return ret;-}--static JSValue js_string___quote(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return JS_ToQuotedString(ctx, this_val);-}--/* return 0 if before the first char */-static int string_prevc(JSString *p, int *pidx)-{-    int idx, c, c1;--    idx = *pidx;-    if (idx <= 0)-        return 0;-    idx--;-    if (p->is_wide_char) {-        c = p->u.str16[idx];-        if (c >= 0xdc00 && c < 0xe000 && idx > 0) {-            c1 = p->u.str16[idx - 1];-            if (c1 >= 0xd800 && c1 <= 0xdc00) {-                c = (((c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000;-                idx--;-            }-        }-    } else {-        c = p->u.str8[idx];-    }-    *pidx = idx;-    return c;-}--static BOOL test_final_sigma(JSString *p, int sigma_pos)-{-    int k, c1;--    /* before C: skip case ignorable chars and check there is-       a cased letter */-    k = sigma_pos;-    for(;;) {-        c1 = string_prevc(p, &k);-        if (!lre_is_case_ignorable(c1))-            break;-    }-    if (!lre_is_cased(c1))-        return FALSE;--    /* after C: skip case ignorable chars and check there is-       no cased letter */-    k = sigma_pos + 1;-    for(;;) {-        if (k >= p->len)-            return TRUE;-        c1 = string_getc(p, &k);-        if (!lre_is_case_ignorable(c1))-            break;-    }-    return !lre_is_cased(c1);-}--static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue a, b;-    int cmp;--    a = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(a))-        return JS_EXCEPTION;-    b = JS_ToString(ctx, argv[0]);-    if (JS_IsException(b)) {-        JS_FreeValue(ctx, a);-        return JS_EXCEPTION;-    }-    cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));-    JS_FreeValue(ctx, a);-    JS_FreeValue(ctx, b);-    return JS_NewInt32(ctx, cmp);-}--static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv, int to_lower)-{-    JSValue val;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int i, c, j, l;-    uint32_t res[LRE_CC_RES_LEN_MAX];--    val = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_STRING(val);-    if (p->len == 0)-        return val;-    if (string_buffer_init(ctx, b, p->len))-        goto fail;-    for(i = 0; i < p->len;) {-        c = string_getc(p, &i);-        if (c == 0x3a3 && to_lower && test_final_sigma(p, i - 1)) {-            res[0] = 0x3c2; /* final sigma */-            l = 1;-        } else {-            l = lre_case_conv(res, c, to_lower);-        }-        for(j = 0; j < l; j++) {-            if (string_buffer_putc(b, res[j]))-                goto fail;-        }-    }-    JS_FreeValue(ctx, val);-    return string_buffer_end(b);- fail:-    JS_FreeValue(ctx, val);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--#ifdef CONFIG_ALL_UNICODE--/* return (-1, NULL) if exception, otherwise (len, buf) */-static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValueConst val1)-{-    JSValue val;-    JSString *p;-    uint32_t *buf;-    int i, j, len;--    val = JS_ToString(ctx, val1);-    if (JS_IsException(val))-        return -1;-    p = JS_VALUE_GET_STRING(val);-    len = p->len;-    /* UTF32 buffer length is len minus the number of correct surrogates pairs */-    buf = js_malloc(ctx, sizeof(buf[0]) * max_int(len, 1));-    if (!buf) {-        JS_FreeValue(ctx, val);-        goto fail;-    }-    for(i = j = 0; i < len;)-        buf[j++] = string_getc(p, &i);-    JS_FreeValue(ctx, val);-    *pbuf = buf;-    return j;- fail:-    *pbuf = NULL;-    return -1;-}--static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)-{-    int i;-    StringBuffer b_s, *b = &b_s;-    if (string_buffer_init(ctx, b, len))-        return JS_EXCEPTION;-    for(i = 0; i < len; i++) {-        if (string_buffer_putc(b, buf[i]))-            goto fail;-    }-    return string_buffer_end(b);- fail:-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    const char *form, *p;-    size_t form_len;-    int is_compat, buf_len, out_len;-    UnicodeNormalizationEnum n_type;-    JSValue val;-    uint32_t *buf, *out_buf;--    val = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(val))-        return val;-    buf_len = JS_ToUTF32String(ctx, &buf, val);-    JS_FreeValue(ctx, val);-    if (buf_len < 0)-        return JS_EXCEPTION;--    if (argc == 0 || JS_IsUndefined(argv[0])) {-        n_type = UNICODE_NFC;-    } else {-        form = JS_ToCStringLen(ctx, &form_len, argv[0]);-        if (!form)-            goto fail1;-        p = form;-        if (p[0] != 'N' || p[1] != 'F')-            goto bad_form;-        p += 2;-        is_compat = FALSE;-        if (*p == 'K') {-            is_compat = TRUE;-            p++;-        }-        if (*p == 'C' || *p == 'D') {-            n_type = UNICODE_NFC + is_compat * 2 + (*p - 'C');-            if ((p + 1 - form) != form_len)-                goto bad_form;-        } else {-        bad_form:-            JS_FreeCString(ctx, form);-            JS_ThrowRangeError(ctx, "bad normalization form");-        fail1:-            js_free(ctx, buf);-            return JS_EXCEPTION;-        }-        JS_FreeCString(ctx, form);-    }--    out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,-                                ctx->rt, (DynBufReallocFunc *)js_realloc_rt);-    js_free(ctx, buf);-    if (out_len < 0)-        return JS_EXCEPTION;-    val = JS_NewUTF32String(ctx, out_buf, out_len);-    js_free(ctx, out_buf);-    return val;-}-#endif /* CONFIG_ALL_UNICODE */--/* also used for String.prototype.valueOf */-static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    return js_thisStringValue(ctx, this_val);-}--#if 0-static JSValue js_string___toStringCheckObject(JSContext *ctx, JSValueConst this_val,-                                               int argc, JSValueConst *argv)-{-    return JS_ToStringCheckObject(ctx, argv[0]);-}--static JSValue js_string___toString(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    return JS_ToString(ctx, argv[0]);-}--static JSValue js_string___advanceStringIndex(JSContext *ctx, JSValueConst-                                              this_val,-                                              int argc, JSValueConst *argv)-{-    JSValue str;-    int idx;-    BOOL is_unicode;-    JSString *p;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return str;-    if (JS_ToInt32Sat(ctx, &idx, argv[1])) {-        JS_FreeValue(ctx, str);-        return JS_EXCEPTION;-    }-    is_unicode = JS_ToBool(ctx, argv[2]);-    p = JS_VALUE_GET_STRING(str);-    if (!is_unicode || (unsigned)idx >= p->len || !p->is_wide_char) {-        idx++;-    } else {-        string_getc(p, &idx);-    }-    JS_FreeValue(ctx, str);-    return JS_NewInt32(ctx, idx);-}-#endif--/* String Iterator */--static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv,-                                       BOOL *pdone, int magic)-{-    JSArrayIteratorData *it;-    uint32_t idx, c, start;-    JSString *p;--    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_STRING_ITERATOR);-    if (!it) {-        *pdone = FALSE;-        return JS_EXCEPTION;-    }-    if (JS_IsUndefined(it->obj))-        goto done;-    p = JS_VALUE_GET_STRING(it->obj);-    idx = it->idx;-    if (idx >= p->len) {-        JS_FreeValue(ctx, it->obj);-        it->obj = JS_UNDEFINED;-    done:-        *pdone = TRUE;-        return JS_UNDEFINED;-    }--    start = idx;-    c = string_getc(p, (int *)&idx);-    it->idx = idx;-    *pdone = FALSE;-    if (c <= 0xffff) {-        return js_new_string_char(ctx, c);-    } else {-        return js_new_string16(ctx, p->u.str16 + start, 2);-    }-}--/* ES6 Annex B 2.3.2 etc. */-enum {-    magic_string_anchor,-    magic_string_big,-    magic_string_blink,-    magic_string_bold,-    magic_string_fixed,-    magic_string_fontcolor,-    magic_string_fontsize,-    magic_string_italics,-    magic_string_link,-    magic_string_small,-    magic_string_strike,-    magic_string_sub,-    magic_string_sup,-};--static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv, int magic)-{-    JSValue str;-    const JSString *p;-    StringBuffer b_s, *b = &b_s;-    static struct { const char *tag, *attr; } const defs[] = {-        { "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL },-        { "tt", NULL }, { "font", "color" }, { "font", "size" }, { "i", NULL },-        { "a", "href" }, { "small", NULL }, { "strike", NULL }, -        { "sub", NULL }, { "sup", NULL },-    };--    str = JS_ToStringCheckObject(ctx, this_val);-    if (JS_IsException(str))-        return JS_EXCEPTION;-    string_buffer_init(ctx, b, 7);-    string_buffer_putc8(b, '<');-    string_buffer_puts8(b, defs[magic].tag);-    if (defs[magic].attr) {-        // r += " " + attr + "=\"" + value + "\"";-        JSValue value;-        int i;--        string_buffer_putc8(b, ' ');-        string_buffer_puts8(b, defs[magic].attr);-        string_buffer_puts8(b, "=\"");-        value = JS_ToStringCheckObject(ctx, argv[0]);-        if (JS_IsException(value)) {-            JS_FreeValue(ctx, str);-            string_buffer_free(b);-            return JS_EXCEPTION;-        }-        p = JS_VALUE_GET_STRING(value);-        for (i = 0; i < p->len; i++) {-            int c = string_get(p, i);-            if (c == '"') {-                string_buffer_puts8(b, "&quot;");-            } else {-                string_buffer_putc16(b, c);-            }-        }-        JS_FreeValue(ctx, value);-        string_buffer_putc8(b, '\"');-    }-    // return r + ">" + str + "</" + tag + ">";-    string_buffer_putc8(b, '>');-    string_buffer_concat_value_free(b, str);-    string_buffer_puts8(b, "</");-    string_buffer_puts8(b, defs[magic].tag);-    string_buffer_putc8(b, '>');-    return string_buffer_end(b);-}--static const JSCFunctionListEntry js_string_funcs[] = {-    JS_CFUNC_DEF("fromCharCode", 1, js_string_fromCharCode ),-    JS_CFUNC_DEF("fromCodePoint", 1, js_string_fromCodePoint ),-    JS_CFUNC_DEF("raw", 1, js_string_raw ),-    //JS_CFUNC_DEF("__toString", 1, js_string___toString ),-    //JS_CFUNC_DEF("__isSpace", 1, js_string___isSpace ),-    //JS_CFUNC_DEF("__toStringCheckObject", 1, js_string___toStringCheckObject ),-    //JS_CFUNC_DEF("__advanceStringIndex", 3, js_string___advanceStringIndex ),-    //JS_CFUNC_DEF("__GetSubstitution", 6, js_string___GetSubstitution ),-};--static const JSCFunctionListEntry js_string_proto_funcs[] = {-    JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ),-    JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ),-    JS_CFUNC_DEF("charAt", 1, js_string_charAt ),-    JS_CFUNC_DEF("concat", 1, js_string_concat ),-    JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),-    JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),-    JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),-    JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),-    JS_CFUNC_MAGIC_DEF("endsWith", 1, js_string_includes, 2 ),-    JS_CFUNC_MAGIC_DEF("startsWith", 1, js_string_includes, 1 ),-    JS_CFUNC_MAGIC_DEF("match", 1, js_string_match, JS_ATOM_Symbol_match ),-    JS_CFUNC_MAGIC_DEF("matchAll", 1, js_string_match, JS_ATOM_Symbol_matchAll ),-    JS_CFUNC_MAGIC_DEF("search", 1, js_string_match, JS_ATOM_Symbol_search ),-    JS_CFUNC_DEF("split", 2, js_string_split ),-    JS_CFUNC_DEF("substring", 2, js_string_substring ),-    JS_CFUNC_DEF("substr", 2, js_string_substr ),-    JS_CFUNC_DEF("slice", 2, js_string_slice ),-    JS_CFUNC_DEF("repeat", 1, js_string_repeat ),-    JS_CFUNC_MAGIC_DEF("replace", 2, js_string_replace, 0 ),-    JS_CFUNC_MAGIC_DEF("replaceAll", 2, js_string_replace, 1 ),-    JS_CFUNC_MAGIC_DEF("padEnd", 1, js_string_pad, 1 ),-    JS_CFUNC_MAGIC_DEF("padStart", 1, js_string_pad, 0 ),-    JS_CFUNC_MAGIC_DEF("trim", 0, js_string_trim, 3 ),-    JS_CFUNC_MAGIC_DEF("trimEnd", 0, js_string_trim, 2 ),-    JS_ALIAS_DEF("trimRight", "trimEnd" ),-    JS_CFUNC_MAGIC_DEF("trimStart", 0, js_string_trim, 1 ),-    JS_ALIAS_DEF("trimLeft", "trimStart" ),-    JS_CFUNC_DEF("toString", 0, js_string_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_string_toString ),-    JS_CFUNC_DEF("__quote", 1, js_string___quote ),-    JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ),-    JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ),-    JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ),-    JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ),-    JS_CFUNC_MAGIC_DEF("toLocaleUpperCase", 0, js_string_toLowerCase, 0 ),-    JS_CFUNC_MAGIC_DEF("[Symbol.iterator]", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE | 4 ),-    /* ES6 Annex B 2.3.2 etc. */-    JS_CFUNC_MAGIC_DEF("anchor", 1, js_string_CreateHTML, magic_string_anchor ),-    JS_CFUNC_MAGIC_DEF("big", 0, js_string_CreateHTML, magic_string_big ),-    JS_CFUNC_MAGIC_DEF("blink", 0, js_string_CreateHTML, magic_string_blink ),-    JS_CFUNC_MAGIC_DEF("bold", 0, js_string_CreateHTML, magic_string_bold ),-    JS_CFUNC_MAGIC_DEF("fixed", 0, js_string_CreateHTML, magic_string_fixed ),-    JS_CFUNC_MAGIC_DEF("fontcolor", 1, js_string_CreateHTML, magic_string_fontcolor ),-    JS_CFUNC_MAGIC_DEF("fontsize", 1, js_string_CreateHTML, magic_string_fontsize ),-    JS_CFUNC_MAGIC_DEF("italics", 0, js_string_CreateHTML, magic_string_italics ),-    JS_CFUNC_MAGIC_DEF("link", 1, js_string_CreateHTML, magic_string_link ),-    JS_CFUNC_MAGIC_DEF("small", 0, js_string_CreateHTML, magic_string_small ),-    JS_CFUNC_MAGIC_DEF("strike", 0, js_string_CreateHTML, magic_string_strike ),-    JS_CFUNC_MAGIC_DEF("sub", 0, js_string_CreateHTML, magic_string_sub ),-    JS_CFUNC_MAGIC_DEF("sup", 0, js_string_CreateHTML, magic_string_sup ),-};--static const JSCFunctionListEntry js_string_iterator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 0, js_string_iterator_next, 0 ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "String Iterator", JS_PROP_CONFIGURABLE ),-};--#ifdef CONFIG_ALL_UNICODE-static const JSCFunctionListEntry js_string_proto_normalize[] = {-    JS_CFUNC_DEF("normalize", 0, js_string_normalize ),-};-#endif--void JS_AddIntrinsicStringNormalize(JSContext *ctx)-{-#ifdef CONFIG_ALL_UNICODE-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize,-                               countof(js_string_proto_normalize));-#endif-}--/* Math */--/* precondition: a and b are not NaN */-static double js_fmin(double a, double b)-{-    if (a == 0 && b == 0) {-        JSFloat64Union a1, b1;-        a1.d = a;-        b1.d = b;-        a1.u64 |= b1.u64;-        return a1.d;-    } else {-        return fmin(a, b);-    }-}--/* precondition: a and b are not NaN */-static double js_fmax(double a, double b)-{-    if (a == 0 && b == 0) {-        JSFloat64Union a1, b1;-        a1.d = a;-        b1.d = b;-        a1.u64 &= b1.u64;-        return a1.d;-    } else {-        return fmax(a, b);-    }-}--static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv, int magic)-{-    BOOL is_max = magic;-    double r, a;-    int i;-    uint32_t tag;--    if (unlikely(argc == 0)) {-        return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0);-    }--    tag = JS_VALUE_GET_TAG(argv[0]);-    if (tag == JS_TAG_INT) {-        int a1, r1 = JS_VALUE_GET_INT(argv[0]);-        for(i = 1; i < argc; i++) {-            tag = JS_VALUE_GET_TAG(argv[i]);-            if (tag != JS_TAG_INT) {-                r = r1;-                goto generic_case;-            }-            a1 = JS_VALUE_GET_INT(argv[i]);-            if (is_max)-                r1 = max_int(r1, a1);-            else-                r1 = min_int(r1, a1);--        }-        return JS_NewInt32(ctx, r1);-    } else {-        if (JS_ToFloat64(ctx, &r, argv[0]))-            return JS_EXCEPTION;-        i = 1;-    generic_case:-        while (i < argc) {-            if (JS_ToFloat64(ctx, &a, argv[i]))-                return JS_EXCEPTION;-            if (!isnan(r)) {-                if (isnan(a)) {-                    r = a;-                } else {-                    if (is_max)-                        r = js_fmax(r, a);-                    else-                        r = js_fmin(r, a);-                }-            }-            i++;-        }-        return JS_NewFloat64(ctx, r);-    }-}--static double js_math_sign(double a)-{-    if (isnan(a) || a == 0.0)-        return a;-    if (a < 0)-        return -1;-    else-        return 1;-}--static double js_math_round(double a)-{-    JSFloat64Union u;-    uint64_t frac_mask, one;-    unsigned int e, s;--    u.d = a;-    e = (u.u64 >> 52) & 0x7ff;-    if (e < 1023) {-        /* abs(a) < 1 */-        if (e == (1023 - 1) && u.u64 != 0xbfe0000000000000) {-            /* abs(a) > 0.5 or a = 0.5: return +/-1.0 */-            u.u64 = (u.u64 & ((uint64_t)1 << 63)) | ((uint64_t)1023 << 52);-        } else {-            /* return +/-0.0 */-            u.u64 &= (uint64_t)1 << 63;-        }-    } else if (e < (1023 + 52)) {-        s = u.u64 >> 63;-        one = (uint64_t)1 << (52 - (e - 1023));-        frac_mask = one - 1;-        u.u64 += (one >> 1) - s;-        u.u64 &= ~frac_mask; /* truncate to an integer */-    }-    /* otherwise: abs(a) >= 2^52, or NaN, +/-Infinity: no change */-    return u.d;-}--static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    double r, a;-    int i;--    r = 0;-    if (argc > 0) {-        if (JS_ToFloat64(ctx, &r, argv[0]))-            return JS_EXCEPTION;-        if (argc == 1) {-            r = fabs(r);-        } else {-            /* use the built-in function to minimize precision loss */-            for (i = 1; i < argc; i++) {-                if (JS_ToFloat64(ctx, &a, argv[i]))-                    return JS_EXCEPTION;-                r = hypot(r, a);-            }-        }-    }-    return JS_NewFloat64(ctx, r);-}--static double js_math_fround(double a)-{-    return (float)a;-}--static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,-                            int argc, JSValueConst *argv)-{-    int a, b;--    if (JS_ToInt32(ctx, &a, argv[0]))-        return JS_EXCEPTION;-    if (JS_ToInt32(ctx, &b, argv[1]))-        return JS_EXCEPTION;-    /* purposely ignoring overflow */-    return JS_NewInt32(ctx, a * b);-}--static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    uint32_t a, r;--    if (JS_ToUint32(ctx, &a, argv[0]))-        return JS_EXCEPTION;-    if (a == 0)-        r = 32;-    else-        r = clz32(a);-    return JS_NewInt32(ctx, r);-}--/* xorshift* random number generator by Marsaglia */-static uint64_t xorshift64star(uint64_t *pstate)-{-    uint64_t x;-    x = *pstate;-    x ^= x >> 12;-    x ^= x << 25;-    x ^= x >> 27;-    *pstate = x;-    return x * 0x2545F4914F6CDD1D;-}--static void js_random_init(JSContext *ctx)-{-    struct timeval tv;-    gettimeofday(&tv, NULL);-    ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;-    /* the state must be non zero */-    if (ctx->random_state == 0)-        ctx->random_state = 1;-}--static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSFloat64Union u;-    uint64_t v;--    v = xorshift64star(&ctx->random_state);-    /* 1.0 <= u.d < 2 */-    u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);-    return __JS_NewFloat64(ctx, u.d - 1.0);-}--static const JSCFunctionListEntry js_math_funcs[] = {-    JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),-    JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),-    JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),-    JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ),-    JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ),-    JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),-    JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),--    JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, acos ),-    JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, asin ),-    JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, atan ),-    JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, atan2 ),-    JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, cos ),-    JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, exp ),-    JS_CFUNC_SPECIAL_DEF("log", 1, f_f, log ),-    JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_pow ),-    JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, sin ),-    JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, tan ),-    /* ES6 */-    JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, trunc ),-    JS_CFUNC_SPECIAL_DEF("sign", 1, f_f, js_math_sign ),-    JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, cosh ),-    JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, sinh ),-    JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, tanh ),-    JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, acosh ),-    JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, asinh ),-    JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ),-    JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ),-    JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ),-    JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2 ),-    JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ),-    JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),-    JS_CFUNC_DEF("hypot", 2, js_math_hypot ),-    JS_CFUNC_DEF("random", 0, js_math_random ),-    JS_CFUNC_SPECIAL_DEF("fround", 1, f_f, js_math_fround ),-    JS_CFUNC_DEF("imul", 2, js_math_imul ),-    JS_CFUNC_DEF("clz32", 1, js_math_clz32 ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Math", JS_PROP_CONFIGURABLE ),-    JS_PROP_DOUBLE_DEF("E", 2.718281828459045, 0 ),-    JS_PROP_DOUBLE_DEF("LN10", 2.302585092994046, 0 ),-    JS_PROP_DOUBLE_DEF("LN2", 0.6931471805599453, 0 ),-    JS_PROP_DOUBLE_DEF("LOG2E", 1.4426950408889634, 0 ),-    JS_PROP_DOUBLE_DEF("LOG10E", 0.4342944819032518, 0 ),-    JS_PROP_DOUBLE_DEF("PI", 3.141592653589793, 0 ),-    JS_PROP_DOUBLE_DEF("SQRT1_2", 0.7071067811865476, 0 ),-    JS_PROP_DOUBLE_DEF("SQRT2", 1.4142135623730951, 0 ),-};--static const JSCFunctionListEntry js_math_obj[] = {-    JS_OBJECT_DEF("Math", js_math_funcs, countof(js_math_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),-};--/* Date */--#if 0-/* OS dependent: return the UTC time in ms since 1970. */-static JSValue js___date_now(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    int64_t d;-    struct timeval tv;-    gettimeofday(&tv, NULL);-    d = (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);-    return JS_NewInt64(ctx, d);-}-#endif--/* OS dependent: return the UTC time in microseconds since 1970. */-static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    int64_t d;-    struct timeval tv;-    gettimeofday(&tv, NULL);-    d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;-    return JS_NewInt64(ctx, d);-}--/* OS dependent. d = argv[0] is in ms from 1970. Return the difference-   between local time and UTC time 'd' in minutes */-static int getTimezoneOffset(int64_t time) {-#if defined(_WIN32)-    /* XXX: TODO */-    return 0;-#else-    time_t ti;-    struct tm tm;--    time /= 1000; /* convert to seconds */-    if (sizeof(time_t) == 4) {-        /* on 32-bit systems, we need to clamp the time value to the-           range of `time_t`. This is better than truncating values to-           32 bits and hopefully provides the same result as 64-bit-           implementation of localtime_r.-         */-        if ((time_t)-1 < 0) {-            if (time < INT32_MIN) {-                time = INT32_MIN;-            } else if (time > INT32_MAX) {-                time = INT32_MAX;-            }-        } else {-            if (time < 0) {-                time = 0;-            } else if (time > UINT32_MAX) {-                time = UINT32_MAX;-            }-        }-    }-    ti = time;-    localtime_r(&ti, &tm);-    return -tm.tm_gmtoff / 60;-#endif-}--#if 0-static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,-                                           int argc, JSValueConst *argv)-{-    double dd;--    if (JS_ToFloat64(ctx, &dd, argv[0]))-        return JS_EXCEPTION;-    if (isnan(dd))-        return __JS_NewFloat64(ctx, dd);-    else-        return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));-}--static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor,-                                          JSValueConst def_proto)-{-    JSValue proto;-    proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);-    if (JS_IsException(proto))-        return proto;-    if (!JS_IsObject(proto)) {-        JS_FreeValue(ctx, proto);-        proto = JS_DupValue(ctx, def_proto);-    }-    return proto;-}--/* create a new date object */-static JSValue js___date_create(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue obj, proto;-    proto = js_get_prototype_from_ctor(ctx, argv[0], argv[1]);-    if (JS_IsException(proto))-        return proto;-    obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_DATE);-    JS_FreeValue(ctx, proto);-    if (!JS_IsException(obj))-        JS_SetObjectData(ctx, obj, JS_DupValue(ctx, argv[2]));-    return obj;-}-#endif--/* RegExp */--static void js_regexp_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSRegExp *re = &p->u.regexp;-    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->bytecode));-    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->pattern));-}--/* create a string containing the RegExp bytecode */-static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,-                                 JSValueConst flags)-{-    const char *str;-    int re_flags, mask;-    uint8_t *re_bytecode_buf;-    size_t i, len;-    int re_bytecode_len;-    JSValue ret;-    char error_msg[64];--    re_flags = 0;-    if (!JS_IsUndefined(flags)) {-        str = JS_ToCStringLen(ctx, &len, flags);-        if (!str)-            return JS_EXCEPTION;-        /* XXX: re_flags = LRE_FLAG_OCTAL unless strict mode? */-        for (i = 0; i < len; i++) {-            switch(str[i]) {-            case 'g':-                mask = LRE_FLAG_GLOBAL;-                break;-            case 'i':-                mask = LRE_FLAG_IGNORECASE;-                break;-            case 'm':-                mask = LRE_FLAG_MULTILINE;-                break;-            case 's':-                mask = LRE_FLAG_DOTALL;-                break;-            case 'u':-                mask = LRE_FLAG_UTF16;-                break;-            case 'y':-                mask = LRE_FLAG_STICKY;-                break;-            default:-                goto bad_flags;-            }-            if ((re_flags & mask) != 0) {-            bad_flags:-                JS_FreeCString(ctx, str);-                return JS_ThrowSyntaxError(ctx, "invalid regular expression flags");-            }-            re_flags |= mask;-        }-        JS_FreeCString(ctx, str);-    }--    str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16));-    if (!str)-        return JS_EXCEPTION;-    re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg,-                                  sizeof(error_msg), str, len, re_flags, ctx);-    JS_FreeCString(ctx, str);-    if (!re_bytecode_buf) {-        JS_ThrowSyntaxError(ctx, "%s", error_msg);-        return JS_EXCEPTION;-    }--    ret = js_new_string8(ctx, re_bytecode_buf, re_bytecode_len);-    js_free(ctx, re_bytecode_buf);-    return ret;-}--/* create a RegExp object from a string containing the RegExp bytecode-   and the source pattern */-static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,-                                              JSValue pattern, JSValue bc)-{-    JSValue obj;-    JSObject *p;-    JSRegExp *re;--    /* sanity check */-    if (JS_VALUE_GET_TAG(bc) != JS_TAG_STRING ||-        JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING) {-        JS_ThrowTypeError(ctx, "string expected");-    fail:-        JS_FreeValue(ctx, bc);-        JS_FreeValue(ctx, pattern);-        return JS_EXCEPTION;-    }--    obj = js_create_from_ctor(ctx, ctor, JS_CLASS_REGEXP);-    if (JS_IsException(obj))-        goto fail;-    p = JS_VALUE_GET_OBJ(obj);-    re = &p->u.regexp;-    re->pattern = JS_VALUE_GET_STRING(pattern);-    re->bytecode = JS_VALUE_GET_STRING(bc);-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0),-                           JS_PROP_WRITABLE);-    return obj;-}--static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_error)-{-    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(obj);-        if (p->class_id == JS_CLASS_REGEXP)-            return &p->u.regexp;-    }-    if (throw_error) {-        JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);-    }-    return NULL;-}--/* return < 0 if exception or TRUE/FALSE */-static int js_is_regexp(JSContext *ctx, JSValueConst obj)-{-    JSValue m;--    if (!JS_IsObject(obj))-        return FALSE;-    m = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_match);-    if (JS_IsException(m))-        return -1;-    if (!JS_IsUndefined(m))-        return JS_ToBoolFree(ctx, m);-    return js_get_regexp(ctx, obj, FALSE) != NULL;-}--static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue pattern, flags, bc, val;-    JSValueConst pat, flags1;-    JSRegExp *re;-    int pat_is_regexp;--    pat = argv[0];-    flags1 = argv[1];-    pat_is_regexp = js_is_regexp(ctx, pat);-    if (pat_is_regexp < 0)-        return JS_EXCEPTION;-    if (JS_IsUndefined(new_target)) {-        /* called as a function */-        new_target = JS_GetActiveFunction(ctx);-        if (pat_is_regexp && JS_IsUndefined(flags1)) {-            JSValue ctor;-            BOOL res;-            ctor = JS_GetProperty(ctx, pat, JS_ATOM_constructor);-            if (JS_IsException(ctor))-                return ctor;-            res = js_same_value(ctx, ctor, new_target);-            JS_FreeValue(ctx, ctor);-            if (res)-                return JS_DupValue(ctx, pat);-        }-    }-    re = js_get_regexp(ctx, pat, FALSE);-    if (re) {-        pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));-        if (JS_IsUndefined(flags1)) {-            bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode));-            goto no_compilation;-        } else {-            flags = JS_ToString(ctx, flags1);-            if (JS_IsException(flags))-                goto fail;-        }-    } else {-        flags = JS_UNDEFINED;-        if (pat_is_regexp) {-            pattern = JS_GetProperty(ctx, pat, JS_ATOM_source);-            if (JS_IsException(pattern))-                goto fail;-            if (JS_IsUndefined(flags1)) {-                flags = JS_GetProperty(ctx, pat, JS_ATOM_flags);-                if (JS_IsException(flags))-                    goto fail;-            } else {-                flags = JS_DupValue(ctx, flags1);-            }-        } else {-            pattern = JS_DupValue(ctx, pat);-            flags = JS_DupValue(ctx, flags1);-        }-        if (JS_IsUndefined(pattern)) {-            pattern = JS_AtomToString(ctx, JS_ATOM_empty_string);-        } else {-            val = pattern;-            pattern = JS_ToString(ctx, val);-            JS_FreeValue(ctx, val);-            if (JS_IsException(pattern))-                goto fail;-        }-    }-    bc = js_compile_regexp(ctx, pattern, flags);-    if (JS_IsException(bc))-        goto fail;-    JS_FreeValue(ctx, flags);- no_compilation:-    return js_regexp_constructor_internal(ctx, new_target, pattern, bc);- fail:-    JS_FreeValue(ctx, pattern);-    JS_FreeValue(ctx, flags);-    return JS_EXCEPTION;-}--static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSRegExp *re1, *re;-    JSValueConst pattern1, flags1;-    JSValue bc, pattern;--    re = js_get_regexp(ctx, this_val, TRUE);-    if (!re)-        return JS_EXCEPTION;-    pattern1 = argv[0];-    flags1 = argv[1];-    re1 = js_get_regexp(ctx, pattern1, FALSE);-    if (re1) {-        if (!JS_IsUndefined(flags1))-            return JS_ThrowTypeError(ctx, "flags must be undefined");-        pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->pattern));-        bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->bytecode));-    } else {-        bc = JS_UNDEFINED;-        if (JS_IsUndefined(pattern1))-            pattern = JS_AtomToString(ctx, JS_ATOM_empty_string);-        else-            pattern = JS_ToString(ctx, pattern1);-        if (JS_IsException(pattern))-            goto fail;-        bc = js_compile_regexp(ctx, pattern, flags1);-        if (JS_IsException(bc))-            goto fail;-    }-    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));-    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode));-    re->pattern = JS_VALUE_GET_STRING(pattern);-    re->bytecode = JS_VALUE_GET_STRING(bc);-    if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,-                       JS_NewInt32(ctx, 0)) < 0)-        return JS_EXCEPTION;-    return JS_DupValue(ctx, this_val);- fail:-    JS_FreeValue(ctx, pattern);-    JS_FreeValue(ctx, bc);-    return JS_EXCEPTION;-}--#if 0-static JSValue js_regexp_get___source(JSContext *ctx, JSValueConst this_val)-{-    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);-    if (!re)-        return JS_EXCEPTION;-    return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));-}--static JSValue js_regexp_get___flags(JSContext *ctx, JSValueConst this_val)-{-    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);-    int flags;--    if (!re)-        return JS_EXCEPTION;-    flags = lre_get_flags(re->bytecode->u.str8);-    return JS_NewInt32(ctx, flags);-}-#endif--static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)-{-    JSRegExp *re;-    JSString *p;-    StringBuffer b_s, *b = &b_s;-    int i, n, c, c2, bra;--    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);--    if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))-        goto empty_regex;--    re = js_get_regexp(ctx, this_val, TRUE);-    if (!re)-        return JS_EXCEPTION;--    p = re->pattern;--    if (p->len == 0) {-    empty_regex:-        return JS_NewString(ctx, "(?:)");-    }    -    string_buffer_init2(ctx, b, p->len, p->is_wide_char);--    /* Escape '/' and newline sequences as needed */-    bra = 0;-    for (i = 0, n = p->len; i < n;) {-        c2 = -1;-        switch (c = string_get(p, i++)) {-        case '\\':-            if (i < n)-                c2 = string_get(p, i++);-            break;-        case ']':-            bra = 0;-            break;-        case '[':-            if (!bra) {-                if (i < n && string_get(p, i) == ']')-                    c2 = string_get(p, i++);-                bra = 1;-            }-            break;-        case '\n':-            c = '\\';-            c2 = 'n';-            break;-        case '\r':-            c = '\\';-            c2 = 'r';-            break;-        case '/':-            if (!bra) {-                c = '\\';-                c2 = '/';-            }-            break;-        }-        string_buffer_putc16(b, c);-        if (c2 >= 0)-            string_buffer_putc16(b, c2);-    }-    return string_buffer_end(b);-}--static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mask)-{-    JSRegExp *re;-    int flags;--    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);--    re = js_get_regexp(ctx, this_val, FALSE);-    if (!re) {-        if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))-            return JS_UNDEFINED;-        else-            return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);-    }-    -    flags = lre_get_flags(re->bytecode->u.str8);-    return JS_NewBool(ctx, (flags & mask) != 0);-}--static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)-{-    char str[8], *p = str;-    int res;--    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);--    res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 'g';-    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "ignoreCase"));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 'i';-    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "multiline"));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 'm';-    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "dotAll"));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 's';-    res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_unicode));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 'u';-    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "sticky"));-    if (res < 0)-        goto exception;-    if (res)-        *p++ = 'y';-    return JS_NewStringLen(ctx, str, p - str);--exception:-    return JS_EXCEPTION;-}--static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValue pattern, flags;-    StringBuffer b_s, *b = &b_s;--    if (!JS_IsObject(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    string_buffer_init(ctx, b, 0);-    string_buffer_putc8(b, '/');-    pattern = JS_GetProperty(ctx, this_val, JS_ATOM_source);-    if (string_buffer_concat_value_free(b, pattern))-        goto fail;-    string_buffer_putc8(b, '/');-    flags = JS_GetProperty(ctx, this_val, JS_ATOM_flags);-    if (string_buffer_concat_value_free(b, flags))-        goto fail;-    return string_buffer_end(b);--fail:-    string_buffer_free(b);-    return JS_EXCEPTION;-}--BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)-{-    JSContext *ctx = opaque;-    return js_check_stack_overflow(ctx->rt, alloca_size);-}--void *lre_realloc(void *opaque, void *ptr, size_t size)-{-    JSContext *ctx = opaque;-    /* No JS exception is raised here */-    return js_realloc_rt(ctx->rt, ptr, size);-}--static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);-    JSString *str;-    JSValue str_val, obj, val, groups = JS_UNDEFINED;-    uint8_t *re_bytecode;-    int ret;-    uint8_t **capture, *str_buf;-    int capture_count, shift, i, re_flags;-    int64_t last_index;-    const char *group_name_ptr;--    if (!re)-        return JS_EXCEPTION;-    str_val = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str_val))-        return str_val;-    val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);-    if (JS_IsException(val) ||-        JS_ToLengthFree(ctx, &last_index, val)) {-        JS_FreeValue(ctx, str_val);-        return JS_EXCEPTION;-    }-    re_bytecode = re->bytecode->u.str8;-    re_flags = lre_get_flags(re_bytecode);-    if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {-        last_index = 0;-    }-    str = JS_VALUE_GET_STRING(str_val);-    capture_count = lre_get_capture_count(re_bytecode);-    capture = NULL;-    if (capture_count > 0) {-        capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);-        if (!capture) {-            JS_FreeValue(ctx, str_val);-            return JS_EXCEPTION;-        }-    }-    shift = str->is_wide_char;-    str_buf = str->u.str8;-    if (last_index > str->len) {-        ret = 2;-    } else {-        ret = lre_exec(capture, re_bytecode,-                       str_buf, last_index, str->len,-                       shift, ctx);-    }-    obj = JS_NULL;-    if (ret != 1) {-        if (ret >= 0) {-            if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {-                if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,-                                   JS_NewInt32(ctx, 0)) < 0)-                    goto fail;-            }-        } else {-            JS_ThrowInternalError(ctx, "out of memory in regexp execution");-            goto fail;-        }-        JS_FreeValue(ctx, str_val);-    } else {-        int prop_flags;-        if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) {-            if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,-                               JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0)-                goto fail;-        }-        obj = JS_NewArray(ctx);-        if (JS_IsException(obj))-            goto fail;-        prop_flags = JS_PROP_C_W_E | JS_PROP_THROW;-        group_name_ptr = lre_get_groupnames(re_bytecode);-        if (group_name_ptr) {-            groups = JS_NewObjectProto(ctx, JS_NULL);-            if (JS_IsException(groups))-                goto fail;-        }--        for(i = 0; i < capture_count; i++) {-            int start, end;-            JSValue val;-            if (capture[2 * i] == NULL ||-                capture[2 * i + 1] == NULL) {-                val = JS_UNDEFINED;-            } else {-                start = (capture[2 * i] - str_buf) >> shift;-                end = (capture[2 * i + 1] - str_buf) >> shift;-                val = js_sub_string(ctx, str, start, end);-                if (JS_IsException(val))-                    goto fail;-            }-            if (group_name_ptr && i > 0) {-                if (*group_name_ptr) {-                    if (JS_DefinePropertyValueStr(ctx, groups, group_name_ptr,-                                                  JS_DupValue(ctx, val),-                                                  prop_flags) < 0) {-                        JS_FreeValue(ctx, val);-                        goto fail;-                    }-                }-                group_name_ptr += strlen(group_name_ptr) + 1;-            }-            if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0)-                goto fail;-        }-        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups,-                                   groups, prop_flags) < 0)-            goto fail;-        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index,-                                   JS_NewInt32(ctx, (capture[0] - str_buf) >> shift), prop_flags) < 0)-            goto fail;-        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, str_val, prop_flags) < 0)-            goto fail1;-    }-    js_free(ctx, capture);-    return obj;-fail:-    JS_FreeValue(ctx, groups);-    JS_FreeValue(ctx, str_val);-fail1:-    JS_FreeValue(ctx, obj);-    js_free(ctx, capture);-    return JS_EXCEPTION;-}--/* delete portions of a string that match a given regex */-static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg)-{-    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);-    JSString *str;-    JSValue str_val, val;-    uint8_t *re_bytecode;-    int ret;-    uint8_t **capture, *str_buf;-    int capture_count, shift, re_flags;-    int next_src_pos, start, end;-    int64_t last_index;-    StringBuffer b_s, *b = &b_s;--    if (!re)-        return JS_EXCEPTION;--    string_buffer_init(ctx, b, 0);--    capture = NULL;-    str_val = JS_ToString(ctx, arg);-    if (JS_IsException(str_val))-        goto fail;-    str = JS_VALUE_GET_STRING(str_val);-    re_bytecode = re->bytecode->u.str8;-    re_flags = lre_get_flags(re_bytecode);-    if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {-        last_index = 0;-    } else {-        val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);-        if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val))-            goto fail;-    }-    capture_count = lre_get_capture_count(re_bytecode);-    if (capture_count > 0) {-        capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);-        if (!capture)-            goto fail;-    }-    shift = str->is_wide_char;-    str_buf = str->u.str8;-    next_src_pos = 0;-    for (;;) {-        if (last_index > str->len)-            break;--        ret = lre_exec(capture, re_bytecode,-                       str_buf, last_index, str->len, shift, ctx);-        if (ret != 1) {-            if (ret >= 0) {-                if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {-                    if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,-                                       JS_NewInt32(ctx, 0)) < 0)-                        goto fail;-                }-            } else {-                JS_ThrowInternalError(ctx, "out of memory in regexp execution");-                goto fail;-            }-            break;-        }-        start = (capture[0] - str_buf) >> shift;-        end = (capture[1] - str_buf) >> shift;-        last_index = end;-        if (next_src_pos < start) {-            if (string_buffer_concat(b, str, next_src_pos, start))-                goto fail;-        }-        next_src_pos = end;-        if (!(re_flags & LRE_FLAG_GLOBAL)) {-            if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,-                               JS_NewInt32(ctx, end)) < 0)-                goto fail;-            break;-        }-        if (end == start) {-            if (!(re_flags & LRE_FLAG_UTF16) || (unsigned)end >= str->len || !str->is_wide_char) {-                end++;-            } else {-                string_getc(str, &end);-            }-        }-        last_index = end;-    }-    if (string_buffer_concat(b, str, next_src_pos, str->len))-        goto fail;-    JS_FreeValue(ctx, str_val);-    js_free(ctx, capture);-    return string_buffer_end(b);-fail:-    JS_FreeValue(ctx, str_val);-    js_free(ctx, capture);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)-{-    JSValue method, ret;--    method = JS_GetProperty(ctx, r, JS_ATOM_exec);-    if (JS_IsException(method))-        return method;-    if (JS_IsFunction(ctx, method)) {-        ret = JS_CallFree(ctx, method, r, 1, &s);-        if (JS_IsException(ret))-            return ret;-        if (!JS_IsObject(ret) && !JS_IsNull(ret)) {-            JS_FreeValue(ctx, ret);-            return JS_ThrowTypeError(ctx, "RegExp exec method must return an object or null");-        }-        return ret;-    }-    JS_FreeValue(ctx, method);-    return js_regexp_exec(ctx, r, 1, &s);-}--#if 0-static JSValue js_regexp___RegExpExec(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    return JS_RegExpExec(ctx, argv[0], argv[1]);-}-static JSValue js_regexp___RegExpDelete(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    return JS_RegExpDelete(ctx, argv[0], argv[1]);-}-#endif--static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSValue val;-    BOOL ret;--    val = JS_RegExpExec(ctx, this_val, argv[0]);-    if (JS_IsException(val))-        return JS_EXCEPTION;-    ret = !JS_IsNull(val);-    JS_FreeValue(ctx, val);-    return JS_NewBool(ctx, ret);-}--static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    // [Symbol.match](str)-    JSValueConst rx = this_val;-    JSValue A, S, result, matchStr;-    int global, n, fullUnicode, isEmpty;-    JSString *p;--    if (!JS_IsObject(rx))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    A = JS_UNDEFINED;-    result = JS_UNDEFINED;-    matchStr = JS_UNDEFINED;-    S = JS_ToString(ctx, argv[0]);-    if (JS_IsException(S))-        goto exception;--    global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));-    if (global < 0)-        goto exception;--    if (!global) {-        A = JS_RegExpExec(ctx, rx, S);-    } else {-        fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));-        if (fullUnicode < 0)-            goto exception;--        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)-            goto exception;-        A = JS_NewArray(ctx);-        if (JS_IsException(A))-            goto exception;-        n = 0;-        for(;;) {-            JS_FreeValue(ctx, result);-            result = JS_RegExpExec(ctx, rx, S);-            if (JS_IsException(result))-                goto exception;-            if (JS_IsNull(result))-                break;-            matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));-            if (JS_IsException(matchStr))-                goto exception;-            isEmpty = JS_IsEmptyString(matchStr);-            if (JS_SetPropertyInt64(ctx, A, n++, matchStr) < 0)-                goto exception;-            if (isEmpty) {-                int64_t thisIndex, nextIndex;-                if (JS_ToLengthFree(ctx, &thisIndex,-                                    JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)-                    goto exception;-                p = JS_VALUE_GET_STRING(S);-                nextIndex = string_advance_index(p, thisIndex, fullUnicode);-                if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)-                    goto exception;-            }-        }-        if (n == 0) {-            JS_FreeValue(ctx, A);-            A = JS_NULL;-        }-    }-    JS_FreeValue(ctx, result);-    JS_FreeValue(ctx, S);-    return A;--exception:-    JS_FreeValue(ctx, A);-    JS_FreeValue(ctx, result);-    JS_FreeValue(ctx, S);-    return JS_EXCEPTION;-}--typedef struct JSRegExpStringIteratorData {-    JSValue iterating_regexp;-    JSValue iterated_string;-    BOOL global;-    BOOL unicode;-    BOOL done;-} JSRegExpStringIteratorData;--static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data;-    if (it) {-        JS_FreeValueRT(rt, it->iterating_regexp);-        JS_FreeValueRT(rt, it->iterated_string);-        js_free_rt(rt, it);-    }-}--static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,-                                           JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data;-    if (it) {-        JS_MarkValue(rt, it->iterating_regexp, mark_func);-        JS_MarkValue(rt, it->iterated_string, mark_func);-    }-}--static JSValue js_regexp_string_iterator_next(JSContext *ctx,-                                              JSValueConst this_val,-                                              int argc, JSValueConst *argv,-                                              BOOL *pdone, int magic)-{-    JSRegExpStringIteratorData *it;-    JSValueConst R, S;-    JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED;-    JSString *sp;--    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_REGEXP_STRING_ITERATOR);-    if (!it)-        goto exception;-    if (it->done) {-        *pdone = TRUE;-        return JS_UNDEFINED;-    }-    R = it->iterating_regexp;-    S = it->iterated_string;-    match = JS_RegExpExec(ctx, R, S);-    if (JS_IsException(match))-        goto exception;-    if (JS_IsNull(match)) {-        it->done = TRUE;-        *pdone = TRUE;-        return JS_UNDEFINED;-    } else if (it->global) {-        matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, match, 0));-        if (JS_IsException(matchStr))-            goto exception;-        if (JS_IsEmptyString(matchStr)) {-            int64_t thisIndex, nextIndex;-            if (JS_ToLengthFree(ctx, &thisIndex,-                                JS_GetProperty(ctx, R, JS_ATOM_lastIndex)) < 0)-                goto exception;-            sp = JS_VALUE_GET_STRING(S);-            nextIndex = string_advance_index(sp, thisIndex, it->unicode);-            if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex,-                               JS_NewInt64(ctx, nextIndex)) < 0)-                goto exception;-        }-        JS_FreeValue(ctx, matchStr);-    } else {-        it->done = TRUE;-    }-    *pdone = FALSE;-    return match;- exception:-    JS_FreeValue(ctx, match);-    JS_FreeValue(ctx, matchStr);-    *pdone = FALSE;-    return JS_EXCEPTION;-}--static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    // [Symbol.matchAll](str)-    JSValueConst R = this_val;-    JSValue S, C, flags, matcher, iter;-    JSValueConst args[2];-    JSString *strp;-    int64_t lastIndex;-    JSRegExpStringIteratorData *it;-    -    if (!JS_IsObject(R))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    C = JS_UNDEFINED;-    flags = JS_UNDEFINED;-    matcher = JS_UNDEFINED;-    iter = JS_UNDEFINED;-    -    S = JS_ToString(ctx, argv[0]);-    if (JS_IsException(S))-        goto exception;-    C = JS_SpeciesConstructor(ctx, R, ctx->regexp_ctor);-    if (JS_IsException(C))-        goto exception;-    flags = JS_ToStringFree(ctx, JS_GetProperty(ctx, R, JS_ATOM_flags));-    if (JS_IsException(flags))-        goto exception;-    args[0] = R;-    args[1] = flags;-    matcher = JS_CallConstructor(ctx, C, 2, args);-    if (JS_IsException(matcher))-        goto exception;-    if (JS_ToLengthFree(ctx, &lastIndex,-                        JS_GetProperty(ctx, R, JS_ATOM_lastIndex)))-        goto exception;-    if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex,-                       JS_NewInt64(ctx, lastIndex)) < 0)-        goto exception;-    -    iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR);-    if (JS_IsException(iter))-        goto exception;-    it = js_malloc(ctx, sizeof(*it));-    if (!it)-        goto exception;-    it->iterating_regexp = matcher;-    it->iterated_string = S;-    strp = JS_VALUE_GET_STRING(flags);-    it->global = string_indexof_char(strp, 'g', 0) >= 0;-    it->unicode = string_indexof_char(strp, 'u', 0) >= 0;-    it->done = FALSE;-    JS_SetOpaque(iter, it);--    JS_FreeValue(ctx, C);-    JS_FreeValue(ctx, flags);-    return iter;- exception:-    JS_FreeValue(ctx, S);-    JS_FreeValue(ctx, C);-    JS_FreeValue(ctx, flags);-    JS_FreeValue(ctx, matcher);-    JS_FreeValue(ctx, iter);-    return JS_EXCEPTION;-}--typedef struct ValueBuffer {-    JSContext *ctx;-    JSValue *arr;-    JSValue def[4];-    int len;-    int size;-    int error_status;-} ValueBuffer;--static int value_buffer_init(JSContext *ctx, ValueBuffer *b)-{-    b->ctx = ctx;-    b->len = 0;-    b->size = 4;-    b->error_status = 0;-    b->arr = b->def;-    return 0;-}--static void value_buffer_free(ValueBuffer *b)-{-    while (b->len > 0)-        JS_FreeValue(b->ctx, b->arr[--b->len]);-    if (b->arr != b->def)-        js_free(b->ctx, b->arr);-    b->arr = b->def;-    b->size = 4;-}--static int value_buffer_append(ValueBuffer *b, JSValue val)-{-    if (b->error_status)-        return -1;--    if (b->len >= b->size) {-        int new_size = (b->len + (b->len >> 1) + 31) & ~16;-        size_t slack;-        JSValue *new_arr;--        if (b->arr == b->def) {-            new_arr = js_realloc2(b->ctx, NULL, sizeof(*b->arr) * new_size, &slack);-            if (new_arr)-                memcpy(new_arr, b->def, sizeof b->def);-        } else {-            new_arr = js_realloc2(b->ctx, b->arr, sizeof(*b->arr) * new_size, &slack);-        }-        if (!new_arr) {-            value_buffer_free(b);-            JS_FreeValue(b->ctx, val);-            b->error_status = -1;-            return -1;-        }-        new_size += slack / sizeof(*new_arr);-        b->arr = new_arr;-        b->size = new_size;-    }-    b->arr[b->len++] = val;-    return 0;-}--static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx)-{-    JSValue val;-    int res;--    val = JS_GetProperty(ctx, rx, JS_ATOM_constructor);-    if (JS_IsException(val))-        return -1;-    // rx.constructor === RegExp-    res = js_same_value(ctx, val, ctx->regexp_ctor);-    JS_FreeValue(ctx, val);-    if (res) {-        val = JS_GetProperty(ctx, rx, JS_ATOM_exec);-        if (JS_IsException(val))-            return -1;-        // rx.exec === RE_exec-        res = JS_IsCFunction(ctx, val, js_regexp_exec, 0);-        JS_FreeValue(ctx, val);-    }-    return res;-}--static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    // [Symbol.replace](str, rep)-    JSValueConst rx = this_val, rep = argv[1];-    JSValueConst args[6];-    JSValue str, rep_val, matched, tab, rep_str, namedCaptures, res;-    JSString *sp, *rp;-    StringBuffer b_s, *b = &b_s;-    ValueBuffer v_b, *results = &v_b;-    int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode;-    uint32_t nCaptures;-    int64_t position;--    if (!JS_IsObject(rx))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    string_buffer_init(ctx, b, 0);-    value_buffer_init(ctx, results);--    rep_val = JS_UNDEFINED;-    matched = JS_UNDEFINED;-    tab = JS_UNDEFINED;-    rep_str = JS_UNDEFINED;-    namedCaptures = JS_UNDEFINED;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        goto exception;-        -    sp = JS_VALUE_GET_STRING(str);-    rp = NULL;-    functionalReplace = JS_IsFunction(ctx, rep);-    if (!functionalReplace) {-        rep_val = JS_ToString(ctx, rep);-        if (JS_IsException(rep_val))-            goto exception;-        rp = JS_VALUE_GET_STRING(rep_val);-    }-    fullUnicode = 0;-    is_global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));-    if (is_global < 0)-        goto exception;-    if (is_global) {-        fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));-        if (fullUnicode < 0)-            goto exception;-        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)-            goto exception;-    }--    if (rp && rp->len == 0 && is_global && js_is_standard_regexp(ctx, rx)) {-        /* use faster version for simple cases */-        res = JS_RegExpDelete(ctx, rx, str);-        goto done;-    }-    for(;;) {-        JSValue result;-        result = JS_RegExpExec(ctx, rx, str);-        if (JS_IsException(result))-            goto exception;-        if (JS_IsNull(result))-            break;-        if (value_buffer_append(results, result) < 0)-            goto exception;-        if (!is_global)-            break;-        JS_FreeValue(ctx, matched);-        matched = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));-        if (JS_IsException(matched))-            goto exception;-        if (JS_IsEmptyString(matched)) {-            /* always advance of at least one char */-            int64_t thisIndex, nextIndex;-            if (JS_ToLengthFree(ctx, &thisIndex, JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)-                goto exception;-            nextIndex = string_advance_index(sp, thisIndex, fullUnicode);-            if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)-                goto exception;-        }-    }-    nextSourcePosition = 0;-    for(j = 0; j < results->len; j++) {-        JSValueConst result;-        result = results->arr[j];-        if (js_get_length32(ctx, &nCaptures, result) < 0)-            goto exception;-        JS_FreeValue(ctx, matched);-        matched = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));-        if (JS_IsException(matched))-            goto exception;-        if (JS_ToLengthFree(ctx, &position, JS_GetProperty(ctx, result, JS_ATOM_index)))-            goto exception;-        if (position > sp->len)-            position = sp->len;-        else if (position < 0)-            position = 0;-        /* ignore substition if going backward (can happen-           with custom regexp object) */-        JS_FreeValue(ctx, tab);-        tab = JS_NewArray(ctx);-        if (JS_IsException(tab))-            goto exception;-        if (JS_SetPropertyInt64(ctx, tab, 0, JS_DupValue(ctx, matched)) < 0)-            goto exception;-        for(n = 1; n < nCaptures; n++) {-            JSValue capN;-            capN = JS_GetPropertyInt64(ctx, result, n);-            if (JS_IsException(capN))-                goto exception;-            if (!JS_IsUndefined(capN)) {-                capN = JS_ToStringFree(ctx, capN);-                if (JS_IsException(capN))-                    goto exception;-            }-            if (JS_SetPropertyInt64(ctx, tab, n, capN) < 0)-                goto exception;-        }-        JS_FreeValue(ctx, namedCaptures);-        namedCaptures = JS_GetProperty(ctx, result, JS_ATOM_groups);-        if (JS_IsException(namedCaptures))-            goto exception;-        if (functionalReplace) {-            if (JS_SetPropertyInt64(ctx, tab, n++, JS_NewInt32(ctx, position)) < 0)-                goto exception;-            if (JS_SetPropertyInt64(ctx, tab, n++, JS_DupValue(ctx, str)) < 0)-                goto exception;-            if (!JS_IsUndefined(namedCaptures)) {-                if (JS_SetPropertyInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures)) < 0)-                    goto exception;-            }-            args[0] = JS_UNDEFINED;-            args[1] = tab;-            JS_FreeValue(ctx, rep_str);-            rep_str = JS_ToStringFree(ctx, js_function_apply(ctx, rep, 2, args, 0));-        } else {-            JSValue namedCaptures1;-            if (!JS_IsUndefined(namedCaptures)) {-                namedCaptures1 = JS_ToObject(ctx, namedCaptures);-                if (JS_IsException(namedCaptures1))-                    goto exception;-            } else {-                namedCaptures1 = JS_UNDEFINED;-            }-            args[0] = matched;-            args[1] = str;-            args[2] = JS_NewInt32(ctx, position);-            args[3] = tab;-            args[4] = namedCaptures1;-            args[5] = rep_val;-            JS_FreeValue(ctx, rep_str);-            rep_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args);-            JS_FreeValue(ctx, namedCaptures1);-        }-        if (JS_IsException(rep_str))-            goto exception;-        if (position >= nextSourcePosition) {-            string_buffer_concat(b, sp, nextSourcePosition, position);-            string_buffer_concat_value(b, rep_str);-            nextSourcePosition = position + JS_VALUE_GET_STRING(matched)->len;-        }-    }-    string_buffer_concat(b, sp, nextSourcePosition, sp->len);-    res = string_buffer_end(b);-    goto done1;--exception:-    res = JS_EXCEPTION;-done:-    string_buffer_free(b);-done1:-    value_buffer_free(results);-    JS_FreeValue(ctx, rep_val);-    JS_FreeValue(ctx, matched);-    JS_FreeValue(ctx, tab);-    JS_FreeValue(ctx, rep_str);-    JS_FreeValue(ctx, namedCaptures);-    JS_FreeValue(ctx, str);-    return res;-}--static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValueConst rx = this_val;-    JSValue str, previousLastIndex, currentLastIndex, result, index;--    if (!JS_IsObject(rx))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    result = JS_UNDEFINED;-    currentLastIndex = JS_UNDEFINED;-    previousLastIndex = JS_UNDEFINED;-    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        goto exception;--    previousLastIndex = JS_GetProperty(ctx, rx, JS_ATOM_lastIndex);-    if (JS_IsException(previousLastIndex))-        goto exception;--    if (!js_same_value(ctx, previousLastIndex, JS_NewInt32(ctx, 0))) {-        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) {-            goto exception;-        }-    }-    result = JS_RegExpExec(ctx, rx, str);-    if (JS_IsException(result))-        goto exception;-    currentLastIndex = JS_GetProperty(ctx, rx, JS_ATOM_lastIndex);-    if (JS_IsException(currentLastIndex))-        goto exception;-    if (js_same_value(ctx, currentLastIndex, previousLastIndex)) {-        JS_FreeValue(ctx, previousLastIndex);-    } else {-        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, previousLastIndex) < 0)-            goto exception;-    }-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, currentLastIndex);--    if (JS_IsNull(result)) {-        return JS_NewInt32(ctx, -1);-    } else {-        index = JS_GetProperty(ctx, result, JS_ATOM_index);-        JS_FreeValue(ctx, result);-        return index;-    }--exception:-    JS_FreeValue(ctx, result);-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, currentLastIndex);-    JS_FreeValue(ctx, previousLastIndex);-    return JS_EXCEPTION;-}--static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    // [Symbol.split](str, limit)-    JSValueConst rx = this_val;-    JSValueConst args[2];-    JSValue str, ctor, splitter, A, flags, z, sub;-    JSString *strp;-    uint32_t lim, size, p, q;-    int unicodeMatching;-    int64_t lengthA, e, numberOfCaptures, i;--    if (!JS_IsObject(rx))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    ctor = JS_UNDEFINED;-    splitter = JS_UNDEFINED;-    A = JS_UNDEFINED;-    flags = JS_UNDEFINED;-    z = JS_UNDEFINED;-    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        goto exception;-    ctor = JS_SpeciesConstructor(ctx, rx, ctx->regexp_ctor);-    if (JS_IsException(ctor))-        goto exception;-    flags = JS_ToStringFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_flags));-    if (JS_IsException(flags))-        goto exception;-    strp = JS_VALUE_GET_STRING(flags);-    unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0;-    if (string_indexof_char(strp, 'y', 0) < 0) {-        flags = JS_ConcatString3(ctx, "", flags, "y");-        if (JS_IsException(flags))-            goto exception;-    }-    args[0] = rx;-    args[1] = flags;-    splitter = JS_CallConstructor(ctx, ctor, 2, args);-    if (JS_IsException(splitter))-        goto exception;-    A = JS_NewArray(ctx);-    if (JS_IsException(A))-        goto exception;-    lengthA = 0;-    if (JS_IsUndefined(argv[1])) {-        lim = 0xffffffff;-    } else {-        if (JS_ToUint32(ctx, &lim, argv[1]) < 0)-            goto exception;-        if (lim == 0)-            goto done;-    }-    strp = JS_VALUE_GET_STRING(str);-    p = q = 0;-    size = strp->len;-    if (size == 0) {-        z = JS_RegExpExec(ctx, splitter, str);-        if (JS_IsException(z))-            goto exception;-        if (JS_IsNull(z))-            goto add_tail;-        goto done;-    }-    while (q < size) {-        if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0)-            goto exception;-        JS_FreeValue(ctx, z);    -        z = JS_RegExpExec(ctx, splitter, str);-        if (JS_IsException(z))-            goto exception;-        if (JS_IsNull(z)) {-            q = string_advance_index(strp, q, unicodeMatching);-        } else {-            if (JS_ToLengthFree(ctx, &e, JS_GetProperty(ctx, splitter, JS_ATOM_lastIndex)))-                goto exception;-            if (e > size)-                e = size;-            if (e == p) {-                q = string_advance_index(strp, q, unicodeMatching);-            } else {-                sub = js_sub_string(ctx, strp, p, q);-                if (JS_IsException(sub))-                    goto exception;-                if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)-                    goto exception;-                if (lengthA == lim)-                    goto done;-                p = e;-                if (js_get_length64(ctx, &numberOfCaptures, z))-                    goto exception;-                for(i = 1; i < numberOfCaptures; i++) {-                    sub = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, z, i));-                    if (JS_IsException(sub))-                        goto exception;-                    if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)-                        goto exception;-                    if (lengthA == lim)-                        goto done;-                }-                q = p;-            }-        }-    }-add_tail:-    if (p > size)-        p = size;-    sub = js_sub_string(ctx, strp, p, size);-    if (JS_IsException(sub))-        goto exception;-    if (JS_SetPropertyInt64(ctx, A, lengthA++, sub) < 0)-        goto exception;-    goto done;-exception:-    JS_FreeValue(ctx, A);-    A = JS_EXCEPTION;-done:-    JS_FreeValue(ctx, str);-    JS_FreeValue(ctx, ctor);-    JS_FreeValue(ctx, splitter);-    JS_FreeValue(ctx, flags);-    JS_FreeValue(ctx, z);    -    return A;-}--static const JSCFunctionListEntry js_regexp_funcs[] = {-    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),-    //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ),-    //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ),-};--static const JSCFunctionListEntry js_regexp_proto_funcs[] = {-    JS_CGETSET_DEF("flags", js_regexp_get_flags, NULL ),-    JS_CGETSET_DEF("source", js_regexp_get_source, NULL ),-    JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, 1 ),-    JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, 2 ),-    JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, 4 ),-    JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, 8 ),-    JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, 16 ),-    JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, 32 ),-    JS_CFUNC_DEF("exec", 1, js_regexp_exec ),-    JS_CFUNC_DEF("compile", 2, js_regexp_compile ),-    JS_CFUNC_DEF("test", 1, js_regexp_test ),-    JS_CFUNC_DEF("toString", 0, js_regexp_toString ),-    JS_CFUNC_DEF("[Symbol.replace]", 2, js_regexp_Symbol_replace ),-    JS_CFUNC_DEF("[Symbol.match]", 1, js_regexp_Symbol_match ),-    JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ),-    JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ),-    JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ),-    //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ),-    //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ),-};--static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 0, js_regexp_string_iterator_next, 0 ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "RegExp String Iterator", JS_PROP_CONFIGURABLE ),-};--void JS_AddIntrinsicRegExpCompiler(JSContext *ctx)-{-    ctx->compile_regexp = js_compile_regexp;-}--void JS_AddIntrinsicRegExp(JSContext *ctx)-{-    JSValueConst obj;--    JS_AddIntrinsicRegExpCompiler(ctx);--    ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP], js_regexp_proto_funcs,-                               countof(js_regexp_proto_funcs));-    obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2,-                                   ctx->class_proto[JS_CLASS_REGEXP]);-    ctx->regexp_ctor = JS_DupValue(ctx, obj);-    JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs));--    ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] =-        JS_NewObjectProto(ctx, ctx->iterator_proto);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR],-                               js_regexp_string_iterator_proto_funcs,-                               countof(js_regexp_string_iterator_proto_funcs));-}--/* JSON */--static int json_parse_expect(JSParseState *s, int tok)-{-    if (s->token.val != tok) {-        /* XXX: dump token correctly in all cases */-        return js_parse_error(s, "expecting '%c'", tok);-    }-    return json_next_token(s);-}--static JSValue json_parse_value(JSParseState *s)-{-    JSContext *ctx = s->ctx;-    JSValue val = JS_NULL;-    int ret;--    switch(s->token.val) {-    case '{':-        {-            JSValue prop_val;-            JSAtom prop_name;-            -            if (json_next_token(s))-                goto fail;-            val = JS_NewObject(ctx);-            if (JS_IsException(val))-                goto fail;-            if (s->token.val != '}') {-                for(;;) {-                    if (s->token.val == TOK_STRING) {-                        prop_name = JS_ValueToAtom(ctx, s->token.u.str.str);-                        if (prop_name == JS_ATOM_NULL)-                            goto fail;-                    } else if (s->ext_json && s->token.val == TOK_IDENT) {-                        prop_name = JS_DupAtom(ctx, s->token.u.ident.atom);-                    } else {-                        js_parse_error(s, "expecting property name");-                        goto fail;-                    }-                    if (json_next_token(s))-                        goto fail1;-                    if (json_parse_expect(s, ':'))-                        goto fail1;-                    prop_val = json_parse_value(s);-                    if (JS_IsException(prop_val)) {-                    fail1:-                        JS_FreeAtom(ctx, prop_name);-                        goto fail;-                    }-                    ret = JS_DefinePropertyValue(ctx, val, prop_name,-                                                 prop_val, JS_PROP_C_W_E);-                    JS_FreeAtom(ctx, prop_name);-                    if (ret < 0)-                        goto fail;--                    if (s->token.val != ',')-                        break;-                    if (json_next_token(s))-                        goto fail;-                    if (s->ext_json && s->token.val == '}')-                        break;-                }-            }-            if (json_parse_expect(s, '}'))-                goto fail;-        }-        break;-    case '[':-        {-            JSValue el;-            uint32_t idx;--            if (json_next_token(s))-                goto fail;-            val = JS_NewArray(ctx);-            if (JS_IsException(val))-                goto fail;-            if (s->token.val != ']') {-                idx = 0;-                for(;;) {-                    el = json_parse_value(s);-                    if (JS_IsException(el))-                        goto fail;-                    ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E);-                    if (ret < 0)-                        goto fail;-                    if (s->token.val != ',')-                        break;-                    if (json_next_token(s))-                        goto fail;-                    idx++;-                    if (s->ext_json && s->token.val == ']')-                        break;-                }-            }-            if (json_parse_expect(s, ']'))-                goto fail;-        }-        break;-    case TOK_STRING:-        val = JS_DupValue(ctx, s->token.u.str.str);-        if (json_next_token(s))-            goto fail;-        break;-    case TOK_NUMBER:-        val = s->token.u.num.val;-        if (json_next_token(s))-            goto fail;-        break;-    case TOK_IDENT:-        if (s->token.u.ident.atom == JS_ATOM_false ||-            s->token.u.ident.atom == JS_ATOM_true) {-            val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true));-        } else if (s->token.u.ident.atom == JS_ATOM_null) {-            val = JS_NULL;-        } else {-            goto def_token;-        }-        if (json_next_token(s))-            goto fail;-        break;-    default:-    def_token:-        if (s->token.val == TOK_EOF) {-            js_parse_error(s, "unexpected end of input");-        } else {-            js_parse_error(s, "unexpected token: '%.*s'",-                           (int)(s->buf_ptr - s->token.ptr), s->token.ptr);-        }-        goto fail;-    }-    return val;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,-                      const char *filename, int flags)-{-    JSParseState s1, *s = &s1;-    JSValue val = JS_UNDEFINED;--    js_parse_init(ctx, s, buf, buf_len, filename);-    s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);-    if (json_next_token(s))-        goto fail;-    val = json_parse_value(s);-    if (JS_IsException(val))-        goto fail;-    if (s->token.val != TOK_EOF) {-        if (js_parse_error(s, "unexpected data at the end"))-            goto fail;-    }-    return val;- fail:-    JS_FreeValue(ctx, val);-    free_token(s, &s->token);-    return JS_EXCEPTION;-}--JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,-                     const char *filename)-{-    return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); -}--static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,-                                         JSAtom name, JSValueConst reviver)-{-    JSValue val, new_el, name_val, res;-    JSValueConst args[2];-    int ret, is_array;-    uint32_t i, len = 0;-    JSAtom prop;-    JSPropertyEnum *atoms = NULL;--    if (js_check_stack_overflow(ctx->rt, 0)) {-        return JS_ThrowStackOverflow(ctx);-    }--    val = JS_GetProperty(ctx, holder, name);-    if (JS_IsException(val))-        return val;-    if (JS_IsObject(val)) {-        is_array = JS_IsArray(ctx, val);-        if (is_array < 0)-            goto fail;-        if (is_array) {-            if (js_get_length32(ctx, &len, val))-                goto fail;-        } else {-            ret = JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, JS_VALUE_GET_OBJ(val), JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);-            if (ret < 0)-                goto fail;-        }-        for(i = 0; i < len; i++) {-            if (is_array) {-                prop = JS_NewAtomUInt32(ctx, i);-                if (prop == JS_ATOM_NULL)-                    goto fail;-            } else {-                prop = JS_DupAtom(ctx, atoms[i].atom);-            }-            new_el = internalize_json_property(ctx, val, prop, reviver);-            if (JS_IsException(new_el)) {-                JS_FreeAtom(ctx, prop);-                goto fail;-            }-            if (JS_IsUndefined(new_el)) {-                ret = JS_DeleteProperty(ctx, val, prop, 0);-            } else {-                ret = JS_DefinePropertyValue(ctx, val, prop, new_el, JS_PROP_C_W_E);-            }-            JS_FreeAtom(ctx, prop);-            if (ret < 0)-                goto fail;-        }-    }-    js_free_prop_enum(ctx, atoms, len);-    atoms = NULL;-    name_val = JS_AtomToValue(ctx, name);-    if (JS_IsException(name_val))-        goto fail;-    args[0] = name_val;-    args[1] = val;-    res = JS_Call(ctx, reviver, holder, 2, args);-    JS_FreeValue(ctx, name_val);-    JS_FreeValue(ctx, val);-    return res;- fail:-    js_free_prop_enum(ctx, atoms, len);-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    JSValue obj, root;-    JSValueConst reviver;-    const char *str;-    size_t len;--    str = JS_ToCStringLen(ctx, &len, argv[0]);-    if (!str)-        return JS_EXCEPTION;-    obj = JS_ParseJSON(ctx, str, len, "<input>");-    JS_FreeCString(ctx, str);-    if (JS_IsException(obj))-        return obj;-    if (argc > 1 && JS_IsFunction(ctx, argv[1])) {-        reviver = argv[1];-        root = JS_NewObject(ctx);-        if (JS_IsException(root)) {-            JS_FreeValue(ctx, obj);-            return JS_EXCEPTION;-        }-        if (JS_DefinePropertyValue(ctx, root, JS_ATOM_empty_string, obj,-                                   JS_PROP_C_W_E) < 0) {-            JS_FreeValue(ctx, root);-            return JS_EXCEPTION;-        }-        obj = internalize_json_property(ctx, root, JS_ATOM_empty_string,-                                        reviver);-        JS_FreeValue(ctx, root);-    }-    return obj;-}--typedef struct JSONStringifyContext {-    JSValueConst replacer_func;-    JSValue stack;-    JSValue property_list;-    JSValue gap;-    JSValue empty;-    StringBuffer *b;-} JSONStringifyContext;--static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) {-    JSValue r = JS_ToQuotedString(ctx, val);-    JS_FreeValue(ctx, val);-    return r;-}--static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,-                             JSValueConst holder, JSValue val, JSValueConst key)-{-    JSValue v;-    JSValueConst args[2];--    if (JS_IsObject(val)-#ifdef CONFIG_BIGNUM-    ||  JS_IsBigInt(ctx, val)   /* XXX: probably useless */-#endif-        ) {-            JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);-            if (JS_IsException(f))-                goto exception;-            if (JS_IsFunction(ctx, f)) {-                v = JS_CallFree(ctx, f, val, 1, &key);-                JS_FreeValue(ctx, val);-                val = v;-                if (JS_IsException(val))-                    goto exception;-            } else {-                JS_FreeValue(ctx, f);-            }-        }--    if (!JS_IsUndefined(jsc->replacer_func)) {-        args[0] = key;-        args[1] = val;-        v = JS_Call(ctx, jsc->replacer_func, holder, 2, args);-        JS_FreeValue(ctx, val);-        val = v;-        if (JS_IsException(val))-            goto exception;-    }--    switch (JS_VALUE_GET_NORM_TAG(val)) {-    case JS_TAG_OBJECT:-        if (JS_IsFunction(ctx, val))-            break;-    case JS_TAG_STRING:-    case JS_TAG_INT:-    case JS_TAG_FLOAT64:-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-#endif-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-#endif-    case JS_TAG_EXCEPTION:-        return val;-    default:-        break;-    }-    JS_FreeValue(ctx, val);-    return JS_UNDEFINED;--exception:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,-                          JSValueConst holder, JSValue val,-                          JSValueConst indent)-{-    JSValue indent1, sep, sep1, tab, v, prop;-    JSObject *p;-    int64_t i, len;-    int cl, ret;-    BOOL has_content;-    -    indent1 = JS_UNDEFINED;-    sep = JS_UNDEFINED;-    sep1 = JS_UNDEFINED;-    tab = JS_UNDEFINED;-    prop = JS_UNDEFINED;--    switch (JS_VALUE_GET_NORM_TAG(val)) {-    case JS_TAG_OBJECT:-        p = JS_VALUE_GET_OBJ(val);-        cl = p->class_id;-        if (cl == JS_CLASS_STRING) {-            val = JS_ToStringFree(ctx, val);-            if (JS_IsException(val))-                goto exception;-            val = JS_ToQuotedStringFree(ctx, val);-            if (JS_IsException(val))-                goto exception;-            return string_buffer_concat_value_free(jsc->b, val);-        } else if (cl == JS_CLASS_NUMBER) {-            val = JS_ToNumberFree(ctx, val);-            if (JS_IsException(val))-                goto exception;-            return string_buffer_concat_value_free(jsc->b, val);-        } else if (cl == JS_CLASS_BOOLEAN) {-            ret = string_buffer_concat_value(jsc->b, p->u.object_data);-            JS_FreeValue(ctx, val);-            return ret;-        }-#ifdef CONFIG_BIGNUM-        else if (cl == JS_CLASS_BIG_FLOAT) {-            return string_buffer_concat_value_free(jsc->b, val);-        } else if (cl == JS_CLASS_BIG_INT) {-            JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");-            goto exception;-        }-#endif-        v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);-        if (JS_IsException(v))-            goto exception;-        if (JS_ToBoolFree(ctx, v)) {-            JS_ThrowTypeError(ctx, "circular reference");-            goto exception;-        }-        indent1 = JS_ConcatString(ctx, JS_DupValue(ctx, indent), JS_DupValue(ctx, jsc->gap));-        if (JS_IsException(indent1))-            goto exception;-        if (!JS_IsEmptyString(jsc->gap)) {-            sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), "");-            if (JS_IsException(sep))-                goto exception;-            sep1 = JS_NewString(ctx, " ");-            if (JS_IsException(sep1))-                goto exception;-        } else {-            sep = JS_DupValue(ctx, jsc->empty);-            sep1 = JS_DupValue(ctx, jsc->empty);-        }-        v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);-        if (check_exception_free(ctx, v))-            goto exception;-        ret = JS_IsArray(ctx, val);-        if (ret < 0)-            goto exception;-        if (ret) {-            if (js_get_length64(ctx, &len, val))-                goto exception;-            string_buffer_putc8(jsc->b, '[');-            for(i = 0; i < len; i++) {-                if (i > 0)-                    string_buffer_putc8(jsc->b, ',');-                string_buffer_concat_value(jsc->b, sep);-                v = JS_GetPropertyInt64(ctx, val, i);-                if (JS_IsException(v))-                    goto exception;-                /* XXX: could do this string conversion only when needed */-                prop = JS_ToStringFree(ctx, JS_NewInt64(ctx, i));-                if (JS_IsException(prop))-                    goto exception;-                v = js_json_check(ctx, jsc, val, v, prop);-                JS_FreeValue(ctx, prop);-                prop = JS_UNDEFINED;-                if (JS_IsException(v))-                    goto exception;-                if (JS_IsUndefined(v))-                    v = JS_NULL;-                if (js_json_to_str(ctx, jsc, val, v, indent1))-                    goto exception;-            }-            if (len > 0 && !JS_IsEmptyString(jsc->gap)) {-                string_buffer_putc8(jsc->b, '\n');-                string_buffer_concat_value(jsc->b, indent);-            }-            string_buffer_putc8(jsc->b, ']');-        } else {-            if (!JS_IsUndefined(jsc->property_list))-                tab = JS_DupValue(ctx, jsc->property_list);-            else-                tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);-            if (JS_IsException(tab))-                goto exception;-            if (js_get_length64(ctx, &len, tab))-                goto exception;-            string_buffer_putc8(jsc->b, '{');-            has_content = FALSE;-            for(i = 0; i < len; i++) {-                JS_FreeValue(ctx, prop);-                prop = JS_GetPropertyInt64(ctx, tab, i);-                if (JS_IsException(prop))-                    goto exception;-                v = JS_GetPropertyValue(ctx, val, JS_DupValue(ctx, prop));-                if (JS_IsException(v))-                    goto exception;-                v = js_json_check(ctx, jsc, val, v, prop);-                if (JS_IsException(v))-                    goto exception;-                if (!JS_IsUndefined(v)) {-                    if (has_content)-                        string_buffer_putc8(jsc->b, ',');-                    prop = JS_ToQuotedStringFree(ctx, prop);-                    if (JS_IsException(prop)) {-                        JS_FreeValue(ctx, v);-                        goto exception;-                    }-                    string_buffer_concat_value(jsc->b, sep);-                    string_buffer_concat_value(jsc->b, prop);-                    string_buffer_putc8(jsc->b, ':');-                    string_buffer_concat_value(jsc->b, sep1);-                    if (js_json_to_str(ctx, jsc, val, v, indent1))-                        goto exception;-                    has_content = TRUE;-                }-            }-            if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) {-                string_buffer_putc8(jsc->b, '\n');-                string_buffer_concat_value(jsc->b, indent);-            }-            string_buffer_putc8(jsc->b, '}');-        }-        if (check_exception_free(ctx, js_array_pop(ctx, jsc->stack, 0, NULL, 0)))-            goto exception;-        JS_FreeValue(ctx, val);-        JS_FreeValue(ctx, tab);-        JS_FreeValue(ctx, sep);-        JS_FreeValue(ctx, sep1);-        JS_FreeValue(ctx, indent1);-        JS_FreeValue(ctx, prop);-        return 0;-    case JS_TAG_STRING:-        val = JS_ToQuotedStringFree(ctx, val);-        if (JS_IsException(val))-            goto exception;-        goto concat_value;-    case JS_TAG_FLOAT64:-        if (!isfinite(JS_VALUE_GET_FLOAT64(val))) {-            val = JS_NULL;-        }-        goto concat_value;-    case JS_TAG_INT:-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_FLOAT:-#endif-    case JS_TAG_BOOL:-    case JS_TAG_NULL:-    concat_value:-        return string_buffer_concat_value_free(jsc->b, val);-#ifdef CONFIG_BIGNUM-    case JS_TAG_BIG_INT:-        JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");-        goto exception;-#endif-    default:-        JS_FreeValue(ctx, val);-        return 0;-    }-    -exception:-    JS_FreeValue(ctx, val);-    JS_FreeValue(ctx, tab);-    JS_FreeValue(ctx, sep);-    JS_FreeValue(ctx, sep1);-    JS_FreeValue(ctx, indent1);-    JS_FreeValue(ctx, prop);-    return -1;-}--JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,-                         JSValueConst replacer, JSValueConst space0)-{-    StringBuffer b_s;-    JSONStringifyContext jsc_s, *jsc = &jsc_s;-    JSValue val, v, space, ret, wrapper;-    int res;-    int64_t i, j, n;--    jsc->replacer_func = JS_UNDEFINED;-    jsc->stack = JS_UNDEFINED;-    jsc->property_list = JS_UNDEFINED;-    jsc->gap = JS_UNDEFINED;-    jsc->b = &b_s;-    jsc->empty = JS_AtomToString(ctx, JS_ATOM_empty_string);-    ret = JS_UNDEFINED;-    wrapper = JS_UNDEFINED;--    string_buffer_init(ctx, jsc->b, 0);-    jsc->stack = JS_NewArray(ctx);-    if (JS_IsException(jsc->stack))-        goto exception;-    if (JS_IsFunction(ctx, replacer)) {-        jsc->replacer_func = replacer;-    } else {-        res = JS_IsArray(ctx, replacer);-        if (res < 0)-            goto exception;-        if (res) {-            /* XXX: enumeration is not fully correct */-            jsc->property_list = JS_NewArray(ctx);-            if (JS_IsException(jsc->property_list))-                goto exception;-            if (js_get_length64(ctx, &n, replacer))-                goto exception;-            for (i = j = 0; i < n; i++) {-                JSValue present;-                v = JS_GetPropertyInt64(ctx, replacer, i);-                if (JS_IsException(v))-                    goto exception;-                if (JS_IsObject(v)) {-                    JSObject *p = JS_VALUE_GET_OBJ(v);-                    if (p->class_id == JS_CLASS_STRING ||-                        p->class_id == JS_CLASS_NUMBER) {-                        v = JS_ToStringFree(ctx, v);-                        if (JS_IsException(v))-                            goto exception;-                    } else {-                        JS_FreeValue(ctx, v);-                        continue;-                    }-                } else if (JS_IsNumber(v)) {-                    v = JS_ToStringFree(ctx, v);-                    if (JS_IsException(v))-                        goto exception;-                } else if (!JS_IsString(v)) {-                    JS_FreeValue(ctx, v);-                    continue;-                }-                present = js_array_includes(ctx, jsc->property_list,-                                            1, (JSValueConst *)&v);-                if (JS_IsException(present)) {-                    JS_FreeValue(ctx, v);-                    goto exception;-                }-                if (!JS_ToBoolFree(ctx, present)) {-                    JS_SetPropertyInt64(ctx, jsc->property_list, j++, v);-                } else {-                    JS_FreeValue(ctx, v);-                }-            }-        }-    }-    space = JS_DupValue(ctx, space0);-    if (JS_IsObject(space)) {-        JSObject *p = JS_VALUE_GET_OBJ(space);-        if (p->class_id == JS_CLASS_NUMBER) {-            space = JS_ToNumberFree(ctx, space);-        } else if (p->class_id == JS_CLASS_STRING) {-            space = JS_ToStringFree(ctx, space);-        }-        if (JS_IsException(space)) {-            JS_FreeValue(ctx, space);-            goto exception;-        }-    }-    if (JS_IsNumber(space)) {-        int n;-        if (JS_ToInt32Clamp(ctx, &n, space, 0, 10, 0))-            goto exception;-        jsc->gap = JS_NewStringLen(ctx, "          ", n);-    } else if (JS_IsString(space)) {-        JSString *p = JS_VALUE_GET_STRING(space);-        jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10));-    } else {-        jsc->gap = JS_DupValue(ctx, jsc->empty);-    }-    JS_FreeValue(ctx, space);-    if (JS_IsException(jsc->gap))-        goto exception;-    wrapper = JS_NewObject(ctx);-    if (JS_IsException(wrapper))-        goto exception;-    if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string,-                               JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0)-        goto exception;-    val = JS_DupValue(ctx, obj);-                           -    val = js_json_check(ctx, jsc, wrapper, val, jsc->empty);-    if (JS_IsException(val))-        goto exception;-    if (JS_IsUndefined(val)) {-        ret = JS_UNDEFINED;-        goto done1;-    }-    if (js_json_to_str(ctx, jsc, wrapper, val, jsc->empty))-        goto exception;--    ret = string_buffer_end(jsc->b);-    goto done;--exception:-    ret = JS_EXCEPTION;-done1:-    string_buffer_free(jsc->b);-done:-    JS_FreeValue(ctx, wrapper);-    JS_FreeValue(ctx, jsc->empty);-    JS_FreeValue(ctx, jsc->gap);-    JS_FreeValue(ctx, jsc->property_list);-    JS_FreeValue(ctx, jsc->stack);-    return ret;-}--static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    // stringify(val, replacer, space)-    return JS_JSONStringify(ctx, argv[0], argv[1], argv[2]);-}--static const JSCFunctionListEntry js_json_funcs[] = {-    JS_CFUNC_DEF("parse", 2, js_json_parse ),-    JS_CFUNC_DEF("stringify", 3, js_json_stringify ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "JSON", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_json_obj[] = {-    JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),-};--void JS_AddIntrinsicJSON(JSContext *ctx)-{-    /* add JSON as autoinit object */-    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj));-}--/* Reflect */--static JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 0);-}--static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValueConst func, array_arg, new_target;-    JSValue *tab, ret;-    uint32_t len;--    func = argv[0];-    array_arg = argv[1];-    if (argc > 2) {-        new_target = argv[2];-        if (!JS_IsConstructor(ctx, new_target))-            return JS_ThrowTypeError(ctx, "not a constructor");-    } else {-        new_target = func;-    }-    tab = build_arg_list(ctx, &len, array_arg);-    if (!tab)-        return JS_EXCEPTION;-    ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);-    free_arg_list(ctx, tab, len);-    return ret;-}--static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    JSValueConst obj;-    JSAtom atom;-    int ret;--    obj = argv[0];-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    atom = JS_ValueToAtom(ctx, argv[1]);-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    ret = JS_DeleteProperty(ctx, obj, atom, 0);-    JS_FreeAtom(ctx, atom);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSValueConst obj, prop, receiver;-    JSAtom atom;-    JSValue ret;--    obj = argv[0];-    prop = argv[1];-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    if (argc > 2)-        receiver = argv[2];-    else-        receiver = obj;-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, FALSE);-    JS_FreeAtom(ctx, atom);-    return ret;-}--static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSValueConst obj, prop;-    JSAtom atom;-    int ret;--    obj = argv[0];-    prop = argv[1];-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    ret = JS_HasProperty(ctx, obj, atom);-    JS_FreeAtom(ctx, atom);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    JSValueConst obj, prop, val, receiver;-    int ret;-    JSAtom atom;--    obj = argv[0];-    prop = argv[1];-    val = argv[2];-    if (argc > 3)-        receiver = argv[3];-    else-        receiver = obj;-    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    atom = JS_ValueToAtom(ctx, prop);-    if (unlikely(atom == JS_ATOM_NULL))-        return JS_EXCEPTION;-    ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(obj), atom,-                                JS_DupValue(ctx, val), receiver, 0);-    JS_FreeAtom(ctx, atom);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    int ret;-    ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE);-    if (ret < 0)-        return JS_EXCEPTION;-    else-        return JS_NewBool(ctx, ret);-}--static JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);-    return JS_GetOwnPropertyNames2(ctx, argv[0],-                                   JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK,-                                   JS_ITERATOR_KIND_KEY);-}--static const JSCFunctionListEntry js_reflect_funcs[] = {-    JS_CFUNC_DEF("apply", 3, js_reflect_apply ),-    JS_CFUNC_DEF("construct", 2, js_reflect_construct ),-    JS_CFUNC_MAGIC_DEF("defineProperty", 3, js_object_defineProperty, 1 ),-    JS_CFUNC_DEF("deleteProperty", 2, js_reflect_deleteProperty ),-    JS_CFUNC_DEF("get", 2, js_reflect_get ),-    JS_CFUNC_MAGIC_DEF("getOwnPropertyDescriptor", 2, js_object_getOwnPropertyDescriptor, 1 ),-    JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 1 ),-    JS_CFUNC_DEF("has", 2, js_reflect_has ),-    JS_CFUNC_MAGIC_DEF("isExtensible", 1, js_object_isExtensible, 1 ),-    JS_CFUNC_DEF("ownKeys", 1, js_reflect_ownKeys ),-    JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 1 ),-    JS_CFUNC_DEF("set", 3, js_reflect_set ),-    JS_CFUNC_DEF("setPrototypeOf", 2, js_reflect_setPrototypeOf ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Reflect", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_reflect_obj[] = {-    JS_OBJECT_DEF("Reflect", js_reflect_funcs, countof(js_reflect_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),-};--/* Proxy */--static void js_proxy_finalizer(JSRuntime *rt, JSValue val)-{-    JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY);-    if (s) {-        JS_FreeValueRT(rt, s->target);-        JS_FreeValueRT(rt, s->handler);-        js_free_rt(rt, s);-    }-}--static void js_proxy_mark(JSRuntime *rt, JSValueConst val,-                          JS_MarkFunc *mark_func)-{-    JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY);-    if (s) {-        JS_MarkValue(rt, s->target, mark_func);-        JS_MarkValue(rt, s->handler, mark_func);-    }-}--static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "revoked proxy");-}--static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod,-                                     JSValueConst obj, JSAtom name)-{-    JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);-    JSValue method;--    /* safer to test recursion in all proxy methods */-    if (js_check_stack_overflow(ctx->rt, 0)) {-        JS_ThrowStackOverflow(ctx);-        return NULL;-    }-    -    /* 's' should never be NULL */-    if (s->is_revoked) {-        JS_ThrowTypeErrorRevokedProxy(ctx);-        return NULL;-    }-    method = JS_GetProperty(ctx, s->handler, name);-    if (JS_IsException(method))-        return NULL;-    if (JS_IsNull(method))-        method = JS_UNDEFINED;-    *pmethod = method;-    return s;-}--static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)-{-    JSProxyData *s;-    JSValue method, ret, proto1;-    int res;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf);-    if (!s)-        return JS_EXCEPTION;-    if (JS_IsUndefined(method))-        return JS_GetPrototype(ctx, s->target);-    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);-    if (JS_IsException(ret))-        return ret;-    if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&-        JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {-        goto fail;-    }-    res = JS_IsExtensible(ctx, s->target);-    if (res < 0) {-        JS_FreeValue(ctx, ret);-        return JS_EXCEPTION;-    }-    if (!res) {-        /* check invariant */-        proto1 = JS_GetPrototype(ctx, s->target);-        if (JS_IsException(proto1)) {-            JS_FreeValue(ctx, ret);-            return JS_EXCEPTION;-        }-        if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) {-            JS_FreeValue(ctx, proto1);-        fail:-            JS_FreeValue(ctx, ret);-            return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");-        }-        JS_FreeValue(ctx, proto1);-    }-    return ret;-}--static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,-                                   JSValueConst proto_val, BOOL throw_flag)-{-    JSProxyData *s;-    JSValue method, ret, proto1;-    JSValueConst args[2];-    BOOL res;-    int res2;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_setPrototypeOf);-    if (!s)-        return -1;-    if (JS_IsUndefined(method))-        return JS_SetPrototypeInternal(ctx, s->target, proto_val, throw_flag);-    args[0] = s->target;-    args[1] = proto_val;-    ret = JS_CallFree(ctx, method, s->handler, 2, args);-    if (JS_IsException(ret))-        return -1;-    res = JS_ToBoolFree(ctx, ret);-    if (!res) {-        if (throw_flag) {-            JS_ThrowTypeError(ctx, "proxy: bad prototype");-            return -1;-        } else {-            return FALSE;-        }-    }-    res2 = JS_IsExtensible(ctx, s->target);-    if (res2 < 0)-        return -1;-    if (!res2) {-        proto1 = JS_GetPrototype(ctx, s->target);-        if (JS_IsException(proto1))-            return -1;-        if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) {-            JS_FreeValue(ctx, proto1);-            JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");-            return -1;-        }-        JS_FreeValue(ctx, proto1);-    }-    return TRUE;-}--static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)-{-    JSProxyData *s;-    JSValue method, ret;-    BOOL res;-    int res2;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_isExtensible);-    if (!s)-        return -1;-    if (JS_IsUndefined(method))-        return JS_IsExtensible(ctx, s->target);-    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);-    if (JS_IsException(ret))-        return -1;-    res = JS_ToBoolFree(ctx, ret);-    res2 = JS_IsExtensible(ctx, s->target);-    if (res2 < 0)-        return res2;-    if (res != res2) {-        JS_ThrowTypeError(ctx, "proxy: inconsistent isExtensible");-        return -1;-    }-    return res;-}--static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)-{-    JSProxyData *s;-    JSValue method, ret;-    BOOL res;-    int res2;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_preventExtensions);-    if (!s)-        return -1;-    if (JS_IsUndefined(method))-        return JS_PreventExtensions(ctx, s->target);-    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);-    if (JS_IsException(ret))-        return -1;-    res = JS_ToBoolFree(ctx, ret);-    if (res) {-        res2 = JS_IsExtensible(ctx, s->target);-        if (res2 < 0)-            return res2;-        if (res2) {-            JS_ThrowTypeError(ctx, "proxy: inconsistent preventExtensions");-            return -1;-        }-    }-    return res;-}--static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom)-{-    JSProxyData *s;-    JSValue method, ret1, atom_val;-    int ret, res;-    JSObject *p;-    JSValueConst args[2];-    BOOL res2;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_has);-    if (!s)-        return -1;-    if (JS_IsUndefined(method))-        return JS_HasProperty(ctx, s->target, atom);-    atom_val = JS_AtomToValue(ctx, atom);-    if (JS_IsException(atom_val)) {-        JS_FreeValue(ctx, method);-        return -1;-    }-    args[0] = s->target;-    args[1] = atom_val;-    ret1 = JS_CallFree(ctx, method, s->handler, 2, args);-    JS_FreeValue(ctx, atom_val);-    if (JS_IsException(ret1))-        return -1;-    ret = JS_ToBoolFree(ctx, ret1);-    if (!ret) {-        JSPropertyDescriptor desc;-        p = JS_VALUE_GET_OBJ(s->target);-        res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);-        if (res < 0)-            return -1;-        if (res) {-            res2 = !(desc.flags & JS_PROP_CONFIGURABLE);-            js_free_desc(ctx, &desc);-            if (res2 || !p->extensible) {-                JS_ThrowTypeError(ctx, "proxy: inconsistent has");-                return -1;-            }-        }-    }-    return ret;-}--static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,-                            JSValueConst receiver)-{-    JSProxyData *s;-    JSValue method, ret, atom_val;-    int res;-    JSValueConst args[3];-    JSPropertyDescriptor desc;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_get);-    if (!s)-        return JS_EXCEPTION;-    /* Note: recursion is possible thru the prototype of s->target */-    if (JS_IsUndefined(method))-        return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE);-    atom_val = JS_AtomToValue(ctx, atom);-    if (JS_IsException(atom_val)) {-        JS_FreeValue(ctx, method);-        return JS_EXCEPTION;-    }-    args[0] = s->target;-    args[1] = atom_val;-    args[2] = receiver;-    ret = JS_CallFree(ctx, method, s->handler, 3, args);-    JS_FreeValue(ctx, atom_val);-    if (JS_IsException(ret))-        return JS_EXCEPTION;-    res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);-    if (res < 0)-        return JS_EXCEPTION;-    if (res) {-        if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) {-            if (!js_same_value(ctx, desc.value, ret)) {-                goto fail;-            }-        } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET) {-            if (JS_IsUndefined(desc.getter) && !JS_IsUndefined(ret)) {-            fail:-                js_free_desc(ctx, &desc);-                JS_FreeValue(ctx, ret);-                return JS_ThrowTypeError(ctx, "proxy: inconsistent get");-            }-        }-        js_free_desc(ctx, &desc);-    }-    return ret;-}--static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,-                        JSValueConst value, JSValueConst receiver, int flags)-{-    JSProxyData *s;-    JSValue method, ret1, atom_val;-    int ret, res;-    JSValueConst args[4];--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_set);-    if (!s)-        return -1;-    if (JS_IsUndefined(method)) {-        return JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(s->target), atom,-                                     JS_DupValue(ctx, value), receiver,-                                     flags);-    }-    atom_val = JS_AtomToValue(ctx, atom);-    if (JS_IsException(atom_val)) {-        JS_FreeValue(ctx, method);-        return -1;-    }-    args[0] = s->target;-    args[1] = atom_val;-    args[2] = value;-    args[3] = receiver;-    ret1 = JS_CallFree(ctx, method, s->handler, 4, args);-    JS_FreeValue(ctx, atom_val);-    if (JS_IsException(ret1))-        return -1;-    ret = JS_ToBoolFree(ctx, ret1);-    if (ret) {-        JSPropertyDescriptor desc;-        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);-        if (res < 0)-            return -1;-        if (res) {-            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) {-                if (!js_same_value(ctx, desc.value, value)) {-                    goto fail;-                }-            } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET && JS_IsUndefined(desc.setter)) {-                fail:-                    js_free_desc(ctx, &desc);-                    JS_ThrowTypeError(ctx, "proxy: inconsistent set");-                    return -1;-            }-            js_free_desc(ctx, &desc);-        }-    } else {-        if ((flags & JS_PROP_THROW) ||-            ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {-            JS_ThrowTypeError(ctx, "proxy: cannot set property");-            return -1;-        }-    }-    return ret;-}--static JSValue js_create_desc(JSContext *ctx, JSValueConst val,-                              JSValueConst getter, JSValueConst setter,-                              int flags)-{-    JSValue ret;-    ret = JS_NewObject(ctx);-    if (JS_IsException(ret))-        return ret;-    if (flags & JS_PROP_HAS_GET) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, getter),-                               JS_PROP_C_W_E);-    }-    if (flags & JS_PROP_HAS_SET) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter),-                               JS_PROP_C_W_E);-    }-    if (flags & JS_PROP_HAS_VALUE) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val),-                               JS_PROP_C_W_E);-    }-    if (flags & JS_PROP_HAS_WRITABLE) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,-                               JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0),-                               JS_PROP_C_W_E);-    }-    if (flags & JS_PROP_HAS_ENUMERABLE) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,-                               JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0),-                               JS_PROP_C_W_E);-    }-    if (flags & JS_PROP_HAS_CONFIGURABLE) {-        JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,-                               JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0),-                               JS_PROP_C_W_E);-    }-    return ret;-}--static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc,-                                     JSValueConst obj, JSAtom prop)-{-    JSProxyData *s;-    JSValue method, trap_result_obj, prop_val;-    int res, target_desc_ret, ret;-    JSObject *p;-    JSValueConst args[2];-    JSPropertyDescriptor result_desc, target_desc;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor);-    if (!s)-        return -1;-    p = JS_VALUE_GET_OBJ(s->target);-    if (JS_IsUndefined(method)) {-        return JS_GetOwnPropertyInternal(ctx, pdesc, p, prop);-    }-    prop_val = JS_AtomToValue(ctx, prop);-    if (JS_IsException(prop_val)) {-        JS_FreeValue(ctx, method);-        return -1;-    }-    args[0] = s->target;-    args[1] = prop_val;-    trap_result_obj = JS_CallFree(ctx, method, s->handler, 2, args);-    JS_FreeValue(ctx, prop_val);-    if (JS_IsException(trap_result_obj))-        return -1;-    if (!JS_IsObject(trap_result_obj) && !JS_IsUndefined(trap_result_obj)) {-        JS_FreeValue(ctx, trap_result_obj);-        goto fail;-    }-    target_desc_ret = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop);-    if (target_desc_ret < 0) {-        JS_FreeValue(ctx, trap_result_obj);-        return -1;-    }-    if (target_desc_ret)-        js_free_desc(ctx, &target_desc);-    if (JS_IsUndefined(trap_result_obj)) {-        if (target_desc_ret) {-            if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible)-                goto fail;-        }-        ret = FALSE;-    } else {-        int flags1, extensible_target;-        extensible_target = JS_IsExtensible(ctx, s->target);-        if (extensible_target < 0) {-            JS_FreeValue(ctx, trap_result_obj);-            return -1;-        }-        res = js_obj_to_desc(ctx, &result_desc, trap_result_obj);-        JS_FreeValue(ctx, trap_result_obj);-        if (res < 0)-            return -1;-        -        if (target_desc_ret) {-            /* convert result_desc.flags to defineProperty flags */-            flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE;-            if (result_desc.flags & JS_PROP_GETSET)-                flags1 |= JS_PROP_HAS_GET | JS_PROP_HAS_SET;-            else-                flags1 |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE;-            /* XXX: not complete check: need to compare value &-               getter/setter as in defineproperty */-            if (!check_define_prop_flags(target_desc.flags, flags1))-                goto fail1;-        } else {-            if (!extensible_target)-                goto fail1;-        }-        if (!(result_desc.flags & JS_PROP_CONFIGURABLE)) {-            if (!target_desc_ret || (target_desc.flags & JS_PROP_CONFIGURABLE))-                goto fail1;-            if ((result_desc.flags &-                 (JS_PROP_GETSET | JS_PROP_WRITABLE)) == 0 &&-                target_desc_ret &&-                (target_desc.flags & JS_PROP_WRITABLE) != 0) {-                /* proxy-missing-checks */-            fail1:-                js_free_desc(ctx, &result_desc);-            fail:-                JS_ThrowTypeError(ctx, "proxy: inconsistent getOwnPropertyDescriptor");-                return -1;-            }-        }-        ret = TRUE;-        if (pdesc) {-            *pdesc = result_desc;-        } else {-            js_free_desc(ctx, &result_desc);-        }-    }-    return ret;-}--static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj,-                                        JSAtom prop, JSValueConst val,-                                        JSValueConst getter, JSValueConst setter,-                                        int flags)-{-    JSProxyData *s;-    JSValue method, ret1, prop_val, desc_val;-    int res, ret;-    JSObject *p;-    JSValueConst args[3];-    JSPropertyDescriptor desc;-    BOOL setting_not_configurable;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_defineProperty);-    if (!s)-        return -1;-    if (JS_IsUndefined(method)) {-        return JS_DefineProperty(ctx, s->target, prop, val, getter, setter, flags);-    }-    prop_val = JS_AtomToValue(ctx, prop);-    if (JS_IsException(prop_val)) {-        JS_FreeValue(ctx, method);-        return -1;-    }-    desc_val = js_create_desc(ctx, val, getter, setter, flags);-    if (JS_IsException(desc_val)) {-        JS_FreeValue(ctx, prop_val);-        JS_FreeValue(ctx, method);-        return -1;-    }-    args[0] = s->target;-    args[1] = prop_val;-    args[2] = desc_val;-    ret1 = JS_CallFree(ctx, method, s->handler, 3, args);-    JS_FreeValue(ctx, prop_val);-    JS_FreeValue(ctx, desc_val);-    if (JS_IsException(ret1))-        return -1;-    ret = JS_ToBoolFree(ctx, ret1);-    if (!ret) {-        if (flags & JS_PROP_THROW) {-            JS_ThrowTypeError(ctx, "proxy: defineProperty exception");-            return -1;-        } else {-            return 0;-        }-    }-    p = JS_VALUE_GET_OBJ(s->target);-    res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);-    if (res < 0)-        return -1;-    setting_not_configurable = ((flags & (JS_PROP_HAS_CONFIGURABLE |-                                          JS_PROP_CONFIGURABLE)) ==-                                JS_PROP_HAS_CONFIGURABLE);-    if (!res) {-        if (!p->extensible || setting_not_configurable)-            goto fail;-    } else {-        if (!check_define_prop_flags(desc.flags, flags) ||-            ((desc.flags & JS_PROP_CONFIGURABLE) && setting_not_configurable)) {-            goto fail1;-        }-        if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {-            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) ==-                JS_PROP_GETSET) {-                if ((flags & JS_PROP_HAS_GET) &&-                    !js_same_value(ctx, getter, desc.getter)) {-                    goto fail1;-                }-                if ((flags & JS_PROP_HAS_SET) &&-                    !js_same_value(ctx, setter, desc.setter)) {-                    goto fail1;-                }-            }-        } else if (flags & JS_PROP_HAS_VALUE) {-            if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) ==-                JS_PROP_WRITABLE && !(flags & JS_PROP_WRITABLE)) {-                /* missing-proxy-check feature */-                goto fail1;-            } else if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 &&-                !js_same_value(ctx, val, desc.value)) {-                goto fail1;-            }-        }-        if (flags & JS_PROP_HAS_WRITABLE) {-            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE |-                               JS_PROP_WRITABLE)) == JS_PROP_WRITABLE) {-                /* proxy-missing-checks */-            fail1:-                js_free_desc(ctx, &desc);-            fail:-                JS_ThrowTypeError(ctx, "proxy: inconsistent defineProperty");-                return -1;-            }-        }-        js_free_desc(ctx, &desc);-    }-    return 1;-}--static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj,-                                    JSAtom atom)-{-    JSProxyData *s;-    JSValue method, ret, atom_val;-    int res, res2, is_extensible;-    JSValueConst args[2];--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty);-    if (!s)-        return -1;-    if (JS_IsUndefined(method)) {-        return JS_DeleteProperty(ctx, s->target, atom, 0);-    }-    atom_val = JS_AtomToValue(ctx, atom);;-    if (JS_IsException(atom_val)) {-        JS_FreeValue(ctx, method);-        return -1;-    }-    args[0] = s->target;-    args[1] = atom_val;-    ret = JS_CallFree(ctx, method, s->handler, 2, args);-    JS_FreeValue(ctx, atom_val);-    if (JS_IsException(ret))-        return -1;-    res = JS_ToBoolFree(ctx, ret);-    if (res) {-        JSPropertyDescriptor desc;-        res2 = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);-        if (res2 < 0)-            return -1;-        if (res2) {-            if (!(desc.flags & JS_PROP_CONFIGURABLE))-                goto fail;-            is_extensible = JS_IsExtensible(ctx, s->target);-            if (is_extensible < 0)-                goto fail1;-            if (!is_extensible) {-                /* proxy-missing-checks */-            fail:-                JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty");-            fail1:-                js_free_desc(ctx, &desc);-                return -1;-            }-            js_free_desc(ctx, &desc);-        }-    }-    return res;-}--/* return the index of the property or -1 if not found */-static int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom)-{-    int i;-    for(i = 0; i < n; i++) {-        if (tab[i].atom == atom)-            return i;-    }-    return -1;-}--static int js_proxy_get_own_property_names(JSContext *ctx,-                                           JSPropertyEnum **ptab,-                                           uint32_t *plen,-                                           JSValueConst obj)-{-    JSProxyData *s;-    JSValue method, prop_array, val;-    uint32_t len, i, len2;-    JSPropertyEnum *tab, *tab2;-    JSAtom atom;-    JSPropertyDescriptor desc;-    int res, is_extensible, idx;--    s = get_proxy_method(ctx, &method, obj, JS_ATOM_ownKeys);-    if (!s)-        return -1;-    if (JS_IsUndefined(method)) {-        return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen,-                                      JS_VALUE_GET_OBJ(s->target),-                                      JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);-    }-    prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);-    if (JS_IsException(prop_array))-        return -1;-    tab = NULL;-    len = 0;-    tab2 = NULL;-    len2 = 0;-    if (js_get_length32(ctx, &len, prop_array))-        goto fail;-    if (len > 0) {-        tab = js_mallocz(ctx, sizeof(tab[0]) * len);-        if (!tab)-            goto fail;-    }-    for(i = 0; i < len; i++) {-        val = JS_GetPropertyUint32(ctx, prop_array, i);-        if (JS_IsException(val))-            goto fail;-        if (!JS_IsString(val) && !JS_IsSymbol(val)) {-            JS_FreeValue(ctx, val);-            JS_ThrowTypeError(ctx, "proxy: properties must be strings or symbols");-            goto fail;-        }-        atom = JS_ValueToAtom(ctx, val);-        JS_FreeValue(ctx, val);-        if (atom == JS_ATOM_NULL)-            goto fail;-        tab[i].atom = atom;-        tab[i].is_enumerable = FALSE; /* XXX: redundant? */-    }--    /* check duplicate properties (XXX: inefficient, could store the-     * properties an a temporary object to use the hash) */-    for(i = 1; i < len; i++) {-        if (find_prop_key(tab, i, tab[i].atom) >= 0) {-            JS_ThrowTypeError(ctx, "proxy: duplicate property");-            goto fail;-        }-    }--    is_extensible = JS_IsExtensible(ctx, s->target);-    if (is_extensible < 0)-        goto fail;--    /* check if there are non configurable properties */-    if (s->is_revoked) {-        JS_ThrowTypeErrorRevokedProxy(ctx);-        goto fail;-    }-    if (JS_GetOwnPropertyNamesInternal(ctx, &tab2, &len2, JS_VALUE_GET_OBJ(s->target),-                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK))-        goto fail;-    for(i = 0; i < len2; i++) {-        if (s->is_revoked) {-            JS_ThrowTypeErrorRevokedProxy(ctx);-            goto fail;-        }-        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target),-                                tab2[i].atom);-        if (res < 0)-            goto fail;-        if (res) {  /* safety, property should be found */-            js_free_desc(ctx, &desc);-            if (!(desc.flags & JS_PROP_CONFIGURABLE) || !is_extensible) {-                idx = find_prop_key(tab, len, tab2[i].atom);-                if (idx < 0) {-                    JS_ThrowTypeError(ctx, "proxy: target property must be present in proxy ownKeys");-                    goto fail;-                }-                /* mark the property as found */-                if (!is_extensible)-                    tab[idx].is_enumerable = TRUE;-            }-        }-    }-    if (!is_extensible) {-        /* check that all property in 'tab' were checked */-        for(i = 0; i < len; i++) {-            if (!tab[i].is_enumerable) {-                JS_ThrowTypeError(ctx, "proxy: property not present in target were returned by non extensible proxy");-                goto fail;-            }-        }-    }--    js_free_prop_enum(ctx, tab2, len2);-    JS_FreeValue(ctx, prop_array);-    *ptab = tab;-    *plen = len;-    return 0;- fail:-    js_free_prop_enum(ctx, tab2, len2);-    js_free_prop_enum(ctx, tab, len);-    JS_FreeValue(ctx, prop_array);-    return -1;-}--static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,-                                         JSValueConst new_target,-                                         int argc, JSValueConst *argv)-{-    JSProxyData *s;-    JSValue method, arg_array, ret;-    JSValueConst args[3];--    s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_construct);-    if (!s)-        return JS_EXCEPTION;-    if (!JS_IsConstructor(ctx, s->target))-        return JS_ThrowTypeError(ctx, "not a constructor");-    if (JS_IsUndefined(method))-        return JS_CallConstructor2(ctx, s->target, new_target, argc, argv);-    arg_array = js_create_array(ctx, argc, argv);-    if (JS_IsException(arg_array)) {-        ret = JS_EXCEPTION;-        goto fail;-    }-    args[0] = s->target;-    args[1] = arg_array;-    args[2] = new_target;-    ret = JS_Call(ctx, method, s->handler, 3, args);-    if (!JS_IsException(ret) && JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {-        JS_FreeValue(ctx, ret);-        ret = JS_ThrowTypeErrorNotAnObject(ctx);-    }- fail:-    JS_FreeValue(ctx, method);-    JS_FreeValue(ctx, arg_array);-    return ret;-}--static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,-                             JSValueConst this_obj,-                             int argc, JSValueConst *argv, int flags)-{-    JSProxyData *s;-    JSValue method, arg_array, ret;-    JSValueConst args[3];--    if (flags & JS_CALL_FLAG_CONSTRUCTOR)-        return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv);-    -    s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply);-    if (!s)-        return JS_EXCEPTION;-    if (!s->is_func) {-        JS_FreeValue(ctx, method);-        return JS_ThrowTypeError(ctx, "not a function");-    }-    if (JS_IsUndefined(method))-        return JS_Call(ctx, s->target, this_obj, argc, argv);-    arg_array = js_create_array(ctx, argc, argv);-    if (JS_IsException(arg_array)) {-        ret = JS_EXCEPTION;-        goto fail;-    }-    args[0] = s->target;-    args[1] = this_obj;-    args[2] = arg_array;-    ret = JS_Call(ctx, method, s->handler, 3, args);- fail:-    JS_FreeValue(ctx, method);-    JS_FreeValue(ctx, arg_array);-    return ret;-}--static int js_proxy_isArray(JSContext *ctx, JSValueConst obj)-{-    JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);-    if (!s)-        return FALSE;-    if (s->is_revoked) {-        JS_ThrowTypeErrorRevokedProxy(ctx);-        return -1;-    }-    return JS_IsArray(ctx, s->target);-}--static const JSClassExoticMethods js_proxy_exotic_methods = {-    .get_own_property = js_proxy_get_own_property,-    .define_own_property = js_proxy_define_own_property,-    .delete_property = js_proxy_delete_property,-    .get_own_property_names = js_proxy_get_own_property_names,-    .has_property = js_proxy_has,-    .get_property = js_proxy_get,-    .set_property = js_proxy_set,-};--static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValueConst target, handler;-    JSValue obj;-    JSProxyData *s;--    target = argv[0];-    handler = argv[1];-    if (JS_VALUE_GET_TAG(target) != JS_TAG_OBJECT ||-        JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT)-        return JS_ThrowTypeErrorNotAnObject(ctx);--    obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY);-    if (JS_IsException(obj))-        return obj;-    s = js_malloc(ctx, sizeof(JSProxyData));-    if (!s) {-        JS_FreeValue(ctx, obj);-        return JS_EXCEPTION;-    }-    s->target = JS_DupValue(ctx, target);-    s->handler = JS_DupValue(ctx, handler);-    s->is_func = JS_IsFunction(ctx, target);-    s->is_revoked = FALSE;-    JS_SetOpaque(obj, s);-    JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target));-    return obj;-}--static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv, int magic,-                               JSValue *func_data)-{-    JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY);-    if (s) {-        /* We do not free the handler and target in case they are-           referenced as constants in the C call stack */-        s->is_revoked = TRUE;-        JS_FreeValue(ctx, func_data[0]);-        func_data[0] = JS_NULL;-    }-    return JS_UNDEFINED;-}--static JSValue js_proxy_revoke_constructor(JSContext *ctx,-                                           JSValueConst proxy_obj)-{-    return JS_NewCFunctionData(ctx, js_proxy_revoke, 0, 0, 1, &proxy_obj);-}--static JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue proxy_obj, revoke_obj = JS_UNDEFINED, obj;--    proxy_obj = js_proxy_constructor(ctx, JS_UNDEFINED, argc, argv);-    if (JS_IsException(proxy_obj))-        goto fail;-    revoke_obj = js_proxy_revoke_constructor(ctx, proxy_obj);-    if (JS_IsException(revoke_obj))-        goto fail;-    obj = JS_NewObject(ctx);-    if (JS_IsException(obj))-        goto fail;-    // XXX: exceptions?-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_proxy, proxy_obj, JS_PROP_C_W_E);-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_revoke, revoke_obj, JS_PROP_C_W_E);-    return obj;- fail:-    JS_FreeValue(ctx, proxy_obj);-    JS_FreeValue(ctx, revoke_obj);-    return JS_EXCEPTION;-}--static const JSCFunctionListEntry js_proxy_funcs[] = {-    JS_CFUNC_DEF("revocable", 2, js_proxy_revocable ),-};--static const JSClassShortDef js_proxy_class_def[] = {-    { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */-};--void JS_AddIntrinsicProxy(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj1;--    if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) {-        init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY,-                         countof(js_proxy_class_def));-        rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods;-        rt->class_array[JS_CLASS_PROXY].call = js_proxy_call;-    }--    obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2,-                            JS_CFUNC_constructor, 0);-    JS_SetConstructorBit(ctx, obj1, TRUE);-    JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs,-                               countof(js_proxy_funcs));-    JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy",-                              obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-}--/* Symbol */--static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,-                                     int argc, JSValueConst *argv)-{-    JSValue str;-    JSString *p;--    if (!JS_IsUndefined(new_target))-        return JS_ThrowTypeError(ctx, "not a constructor");-    if (argc == 0 || JS_IsUndefined(argv[0])) {-        p = NULL;-    } else {-        str = JS_ToString(ctx, argv[0]);-        if (JS_IsException(str))-            return JS_EXCEPTION;-        p = JS_VALUE_GET_STRING(str);-    }-    return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL);-}--static JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL)-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_SYMBOL) {-            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_SYMBOL)-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a symbol");-}--static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValue val, ret;-    val = js_thisSymbolValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    /* XXX: use JS_ToStringInternal() with a flags */-    ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);-    JS_FreeValue(ctx, val);-    return ret;-}--static JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return js_thisSymbolValue(ctx, this_val);-}--static JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val)-{-    JSValue val, ret;-    JSAtomStruct *p;--    val = js_thisSymbolValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    p = JS_VALUE_GET_PTR(val);-    if (p->len == 0 && p->is_wide_char != 0) {-        ret = JS_UNDEFINED;-    } else {-        ret = JS_AtomToString(ctx, js_get_atom_index(ctx->rt, p));-    }-    JS_FreeValue(ctx, val);-    return ret;-}--static const JSCFunctionListEntry js_symbol_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_symbol_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_symbol_valueOf ),-    // XXX: should have writable: false-    JS_CFUNC_DEF("[Symbol.toPrimitive]", 1, js_symbol_valueOf ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Symbol", JS_PROP_CONFIGURABLE ),-    JS_CGETSET_DEF("description", js_symbol_get_description, NULL ),-};--static JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    JSValue str;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return JS_EXCEPTION;-    return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL);-}--static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSAtomStruct *p;--    if (!JS_IsSymbol(argv[0]))-        return JS_ThrowTypeError(ctx, "not a symbol");-    p = JS_VALUE_GET_PTR(argv[0]);-    if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL)-        return JS_UNDEFINED;-    return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));-}--static const JSCFunctionListEntry js_symbol_funcs[] = {-    JS_CFUNC_DEF("for", 1, js_symbol_for ),-    JS_CFUNC_DEF("keyFor", 1, js_symbol_keyFor ),-};--/* Set/Map/WeakSet/WeakMap */--typedef struct JSMapRecord {-    int ref_count; /* used during enumeration to avoid freeing the record */-    BOOL empty; /* TRUE if the record is deleted */-    struct JSMapState *map;-    struct JSMapRecord *next_weak_ref;-    struct list_head link;-    struct list_head hash_link;-    JSValue key;-    JSValue value;-} JSMapRecord;--typedef struct JSMapState {-    BOOL is_weak; /* TRUE if WeakSet/WeakMap */-    struct list_head records; /* list of JSMapRecord.link */-    uint32_t record_count;-    struct list_head *hash_table;-    uint32_t hash_size; /* must be a power of two */-    uint32_t record_count_threshold; /* count at which a hash table-                                        resize is needed */-} JSMapState;--#define MAGIC_SET (1 << 0)-#define MAGIC_WEAK (1 << 1)--static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,-                                  int argc, JSValueConst *argv, int magic)-{-    JSMapState *s;-    JSValue obj, adder = JS_UNDEFINED, iter = JS_UNDEFINED, next_method = JS_UNDEFINED;-    JSValueConst arr;-    BOOL is_set, is_weak;--    is_set = magic & MAGIC_SET;-    is_weak = ((magic & MAGIC_WEAK) != 0);-    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_MAP + magic);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    s = js_mallocz(ctx, sizeof(*s));-    if (!s)-        goto fail;-    init_list_head(&s->records);-    s->is_weak = is_weak;-    JS_SetOpaque(obj, s);-    s->hash_size = 1;-    s->hash_table = js_malloc(ctx, sizeof(s->hash_table[0]) * s->hash_size);-    if (!s->hash_table)-        goto fail;-    init_list_head(&s->hash_table[0]);-    s->record_count_threshold = 4;--    arr = JS_UNDEFINED;-    if (argc > 0)-        arr = argv[0];-    if (!JS_IsUndefined(arr) && !JS_IsNull(arr)) {-        JSValue item, ret;-        BOOL done;--        adder = JS_GetProperty(ctx, obj, is_set ? JS_ATOM_add : JS_ATOM_set);-        if (JS_IsException(adder))-            goto fail;-        if (!JS_IsFunction(ctx, adder)) {-            JS_ThrowTypeError(ctx, "set/add is not a function");-            goto fail;-        }--        iter = JS_GetIterator(ctx, arr, FALSE);-        if (JS_IsException(iter))-            goto fail;-        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);-        if (JS_IsException(next_method))-            goto fail;--        for(;;) {-            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);-            if (JS_IsException(item))-                goto fail;-            if (done) {-                JS_FreeValue(ctx, item);-                break;-            }-            if (is_set) {-                ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);-                if (JS_IsException(ret)) {-                    JS_FreeValue(ctx, item);-                    goto fail;-                }-            } else {-                JSValue key, value;-                JSValueConst args[2];-                key = JS_UNDEFINED;-                value = JS_UNDEFINED;-                if (!JS_IsObject(item)) {-                    JS_ThrowTypeErrorNotAnObject(ctx);-                    goto fail1;-                }-                key = JS_GetPropertyUint32(ctx, item, 0);-                if (JS_IsException(key))-                    goto fail1;-                value = JS_GetPropertyUint32(ctx, item, 1);-                if (JS_IsException(value))-                    goto fail1;-                args[0] = key;-                args[1] = value;-                ret = JS_Call(ctx, adder, obj, 2, args);-                if (JS_IsException(ret)) {-                fail1:-                    JS_FreeValue(ctx, item);-                    JS_FreeValue(ctx, key);-                    JS_FreeValue(ctx, value);-                    goto fail;-                }-                JS_FreeValue(ctx, key);-                JS_FreeValue(ctx, value);-            }-            JS_FreeValue(ctx, ret);-            JS_FreeValue(ctx, item);-        }-        JS_FreeValue(ctx, next_method);-        JS_FreeValue(ctx, iter);-        JS_FreeValue(ctx, adder);-    }-    return obj;- fail:-    if (JS_IsObject(iter)) {-        /* close the iterator object, preserving pending exception */-        JS_IteratorClose(ctx, iter, TRUE);-    }-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    JS_FreeValue(ctx, adder);-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--/* XXX: could normalize strings to speed up comparison */-static JSValueConst map_normalize_key(JSContext *ctx, JSValueConst key)-{-    uint32_t tag = JS_VALUE_GET_TAG(key);-    /* convert -0.0 to +0.0 */-    if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) {-        key = JS_NewInt32(ctx, 0);-    }-    return key;-}--/* XXX: better hash ? */-static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)-{-    uint32_t tag = JS_VALUE_GET_NORM_TAG(key);-    uint32_t h;-    double d;-    JSFloat64Union u;--    switch(tag) {-    case JS_TAG_BOOL:-        h = JS_VALUE_GET_INT(key);-        break;-    case JS_TAG_STRING:-        h = hash_string(JS_VALUE_GET_STRING(key), 0);-        break;-    case JS_TAG_OBJECT:-    case JS_TAG_SYMBOL:-        h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163;-        break;-    case JS_TAG_INT:-        d = JS_VALUE_GET_INT(key) * 3163;-        goto hash_float64;-    case JS_TAG_FLOAT64:-        d = JS_VALUE_GET_FLOAT64(key);-        /* normalize the NaN */-        if (isnan(d))-            d = JS_FLOAT64_NAN;-    hash_float64:-        u.d = d;-        h = (u.u32[0] ^ u.u32[1]) * 3163;-        break;-    default:-        h = 0; /* XXX: bignum support */-        break;-    }-    h ^= tag;-    return h;-}--static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s,-                                    JSValueConst key)-{-    struct list_head *el;-    JSMapRecord *mr;-    uint32_t h;-    h = map_hash_key(ctx, key) & (s->hash_size - 1);-    list_for_each(el, &s->hash_table[h]) {-        mr = list_entry(el, JSMapRecord, hash_link);-        if (js_same_value_zero(ctx, mr->key, key))-            return mr;-    }-    return NULL;-}--static void map_hash_resize(JSContext *ctx, JSMapState *s)-{-    uint32_t new_hash_size, i, h;-    size_t slack;-    struct list_head *new_hash_table, *el;-    JSMapRecord *mr;--    /* XXX: no reporting of memory allocation failure */-    if (s->hash_size == 1)-        new_hash_size = 4;-    else-        new_hash_size = s->hash_size * 2;-    new_hash_table = js_realloc2(ctx, s->hash_table,-                                 sizeof(new_hash_table[0]) * new_hash_size, &slack);-    if (!new_hash_table)-        return;-    new_hash_size += slack / sizeof(*new_hash_table);--    for(i = 0; i < new_hash_size; i++)-        init_list_head(&new_hash_table[i]);--    list_for_each(el, &s->records) {-        mr = list_entry(el, JSMapRecord, link);-        if (!mr->empty) {-            h = map_hash_key(ctx, mr->key) & (new_hash_size - 1);-            list_add_tail(&mr->hash_link, &new_hash_table[h]);-        }-    }-    s->hash_table = new_hash_table;-    s->hash_size = new_hash_size;-    s->record_count_threshold = new_hash_size * 2;-}--static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,-                                   JSValueConst key)-{-    uint32_t h;-    JSMapRecord *mr;--    mr = js_malloc(ctx, sizeof(*mr));-    if (!mr)-        return NULL;-    mr->ref_count = 1;-    mr->map = s;-    mr->empty = FALSE;-    if (s->is_weak) {-        JSObject *p = JS_VALUE_GET_OBJ(key);-        /* Add the weak reference */-        mr->next_weak_ref = p->first_weak_ref;-        p->first_weak_ref = mr;-    } else {-        JS_DupValue(ctx, key);-    }-    mr->key = (JSValue)key;-    h = map_hash_key(ctx, key) & (s->hash_size - 1);-    list_add_tail(&mr->hash_link, &s->hash_table[h]);-    list_add_tail(&mr->link, &s->records);-    s->record_count++;-    if (s->record_count >= s->record_count_threshold) {-        map_hash_resize(ctx, s);-    }-    return mr;-}--/* Remove the weak reference from the object weak-   reference list. we don't use a doubly linked list to-   save space, assuming a given object has few weak-       references to it */-static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr)-{-    JSMapRecord **pmr, *mr1;-    JSObject *p;--    p = JS_VALUE_GET_OBJ(mr->key);-    pmr = &p->first_weak_ref;-    for(;;) {-        mr1 = *pmr;-        assert(mr1 != NULL);-        if (mr1 == mr)-            break;-        pmr = &mr1->next_weak_ref;-    }-    *pmr = mr1->next_weak_ref;-}--static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)-{-    if (mr->empty)-        return;-    list_del(&mr->hash_link);-    if (s->is_weak) {-        delete_weak_ref(rt, mr);-    } else {-        JS_FreeValueRT(rt, mr->key);-    }-    JS_FreeValueRT(rt, mr->value);-    if (--mr->ref_count == 0) {-        list_del(&mr->link);-        js_free_rt(rt, mr);-    } else {-        /* keep a zombie record for iterators */-        mr->empty = TRUE;-        mr->key = JS_UNDEFINED;-        mr->value = JS_UNDEFINED;-    }-    s->record_count--;-}--static void map_decref_record(JSRuntime *rt, JSMapRecord *mr)-{-    if (--mr->ref_count == 0) {-        /* the record can be safely removed */-        assert(mr->empty);-        list_del(&mr->link);-        js_free_rt(rt, mr);-    }-}--static void reset_weak_ref(JSRuntime *rt, JSObject *p)-{-    JSMapRecord *mr, *mr_next;-    JSMapState *s;-    -    /* first pass to remove the records from the WeakMap/WeakSet-       lists */-    for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {-        s = mr->map;-        assert(s->is_weak);-        assert(!mr->empty); /* no iterator on WeakMap/WeakSet */-        list_del(&mr->hash_link);-        list_del(&mr->link);-    }-    -    /* second pass to free the values to avoid modifying the weak-       reference list while traversing it. */-    for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) {-        mr_next = mr->next_weak_ref;-        JS_FreeValueRT(rt, mr->value);-        js_free_rt(rt, mr);-    }--    p->first_weak_ref = NULL; /* fail safe */-}--static JSValue js_map_set(JSContext *ctx, JSValueConst this_val,-                          int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    JSMapRecord *mr;-    JSValueConst key, value;--    if (!s)-        return JS_EXCEPTION;-    key = map_normalize_key(ctx, argv[0]);-    if (s->is_weak && !JS_IsObject(key))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    if (magic & MAGIC_SET)-        value = JS_UNDEFINED;-    else-        value = argv[1];-    mr = map_find_record(ctx, s, key);-    if (mr) {-        JS_FreeValue(ctx, mr->value);-    } else {-        mr = map_add_record(ctx, s, key);-        if (!mr)-            return JS_EXCEPTION;-    }-    mr->value = JS_DupValue(ctx, value);-    return JS_DupValue(ctx, this_val);-}--static JSValue js_map_get(JSContext *ctx, JSValueConst this_val,-                          int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    JSMapRecord *mr;-    JSValueConst key;--    if (!s)-        return JS_EXCEPTION;-    key = map_normalize_key(ctx, argv[0]);-    mr = map_find_record(ctx, s, key);-    if (!mr)-        return JS_UNDEFINED;-    else-        return JS_DupValue(ctx, mr->value);-}--static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,-                          int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    JSMapRecord *mr;-    JSValueConst key;--    if (!s)-        return JS_EXCEPTION;-    key = map_normalize_key(ctx, argv[0]);-    mr = map_find_record(ctx, s, key);-    return JS_NewBool(ctx, (mr != NULL));-}--static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    JSMapRecord *mr;-    JSValueConst key;--    if (!s)-        return JS_EXCEPTION;-    key = map_normalize_key(ctx, argv[0]);-    mr = map_find_record(ctx, s, key);-    if (!mr)-        return JS_FALSE;-    map_delete_record(ctx->rt, s, mr);-    return JS_TRUE;-}--static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val,-                            int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    struct list_head *el, *el1;-    JSMapRecord *mr;--    if (!s)-        return JS_EXCEPTION;-    list_for_each_safe(el, el1, &s->records) {-        mr = list_entry(el, JSMapRecord, link);-        map_delete_record(ctx->rt, s, mr);-    }-    return JS_UNDEFINED;-}--static JSValue js_map_get_size(JSContext *ctx, JSValueConst this_val, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    if (!s)-        return JS_EXCEPTION;-    return JS_NewUint32(ctx, s->record_count);-}--static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    JSValueConst func, this_arg;-    JSValue ret, args[3];-    struct list_head *el;-    JSMapRecord *mr;--    if (!s)-        return JS_EXCEPTION;-    func = argv[0];-    if (argc > 1)-        this_arg = argv[1];-    else-        this_arg = JS_UNDEFINED;-    if (check_function(ctx, func))-        return JS_EXCEPTION;-    /* Note: the list can be modified while traversing it, but the-       current element is locked */-    el = s->records.next;-    while (el != &s->records) {-        mr = list_entry(el, JSMapRecord, link);-        if (!mr->empty) {-            mr->ref_count++;-            /* must duplicate in case the record is deleted */-            args[1] = JS_DupValue(ctx, mr->key);-            if (magic)-                args[0] = args[1];-            else-                args[0] = JS_DupValue(ctx, mr->value);-            args[2] = (JSValue)this_val;-            ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);-            JS_FreeValue(ctx, args[0]);-            if (!magic)-                JS_FreeValue(ctx, args[1]);-            el = el->next;-            map_decref_record(ctx->rt, mr);-            if (JS_IsException(ret))-                return ret;-            JS_FreeValue(ctx, ret);-        } else {-            el = el->next;-        }-    }-    return JS_UNDEFINED;-}--static void js_map_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p;-    JSMapState *s;-    struct list_head *el, *el1;-    JSMapRecord *mr;--    p = JS_VALUE_GET_OBJ(val);-    s = p->u.map_state;-    if (s) {-        /* if the object is deleted we are sure that no iterator is-           using it */-        list_for_each_safe(el, el1, &s->records) {-            mr = list_entry(el, JSMapRecord, link);-            if (!mr->empty) {-                if (s->is_weak)-                    delete_weak_ref(rt, mr);-                else-                    JS_FreeValueRT(rt, mr->key);-                JS_FreeValueRT(rt, mr->value);-            }-            js_free_rt(rt, mr);-        }-        js_free_rt(rt, s->hash_table);-        js_free_rt(rt, s);-    }-}--static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSMapState *s;-    struct list_head *el;-    JSMapRecord *mr;--    s = p->u.map_state;-    if (s) {-        list_for_each(el, &s->records) {-            mr = list_entry(el, JSMapRecord, link);-            if (!s->is_weak)-                JS_MarkValue(rt, mr->key, mark_func);-            JS_MarkValue(rt, mr->value, mark_func);-        }-    }-}--/* Map Iterator */--typedef struct JSMapIteratorData {-    JSValue obj;-    JSIteratorKindEnum kind;-    JSMapRecord *cur_record;-} JSMapIteratorData;--static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p;-    JSMapIteratorData *it;--    p = JS_VALUE_GET_OBJ(val);-    it = p->u.map_iterator_data;-    if (it) {-        /* During the GC sweep phase the Map finalizer may be-           called before the Map iterator finalizer */-        if (JS_IsLiveObject(rt, it->obj) && it->cur_record) {-            map_decref_record(rt, it->cur_record);-        }-        JS_FreeValueRT(rt, it->obj);-        js_free_rt(rt, it);-    }-}--static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,-                                 JS_MarkFunc *mark_func)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSMapIteratorData *it;-    it = p->u.map_iterator_data;-    if (it) {-        /* the record is already marked by the object */-        JS_MarkValue(rt, it->obj, mark_func);-    }-}--static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv, int magic)-{-    JSIteratorKindEnum kind;-    JSMapState *s;-    JSMapIteratorData *it;-    JSValue enum_obj;--    kind = magic >> 2;-    magic &= 3;-    s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);-    if (!s)-        return JS_EXCEPTION;-    enum_obj = JS_NewObjectClass(ctx, JS_CLASS_MAP_ITERATOR + magic);-    if (JS_IsException(enum_obj))-        goto fail;-    it = js_malloc(ctx, sizeof(*it));-    if (!it) {-        JS_FreeValue(ctx, enum_obj);-        goto fail;-    }-    it->obj = JS_DupValue(ctx, this_val);-    it->kind = kind;-    it->cur_record = NULL;-    JS_SetOpaque(enum_obj, it);-    return enum_obj;- fail:-    return JS_EXCEPTION;-}--static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv,-                                    BOOL *pdone, int magic)-{-    JSMapIteratorData *it;-    JSMapState *s;-    JSMapRecord *mr;-    struct list_head *el;--    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP_ITERATOR + magic);-    if (!it) {-        *pdone = FALSE;-        return JS_EXCEPTION;-    }-    if (JS_IsUndefined(it->obj))-        goto done;-    s = JS_GetOpaque(it->obj, JS_CLASS_MAP + magic);-    assert(s != NULL);-    if (!it->cur_record) {-        el = s->records.next;-    } else {-        mr = it->cur_record;-        el = mr->link.next;-        map_decref_record(ctx->rt, mr); /* the record can be freed here */-    }-    for(;;) {-        if (el == &s->records) {-            /* no more record  */-            it->cur_record = NULL;-            JS_FreeValue(ctx, it->obj);-            it->obj = JS_UNDEFINED;-        done:-            /* end of enumeration */-            *pdone = TRUE;-            return JS_UNDEFINED;-        }-        mr = list_entry(el, JSMapRecord, link);-        if (!mr->empty)-            break;-        /* get the next record */-        el = mr->link.next;-    }--    /* lock the record so that it won't be freed */-    mr->ref_count++;-    it->cur_record = mr;-    *pdone = FALSE;--    if (it->kind == JS_ITERATOR_KIND_KEY) {-        return JS_DupValue(ctx, mr->key);-    } else {-        JSValueConst args[2];-        args[0] = mr->key;-        if (magic)-            args[1] = mr->key;-        else-            args[1] = mr->value;-        if (it->kind == JS_ITERATOR_KIND_VALUE) {-            return JS_DupValue(ctx, args[1]);-        } else {-            return js_create_array(ctx, 2, args);-        }-    }-}--static const JSCFunctionListEntry js_map_funcs[] = {-    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),-};--static const JSCFunctionListEntry js_map_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, 0 ),-    JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, 0 ),-    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, 0 ),-    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, 0 ),-    JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, 0 ),-    JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, 0),-    JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, 0 ),-    JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_VALUE << 2) | 0 ),-    JS_CFUNC_MAGIC_DEF("keys", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | 0 ),-    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY_AND_VALUE << 2) | 0 ),-    JS_ALIAS_DEF("[Symbol.iterator]", "entries" ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Map", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_map_iterator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 0, js_map_iterator_next, 0 ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Map Iterator", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_set_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("add", 1, js_map_set, MAGIC_SET ),-    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_SET ),-    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_SET ),-    JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, MAGIC_SET ),-    JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),-    JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),-    JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ),-    JS_ALIAS_DEF("keys", "values" ),-    JS_ALIAS_DEF("[Symbol.iterator]", "values" ),-    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY_AND_VALUE << 2) | MAGIC_SET ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Set", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_set_iterator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 0, js_map_iterator_next, MAGIC_SET ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Set Iterator", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_weak_map_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, MAGIC_WEAK ),-    JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, MAGIC_WEAK ),-    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_WEAK ),-    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_WEAK ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakMap", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry js_weak_set_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("add", 1, js_map_set, MAGIC_SET | MAGIC_WEAK ),-    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_SET | MAGIC_WEAK ),-    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_SET | MAGIC_WEAK ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakSet", JS_PROP_CONFIGURABLE ),-};--static const JSCFunctionListEntry * const js_map_proto_funcs_ptr[6] = {-    js_map_proto_funcs,-    js_set_proto_funcs,-    js_weak_map_proto_funcs,-    js_weak_set_proto_funcs,-    js_map_iterator_proto_funcs,-    js_set_iterator_proto_funcs,-};--static const uint8_t js_map_proto_funcs_count[6] = {-    countof(js_map_proto_funcs),-    countof(js_set_proto_funcs),-    countof(js_weak_map_proto_funcs),-    countof(js_weak_set_proto_funcs),-    countof(js_map_iterator_proto_funcs),-    countof(js_set_iterator_proto_funcs),-};--void JS_AddIntrinsicMapSet(JSContext *ctx)-{-    int i;-    JSValue obj1;-    char buf[ATOM_GET_STR_BUF_SIZE];--    for(i = 0; i < 4; i++) {-        const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf),-                                         JS_ATOM_Map + i);-        ctx->class_proto[JS_CLASS_MAP + i] = JS_NewObject(ctx);-        JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP + i],-                                   js_map_proto_funcs_ptr[i],-                                   js_map_proto_funcs_count[i]);-        obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0,-                                    JS_CFUNC_constructor_magic, i);-        if (i < 2) {-            JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs,-                                       countof(js_map_funcs));-        }-        JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[JS_CLASS_MAP + i]);-    }--    for(i = 0; i < 2; i++) {-        ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] =-            JS_NewObjectProto(ctx, ctx->iterator_proto);-        JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i],-                                   js_map_proto_funcs_ptr[i + 4],-                                   js_map_proto_funcs_count[i + 4]);-    }-}--/* Generator */-static const JSCFunctionListEntry js_generator_function_proto_funcs[] = {-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "GeneratorFunction", JS_PROP_CONFIGURABLE),-};--static const JSCFunctionListEntry js_generator_proto_funcs[] = {-    JS_ITERATOR_NEXT_DEF("next", 1, js_generator_next, GEN_MAGIC_NEXT ),-    JS_ITERATOR_NEXT_DEF("return", 1, js_generator_next, GEN_MAGIC_RETURN ),-    JS_ITERATOR_NEXT_DEF("throw", 1, js_generator_next, GEN_MAGIC_THROW ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Generator", JS_PROP_CONFIGURABLE),-};--/* Promise */--typedef enum JSPromiseStateEnum {-    JS_PROMISE_PENDING,-    JS_PROMISE_FULFILLED,-    JS_PROMISE_REJECTED,-} JSPromiseStateEnum;--typedef struct JSPromiseData {-    JSPromiseStateEnum promise_state;-    /* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */-    struct list_head promise_reactions[2];-    BOOL is_handled; /* Note: only useful to debug */-    JSValue promise_result;-} JSPromiseData;--typedef struct JSPromiseFunctionDataResolved {-    int ref_count;-    BOOL already_resolved;-} JSPromiseFunctionDataResolved;--typedef struct JSPromiseFunctionData {-    JSValue promise;-    JSPromiseFunctionDataResolved *presolved;-} JSPromiseFunctionData;--typedef struct JSPromiseReactionData {-    struct list_head link; /* not used in promise_reaction_job */-    JSValue resolving_funcs[2];-    JSValue handler;-} JSPromiseReactionData;--static int js_create_resolving_functions(JSContext *ctx, JSValue *args,-                                         JSValueConst promise);--static void promise_reaction_data_free(JSRuntime *rt,-                                       JSPromiseReactionData *rd)-{-    JS_FreeValueRT(rt, rd->resolving_funcs[0]);-    JS_FreeValueRT(rt, rd->resolving_funcs[1]);-    JS_FreeValueRT(rt, rd->handler);-    js_free_rt(rt, rd);-}--static JSValue promise_reaction_job(JSContext *ctx, int argc,-                                    JSValueConst *argv)-{-    JSValueConst handler, arg, func;-    JSValue res, res2;-    BOOL is_reject;--    assert(argc == 5);-    handler = argv[2];-    is_reject = JS_ToBool(ctx, argv[3]);-    arg = argv[4];-#ifdef DUMP_PROMISE-    printf("promise_reaction_job: is_reject=%d\n", is_reject);-#endif--    if (JS_IsUndefined(handler)) {-        if (is_reject) {-            res = JS_Throw(ctx, JS_DupValue(ctx, arg));-        } else {-            res = JS_DupValue(ctx, arg);-        }-    } else {-        res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg);-    }-    is_reject = JS_IsException(res);-    if (is_reject)-        res = JS_GetException(ctx);-    func = argv[is_reject];-    /* as an extension, we support undefined as value to avoid-       creating a dummy promise in the 'await' implementation of async-       functions */-    if (!JS_IsUndefined(func)) {-        res2 = JS_Call(ctx, func, JS_UNDEFINED,-                       1, (JSValueConst *)&res);-    } else {-        res2 = JS_UNDEFINED;-    }-    JS_FreeValue(ctx, res);--    return res2;-}--void JS_SetHostPromiseRejectionTracker(JSRuntime *rt,-                                       JSHostPromiseRejectionTracker *cb,-                                       void *opaque)-{-    rt->host_promise_rejection_tracker = cb;-    rt->host_promise_rejection_tracker_opaque = opaque;-}--static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise,-                                      JSValueConst value, BOOL is_reject)-{-    JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);-    struct list_head *el, *el1;-    JSPromiseReactionData *rd;-    JSValueConst args[5];--    if (!s || s->promise_state != JS_PROMISE_PENDING)-        return; /* should never happen */-    set_value(ctx, &s->promise_result, JS_DupValue(ctx, value));-    s->promise_state = JS_PROMISE_FULFILLED + is_reject;-#ifdef DUMP_PROMISE-    printf("fulfill_or_reject_promise: is_reject=%d\n", is_reject);-#endif-    if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {-        JSRuntime *rt = ctx->rt;-        if (rt->host_promise_rejection_tracker) {-            rt->host_promise_rejection_tracker(ctx, promise, value, FALSE,-                                               rt->host_promise_rejection_tracker_opaque);-        }-    }--    list_for_each_safe(el, el1, &s->promise_reactions[is_reject]) {-        rd = list_entry(el, JSPromiseReactionData, link);-        args[0] = rd->resolving_funcs[0];-        args[1] = rd->resolving_funcs[1];-        args[2] = rd->handler;-        args[3] = JS_NewBool(ctx, is_reject);-        args[4] = value;-        JS_EnqueueJob(ctx, promise_reaction_job, 5, args);-        list_del(&rd->link);-        promise_reaction_data_free(ctx->rt, rd);-    }--    list_for_each_safe(el, el1, &s->promise_reactions[1 - is_reject]) {-        rd = list_entry(el, JSPromiseReactionData, link);-        list_del(&rd->link);-        promise_reaction_data_free(ctx->rt, rd);-    }-}--static void reject_promise(JSContext *ctx, JSValueConst promise,-                           JSValueConst value)-{-    fulfill_or_reject_promise(ctx, promise, value, TRUE);-}--static JSValue js_promise_resolve_thenable_job(JSContext *ctx,-                                               int argc, JSValueConst *argv)-{-    JSValueConst promise, thenable, then;-    JSValue args[2], res;--#ifdef DUMP_PROMISE-    printf("js_promise_resolve_thenable_job\n");-#endif-    assert(argc == 3);-    promise = argv[0];-    thenable = argv[1];-    then = argv[2];-    if (js_create_resolving_functions(ctx, args, promise) < 0)-        return JS_EXCEPTION;-    res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);-    if (JS_IsException(res)) {-        JSValue error = JS_GetException(ctx);-        res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);-        JS_FreeValue(ctx, error);-    }-    JS_FreeValue(ctx, args[0]);-    JS_FreeValue(ctx, args[1]);-    return res;-}--static void js_promise_resolve_function_free_resolved(JSRuntime *rt,-                                                      JSPromiseFunctionDataResolved *sr)-{-    if (--sr->ref_count == 0) {-        js_free_rt(rt, sr);-    }-}--static int js_create_resolving_functions(JSContext *ctx,-                                         JSValue *resolving_funcs,-                                         JSValueConst promise)--{-    JSValue obj;-    JSPromiseFunctionData *s;-    JSPromiseFunctionDataResolved *sr;-    int i, ret;--    sr = js_malloc(ctx, sizeof(*sr));-    if (!sr)-        return -1;-    sr->ref_count = 1;-    sr->already_resolved = FALSE; /* must be shared between the two functions */-    ret = 0;-    for(i = 0; i < 2; i++) {-        obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,-                                     JS_CLASS_PROMISE_RESOLVE_FUNCTION + i);-        if (JS_IsException(obj))-            goto fail;-        s = js_malloc(ctx, sizeof(*s));-        if (!s) {-            JS_FreeValue(ctx, obj);-        fail:--            if (i != 0)-                JS_FreeValue(ctx, resolving_funcs[0]);-            ret = -1;-            break;-        }-        sr->ref_count++;-        s->presolved = sr;-        s->promise = JS_DupValue(ctx, promise);-        JS_SetOpaque(obj, s);-        js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1);-        resolving_funcs[i] = obj;-    }-    js_promise_resolve_function_free_resolved(ctx->rt, sr);-    return ret;-}--static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val)-{-    JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data;-    if (s) {-        js_promise_resolve_function_free_resolved(rt, s->presolved);-        JS_FreeValueRT(rt, s->promise);-        js_free_rt(rt, s);-    }-}--static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,-                                             JS_MarkFunc *mark_func)-{-    JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data;-    if (s) {-        JS_MarkValue(rt, s->promise, mark_func);-    }-}--static JSValue js_promise_resolve_function_call(JSContext *ctx,-                                                JSValueConst func_obj,-                                                JSValueConst this_val,-                                                int argc, JSValueConst *argv,-                                                int flags)-{-    JSObject *p = JS_VALUE_GET_OBJ(func_obj);-    JSPromiseFunctionData *s;-    JSValueConst resolution, args[3];-    JSValue then;-    BOOL is_reject;--    s = p->u.promise_function_data;-    if (!s || s->presolved->already_resolved)-        return JS_UNDEFINED;-    s->presolved->already_resolved = TRUE;-    is_reject = p->class_id - JS_CLASS_PROMISE_RESOLVE_FUNCTION;-    if (argc > 0)-        resolution = argv[0];-    else-        resolution = JS_UNDEFINED;-#ifdef DUMP_PROMISE-    printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject);-    JS_DumpValue(ctx, resolution);-    printf("\n");-#endif-    if (is_reject || !JS_IsObject(resolution)) {-        goto done;-    } else if (js_same_value(ctx, resolution, s->promise)) {-        JS_ThrowTypeError(ctx, "promise self resolution");-        goto fail_reject;-    }-    then = JS_GetProperty(ctx, resolution, JS_ATOM_then);-    if (JS_IsException(then)) {-        JSValue error;-    fail_reject:-        error = JS_GetException(ctx);-        reject_promise(ctx, s->promise, error);-        JS_FreeValue(ctx, error);-    } else if (!JS_IsFunction(ctx, then)) {-        JS_FreeValue(ctx, then);-    done:-        fulfill_or_reject_promise(ctx, s->promise, resolution, is_reject);-    } else {-        args[0] = s->promise;-        args[1] = resolution;-        args[2] = then;-        JS_EnqueueJob(ctx, js_promise_resolve_thenable_job, 3, args);-        JS_FreeValue(ctx, then);-    }-    return JS_UNDEFINED;-}--static void js_promise_finalizer(JSRuntime *rt, JSValue val)-{-    JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE);-    struct list_head *el, *el1;-    int i;--    if (!s)-        return;-    for(i = 0; i < 2; i++) {-        list_for_each_safe(el, el1, &s->promise_reactions[i]) {-            JSPromiseReactionData *rd =-                list_entry(el, JSPromiseReactionData, link);-            promise_reaction_data_free(rt, rd);-        }-    }-    JS_FreeValueRT(rt, s->promise_result);-    js_free_rt(rt, s);-}--static void js_promise_mark(JSRuntime *rt, JSValueConst val,-                            JS_MarkFunc *mark_func)-{-    JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE);-    struct list_head *el;-    int i;--    if (!s)-        return;-    for(i = 0; i < 2; i++) {-        list_for_each(el, &s->promise_reactions[i]) {-            JSPromiseReactionData *rd =-                list_entry(el, JSPromiseReactionData, link);-            JS_MarkValue(rt, rd->resolving_funcs[0], mark_func);-            JS_MarkValue(rt, rd->resolving_funcs[1], mark_func);-            JS_MarkValue(rt, rd->handler, mark_func);-        }-    }-    JS_MarkValue(rt, s->promise_result, mark_func);-}--static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,-                                      int argc, JSValueConst *argv)-{-    JSValueConst executor;-    JSValue obj;-    JSPromiseData *s;-    JSValue args[2], ret;-    int i;--    executor = argv[0];-    if (check_function(ctx, executor))-        return JS_EXCEPTION;-    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_PROMISE);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    s = js_mallocz(ctx, sizeof(*s));-    if (!s)-        goto fail;-    s->promise_state = JS_PROMISE_PENDING;-    s->is_handled = FALSE;-    for(i = 0; i < 2; i++)-        init_list_head(&s->promise_reactions[i]);-    s->promise_result = JS_UNDEFINED;-    JS_SetOpaque(obj, s);-    if (js_create_resolving_functions(ctx, args, obj))-        goto fail;-    ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, (JSValueConst *)args);-    if (JS_IsException(ret)) {-        JSValue ret2, error;-        error = JS_GetException(ctx);-        ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);-        JS_FreeValue(ctx, error);-        if (JS_IsException(ret2))-            goto fail1;-        JS_FreeValue(ctx, ret2);-    }-    JS_FreeValue(ctx, ret);-    JS_FreeValue(ctx, args[0]);-    JS_FreeValue(ctx, args[1]);-    return obj;- fail1:-    JS_FreeValue(ctx, args[0]);-    JS_FreeValue(ctx, args[1]);- fail:-    JS_FreeValue(ctx, obj);-    return JS_EXCEPTION;-}--static JSValue js_promise_executor(JSContext *ctx,-                                   JSValueConst this_val,-                                   int argc, JSValueConst *argv,-                                   int magic, JSValue *func_data)-{-    int i;--    for(i = 0; i < 2; i++) {-        if (!JS_IsUndefined(func_data[i]))-            return JS_ThrowTypeError(ctx, "resolving function already set");-        func_data[i] = JS_DupValue(ctx, argv[i]);-    }-    return JS_UNDEFINED;-}--static JSValue js_promise_executor_new(JSContext *ctx)-{-    JSValueConst func_data[2];--    func_data[0] = JS_UNDEFINED;-    func_data[1] = JS_UNDEFINED;-    return JS_NewCFunctionData(ctx, js_promise_executor, 2,-                               0, 2, func_data);-}--static JSValue js_new_promise_capability(JSContext *ctx,-                                         JSValue *resolving_funcs,-                                         JSValueConst ctor)-{-    JSValue executor, result_promise;-    JSCFunctionDataRecord *s;-    int i;--    executor = js_promise_executor_new(ctx);-    if (JS_IsException(executor))-        return executor;--    if (JS_IsUndefined(ctor)) {-        result_promise = js_promise_constructor(ctx, ctor, 1,-                                                (JSValueConst *)&executor);-    } else {-        result_promise = JS_CallConstructor(ctx, ctor, 1,-                                            (JSValueConst *)&executor);-    }-    if (JS_IsException(result_promise))-        goto fail;-    s = JS_GetOpaque(executor, JS_CLASS_C_FUNCTION_DATA);-    for(i = 0; i < 2; i++) {-        if (check_function(ctx, s->data[i]))-            goto fail;-    }-    for(i = 0; i < 2; i++)-        resolving_funcs[i] = JS_DupValue(ctx, s->data[i]);-    JS_FreeValue(ctx, executor);-    return result_promise;- fail:-    JS_FreeValue(ctx, executor);-    JS_FreeValue(ctx, result_promise);-    return JS_EXCEPTION;-}--JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs)-{-    return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED);-}--static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv, int magic)-{-    JSValue result_promise, resolving_funcs[2], ret;-    BOOL is_reject = magic;--    if (!JS_IsObject(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    if (!is_reject && JS_GetOpaque(argv[0], JS_CLASS_PROMISE)) {-        JSValue ctor;-        BOOL is_same;-        ctor = JS_GetProperty(ctx, argv[0], JS_ATOM_constructor);-        if (JS_IsException(ctor))-            return ctor;-        is_same = js_same_value(ctx, ctor, this_val);-        JS_FreeValue(ctx, ctor);-        if (is_same)-            return JS_DupValue(ctx, argv[0]);-    }-    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);-    if (JS_IsException(result_promise))-        return result_promise;-    ret = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, argv);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    if (JS_IsException(ret)) {-        JS_FreeValue(ctx, result_promise);-        return ret;-    }-    JS_FreeValue(ctx, ret);-    return result_promise;-}--#if 0-static JSValue js_promise___newPromiseCapability(JSContext *ctx,-                                                 JSValueConst this_val,-                                                 int argc, JSValueConst *argv)-{-    JSValue result_promise, resolving_funcs[2], obj;-    JSValueConst ctor;-    ctor = argv[0];-    if (!JS_IsObject(ctor))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);-    if (JS_IsException(result_promise))-        return result_promise;-    obj = JS_NewObject(ctx);-    if (JS_IsException(obj)) {-        JS_FreeValue(ctx, resolving_funcs[0]);-        JS_FreeValue(ctx, resolving_funcs[1]);-        JS_FreeValue(ctx, result_promise);-        return JS_EXCEPTION;-    }-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_promise, result_promise, JS_PROP_C_W_E);-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_resolve, resolving_funcs[0], JS_PROP_C_W_E);-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_reject, resolving_funcs[1], JS_PROP_C_W_E);-    return obj;-}-#endif--static __exception int remainingElementsCount_add(JSContext *ctx,-                                                  JSValueConst resolve_element_env,-                                                  int addend)-{-    JSValue val;-    int remainingElementsCount;--    val = JS_GetPropertyUint32(ctx, resolve_element_env, 0);-    if (JS_IsException(val))-        return -1;-    if (JS_ToInt32Free(ctx, &remainingElementsCount, val))-        return -1;-    remainingElementsCount += addend;-    if (JS_SetPropertyUint32(ctx, resolve_element_env, 0,-                             JS_NewInt32(ctx, remainingElementsCount)) < 0)-        return -1;-    return (remainingElementsCount == 0);-}--#define PROMISE_MAGIC_all        0-#define PROMISE_MAGIC_allSettled 1-#define PROMISE_MAGIC_any        2--static JSValue js_promise_all_resolve_element(JSContext *ctx,-                                              JSValueConst this_val,-                                              int argc, JSValueConst *argv,-                                              int magic,-                                              JSValue *func_data)-{-    int resolve_type = magic & 3;-    int is_reject = magic & 4;-    BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]);-    JSValueConst values = func_data[2];-    JSValueConst resolve = func_data[3];-    JSValueConst resolve_element_env = func_data[4];-    JSValue ret, obj;-    int is_zero, index;-    -    if (JS_ToInt32(ctx, &index, func_data[1]))-        return JS_EXCEPTION;-    if (alreadyCalled)-        return JS_UNDEFINED;-    func_data[0] = JS_NewBool(ctx, TRUE);--    if (resolve_type == PROMISE_MAGIC_allSettled) {-        JSValue str;-        -        obj = JS_NewObject(ctx);-        if (JS_IsException(obj))-            return JS_EXCEPTION;-        str = JS_NewString(ctx, is_reject ? "rejected" : "fulfilled");-        if (JS_IsException(str))-            goto fail1;-        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_status,-                                   str,-                                   JS_PROP_C_W_E) < 0)-            goto fail1;-        if (JS_DefinePropertyValue(ctx, obj,-                                   is_reject ? JS_ATOM_reason : JS_ATOM_value,-                                   JS_DupValue(ctx, argv[0]),-                                   JS_PROP_C_W_E) < 0) {-        fail1:-            JS_FreeValue(ctx, obj);-            return JS_EXCEPTION;-        }-    } else {-        obj = JS_DupValue(ctx, argv[0]);-    }-    if (JS_DefinePropertyValueUint32(ctx, values, index,-                                     obj, JS_PROP_C_W_E) < 0)-        return JS_EXCEPTION;-    -    is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1);-    if (is_zero < 0)-        return JS_EXCEPTION;-    if (is_zero) {-        if (resolve_type == PROMISE_MAGIC_any) {-            JSValue error;-            error = js_aggregate_error_constructor(ctx, values);-            if (JS_IsException(error))-                return JS_EXCEPTION;-            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);-            JS_FreeValue(ctx, error);-        } else {-            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);-        }-        if (JS_IsException(ret))-            return ret;-        JS_FreeValue(ctx, ret);-    }-    return JS_UNDEFINED;-}--/* magic = 0: Promise.all 1: Promise.allSettled */-static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    JSValue result_promise, resolving_funcs[2], item, next_promise, ret;-    JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED;-    JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;-    JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED;-    JSValueConst then_args[2], resolve_element_data[5];-    BOOL done;-    int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);-    -    if (!JS_IsObject(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);-    if (JS_IsException(result_promise))-        return result_promise;-    promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);-    if (JS_IsException(promise_resolve) ||-        check_function(ctx, promise_resolve))-        goto fail_reject;-    iter = JS_GetIterator(ctx, argv[0], FALSE);-    if (JS_IsException(iter)) {-        JSValue error;-    fail_reject:-        error = JS_GetException(ctx);-        ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,-                       (JSValueConst *)&error);-        JS_FreeValue(ctx, error);-        if (JS_IsException(ret))-            goto fail;-        JS_FreeValue(ctx, ret);-    } else {-        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);-        if (JS_IsException(next_method))-            goto fail_reject;-        values = JS_NewArray(ctx);-        if (JS_IsException(values))-            goto fail_reject;-        resolve_element_env = JS_NewArray(ctx);-        if (JS_IsException(resolve_element_env))-            goto fail_reject;-        /* remainingElementsCount field */-        if (JS_DefinePropertyValueUint32(ctx, resolve_element_env, 0,-                                         JS_NewInt32(ctx, 1),-                                         JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)-            goto fail_reject;-        -        index = 0;-        for(;;) {-            /* XXX: conformance: should close the iterator if error on 'done'-               access, but not on 'value' access */-            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);-            if (JS_IsException(item))-                goto fail_reject;-            if (done)-                break;-            next_promise = JS_Call(ctx, promise_resolve, -                                   this_val, 1, (JSValueConst *)&item);-            JS_FreeValue(ctx, item);-            if (JS_IsException(next_promise)) {-            fail_reject1:-                JS_IteratorClose(ctx, iter, TRUE);-                goto fail_reject;-            }-            resolve_element_data[0] = JS_NewBool(ctx, FALSE);-            resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);-            resolve_element_data[2] = values;-            resolve_element_data[3] = resolving_funcs[is_promise_any];-            resolve_element_data[4] = resolve_element_env;-            resolve_element =-                JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,-                                    magic, 5, resolve_element_data);-            if (JS_IsException(resolve_element)) {-                JS_FreeValue(ctx, next_promise);-                goto fail_reject1;-            }-            -            if (magic == PROMISE_MAGIC_allSettled) {-                reject_element =-                    JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,-                                        magic | 4, 5, resolve_element_data);-                if (JS_IsException(reject_element)) {-                    JS_FreeValue(ctx, next_promise);-                    goto fail_reject1;-                }-            } else if (magic == PROMISE_MAGIC_any) {-                if (JS_DefinePropertyValueUint32(ctx, values, index,-                                                 JS_UNDEFINED, JS_PROP_C_W_E) < 0)-                    goto fail_reject1;-                reject_element = resolve_element;-                resolve_element = JS_DupValue(ctx, resolving_funcs[0]);-            } else {-                reject_element = JS_DupValue(ctx, resolving_funcs[1]);-            }--            if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) {-                JS_FreeValue(ctx, next_promise);-                JS_FreeValue(ctx, resolve_element);-                JS_FreeValue(ctx, reject_element);-                goto fail_reject1;-            }--            then_args[0] = resolve_element;-            then_args[1] = reject_element;-            ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2, then_args);-            JS_FreeValue(ctx, resolve_element);-            JS_FreeValue(ctx, reject_element);-            if (check_exception_free(ctx, ret))-                goto fail_reject1;-            index++;-        }--        is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1);-        if (is_zero < 0)-            goto fail_reject;-        if (is_zero) {-            if (magic == PROMISE_MAGIC_any) {-                JSValue error;-                error = js_aggregate_error_constructor(ctx, values);-                if (JS_IsException(error))-                    goto fail_reject;-                JS_FreeValue(ctx, values);-                values = error;-            }-            ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,-                          1, (JSValueConst *)&values);-            if (check_exception_free(ctx, ret))-                goto fail_reject;-        }-    }- done:-    JS_FreeValue(ctx, promise_resolve);-    JS_FreeValue(ctx, resolve_element_env);-    JS_FreeValue(ctx, values);-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    return result_promise;- fail:-    JS_FreeValue(ctx, result_promise);-    result_promise = JS_EXCEPTION;-    goto done;-}--static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    JSValue result_promise, resolving_funcs[2], item, next_promise, ret;-    JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED;-    JSValue promise_resolve = JS_UNDEFINED;-    BOOL done;--    if (!JS_IsObject(this_val))-        return JS_ThrowTypeErrorNotAnObject(ctx);-    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);-    if (JS_IsException(result_promise))-        return result_promise;-    promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);-    if (JS_IsException(promise_resolve) ||-        check_function(ctx, promise_resolve))-        goto fail_reject;-    iter = JS_GetIterator(ctx, argv[0], FALSE);-    if (JS_IsException(iter)) {-        JSValue error;-    fail_reject:-        error = JS_GetException(ctx);-        ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,-                       (JSValueConst *)&error);-        JS_FreeValue(ctx, error);-        if (JS_IsException(ret))-            goto fail;-        JS_FreeValue(ctx, ret);-    } else {-        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);-        if (JS_IsException(next_method))-            goto fail_reject;--        for(;;) {-            /* XXX: conformance: should close the iterator if error on 'done'-               access, but not on 'value' access */-            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);-            if (JS_IsException(item))-                goto fail_reject;-            if (done)-                break;-            next_promise = JS_Call(ctx, promise_resolve,-                                   this_val, 1, (JSValueConst *)&item);-            JS_FreeValue(ctx, item);-            if (JS_IsException(next_promise)) {-            fail_reject1:-                JS_IteratorClose(ctx, iter, TRUE);-                goto fail_reject;-            }-            ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2,-                                (JSValueConst *)resolving_funcs);-            if (check_exception_free(ctx, ret))-                goto fail_reject1;-        }-    }- done:-    JS_FreeValue(ctx, promise_resolve);-    JS_FreeValue(ctx, next_method);-    JS_FreeValue(ctx, iter);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    return result_promise;- fail:-    //JS_FreeValue(ctx, next_method); // why not???-    JS_FreeValue(ctx, result_promise);-    result_promise = JS_EXCEPTION;-    goto done;-}--static __exception int perform_promise_then(JSContext *ctx,-                                            JSValueConst promise,-                                            JSValueConst *resolve_reject,-                                            JSValueConst *cap_resolving_funcs)-{-    JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);-    JSPromiseReactionData *rd_array[2], *rd;-    int i, j;--    rd_array[0] = NULL;-    rd_array[1] = NULL;-    for(i = 0; i < 2; i++) {-        JSValueConst handler;-        rd = js_mallocz(ctx, sizeof(*rd));-        if (!rd) {-            if (i == 1)-                promise_reaction_data_free(ctx->rt, rd_array[0]);-            return -1;-        }-        for(j = 0; j < 2; j++)-            rd->resolving_funcs[j] = JS_DupValue(ctx, cap_resolving_funcs[j]);-        handler = resolve_reject[i];-        if (!JS_IsFunction(ctx, handler))-            handler = JS_UNDEFINED;-        rd->handler = JS_DupValue(ctx, handler);-        rd_array[i] = rd;-    }--    if (s->promise_state == JS_PROMISE_PENDING) {-        for(i = 0; i < 2; i++)-            list_add_tail(&rd_array[i]->link, &s->promise_reactions[i]);-    } else {-        JSValueConst args[5];-        if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {-            JSRuntime *rt = ctx->rt;-            if (rt->host_promise_rejection_tracker) {-                rt->host_promise_rejection_tracker(ctx, promise, s->promise_result,-                                                   TRUE, rt->host_promise_rejection_tracker_opaque);-            }-        }-        i = s->promise_state - JS_PROMISE_FULFILLED;-        rd = rd_array[i];-        args[0] = rd->resolving_funcs[0];-        args[1] = rd->resolving_funcs[1];-        args[2] = rd->handler;-        args[3] = JS_NewBool(ctx, i);-        args[4] = s->promise_result;-        JS_EnqueueJob(ctx, promise_reaction_job, 5, args);-        for(i = 0; i < 2; i++)-            promise_reaction_data_free(ctx->rt, rd_array[i]);-    }-    s->is_handled = TRUE;-    return 0;-}--static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    JSValue ctor, result_promise, resolving_funcs[2];-    JSPromiseData *s;-    int i, ret;--    s = JS_GetOpaque2(ctx, this_val, JS_CLASS_PROMISE);-    if (!s)-        return JS_EXCEPTION;--    ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);-    if (JS_IsException(ctor))-        return ctor;-    result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);-    JS_FreeValue(ctx, ctor);-    if (JS_IsException(result_promise))-        return result_promise;-    ret = perform_promise_then(ctx, this_val, argv,-                               (JSValueConst *)resolving_funcs);-    for(i = 0; i < 2; i++)-        JS_FreeValue(ctx, resolving_funcs[i]);-    if (ret) {-        JS_FreeValue(ctx, result_promise);-        return JS_EXCEPTION;-    }-    return result_promise;-}--static JSValue js_promise_catch(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValueConst args[2];-    args[0] = JS_UNDEFINED;-    args[1] = argv[0];-    return JS_Invoke(ctx, this_val, JS_ATOM_then, 2, args);-}--static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValueConst this_val,-                                              int argc, JSValueConst *argv,-                                              int magic, JSValue *func_data)-{-    return JS_DupValue(ctx, func_data[0]);-}--static JSValue js_promise_finally_thrower(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv,-                                          int magic, JSValue *func_data)-{-    return JS_Throw(ctx, JS_DupValue(ctx, func_data[0]));-}--static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_val,-                                            int argc, JSValueConst *argv,-                                            int magic, JSValue *func_data)-{-    JSValueConst ctor = func_data[0];-    JSValueConst onFinally = func_data[1];-    JSValue res, promise, resolving_funcs[2], ret, then_func;--    res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);-    if (JS_IsException(res))-        return res;-    promise = js_new_promise_capability(ctx, resolving_funcs, ctor);-    if (JS_IsException(promise)) {-        JS_FreeValue(ctx, res);-        return JS_EXCEPTION;-    }-    ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,-                  1, (JSValueConst*)&res);-    JS_FreeValue(ctx, res);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    if (JS_IsException(ret)) {-        JS_FreeValue(ctx, promise);-        return ret;-    }-    JS_FreeValue(ctx, ret);-    if (magic == 0) {-        then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 0,-                                        0, 1, argv);-    } else {-        then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 0,-                                        0, 1, argv);-    }-    if (JS_IsException(then_func)) {-        JS_FreeValue(ctx, promise);-        return then_func;-    }-    ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);-    JS_FreeValue(ctx, then_func);-    return ret;-}--static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValueConst onFinally = argv[0];-    JSValue ctor, ret;-    JSValue then_funcs[2];-    JSValueConst func_data[2];-    int i;--    ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);-    if (JS_IsException(ctor))-        return ctor;-    if (!JS_IsFunction(ctx, onFinally)) {-        then_funcs[0] = JS_DupValue(ctx, onFinally);-        then_funcs[1] = JS_DupValue(ctx, onFinally);-    } else {-        func_data[0] = ctor;-        func_data[1] = onFinally;-        for(i = 0; i < 2; i++) {-            then_funcs[i] = JS_NewCFunctionData(ctx, js_promise_then_finally_func, 1, i, 2, func_data);-            if (JS_IsException(then_funcs[i])) {-                if (i == 1)-                    JS_FreeValue(ctx, then_funcs[0]);-                JS_FreeValue(ctx, ctor);-                return JS_EXCEPTION;-            }-        }-    }-    JS_FreeValue(ctx, ctor);-    ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, (JSValueConst *)then_funcs);-    JS_FreeValue(ctx, then_funcs[0]);-    JS_FreeValue(ctx, then_funcs[1]);-    return ret;-}--static const JSCFunctionListEntry js_promise_funcs[] = {-    JS_CFUNC_MAGIC_DEF("resolve", 1, js_promise_resolve, 0 ),-    JS_CFUNC_MAGIC_DEF("reject", 1, js_promise_resolve, 1 ),-    JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ),-    JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),-    JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),-    JS_CFUNC_DEF("race", 1, js_promise_race ),-    //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ),-    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),-};--static const JSCFunctionListEntry js_promise_proto_funcs[] = {-    JS_CFUNC_DEF("then", 2, js_promise_then ),-    JS_CFUNC_DEF("catch", 1, js_promise_catch ),-    JS_CFUNC_DEF("finally", 1, js_promise_finally ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Promise", JS_PROP_CONFIGURABLE ),-};--/* AsyncFunction */-static const JSCFunctionListEntry js_async_function_proto_funcs[] = {-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncFunction", JS_PROP_CONFIGURABLE ),-};--static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx,-                                                  JSValueConst this_val,-                                                  int argc, JSValueConst *argv,-                                                  int magic, JSValue *func_data)-{-    return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]),-                                     JS_ToBool(ctx, func_data[0]));-}--static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,-                                                              BOOL done)-{-    JSValueConst func_data[1];--    func_data[0] = (JSValueConst)JS_NewBool(ctx, done);-    return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,-                               1, 0, 1, func_data);-}--/* AsyncIteratorPrototype */--static const JSCFunctionListEntry js_async_iterator_proto_funcs[] = {-    JS_CFUNC_DEF("[Symbol.asyncIterator]", 0, js_iterator_proto_iterator ),-};--/* AsyncFromSyncIteratorPrototype */--typedef struct JSAsyncFromSyncIteratorData {-    JSValue sync_iter;-    JSValue next_method;-} JSAsyncFromSyncIteratorData;--static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, JSValue val)-{-    JSAsyncFromSyncIteratorData *s =-        JS_GetOpaque(val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);-    if (s) {-        JS_FreeValueRT(rt, s->sync_iter);-        JS_FreeValueRT(rt, s->next_method);-        js_free_rt(rt, s);-    }-}--static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val,-                                             JS_MarkFunc *mark_func)-{-    JSAsyncFromSyncIteratorData *s =-        JS_GetOpaque(val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);-    if (s) {-        JS_MarkValue(rt, s->sync_iter, mark_func);-        JS_MarkValue(rt, s->next_method, mark_func);-    }-}--static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,-                                              JSValueConst sync_iter)-{-    JSValue async_iter, next_method;-    JSAsyncFromSyncIteratorData *s;--    next_method = JS_GetProperty(ctx, sync_iter, JS_ATOM_next);-    if (JS_IsException(next_method))-        return JS_EXCEPTION;-    async_iter = JS_NewObjectClass(ctx, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);-    if (JS_IsException(async_iter)) {-        JS_FreeValue(ctx, next_method);-        return async_iter;-    }-    s = js_mallocz(ctx, sizeof(*s));-    if (!s) {-        JS_FreeValue(ctx, async_iter);-        JS_FreeValue(ctx, next_method);-        return JS_EXCEPTION;-    }-    s->sync_iter = JS_DupValue(ctx, sync_iter);-    s->next_method = next_method;-    JS_SetOpaque(async_iter, s);-    return async_iter;-}--static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val,-                                                int argc, JSValueConst *argv,-                                                int magic)-{-    JSValue promise, resolving_funcs[2], value, err, method;-    JSAsyncFromSyncIteratorData *s;-    int done;-    int is_reject;--    promise = JS_NewPromiseCapability(ctx, resolving_funcs);-    if (JS_IsException(promise))-        return JS_EXCEPTION;-    s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);-    if (!s) {-        JS_ThrowTypeError(ctx, "not an Async-from-Sync Iterator");-        goto reject;-    }--    if (magic == GEN_MAGIC_NEXT) {-        method = JS_DupValue(ctx, s->next_method);-    } else {-        method = JS_GetProperty(ctx, s->sync_iter,-                                magic == GEN_MAGIC_RETURN ? JS_ATOM_return :-                                JS_ATOM_throw);-        if (JS_IsException(method))-            goto reject;-        if (JS_IsUndefined(method) || JS_IsNull(method)) {-            if (magic == GEN_MAGIC_RETURN) {-                err = js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), TRUE);-                is_reject = 0;-            } else {-                err = JS_DupValue(ctx, argv[0]);-                is_reject = 1;-            }-            goto done_resolve;-        }-    }-    value = JS_IteratorNext2(ctx, s->sync_iter, method,-                             argc >= 1 ? 1 : 0, argv, &done);-    JS_FreeValue(ctx, method);-    if (JS_IsException(value))-        goto reject;-    if (done == 2) {-        JSValue obj = value;-        value = JS_IteratorGetCompleteValue(ctx, obj, &done);-        JS_FreeValue(ctx, obj);-        if (JS_IsException(value))-            goto reject;-    }--    if (JS_IsException(value)) {-        JSValue res2;-    reject:-        err = JS_GetException(ctx);-        is_reject = 1;-    done_resolve:-        res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,-                       1, (JSValueConst *)&err);-        JS_FreeValue(ctx, err);-        JS_FreeValue(ctx, res2);-        JS_FreeValue(ctx, resolving_funcs[0]);-        JS_FreeValue(ctx, resolving_funcs[1]);-        return promise;-    }-    {-        JSValue value_wrapper_promise, resolve_reject[2];-        int res;--        value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,-                                                   1, (JSValueConst *)&value, 0);-        if (JS_IsException(value_wrapper_promise)) {-            JS_FreeValue(ctx, value);-            goto reject;-        }--        resolve_reject[0] =-            js_async_from_sync_iterator_unwrap_func_create(ctx, done);-        if (JS_IsException(resolve_reject[0])) {-            JS_FreeValue(ctx, value_wrapper_promise);-            goto fail;-        }-        JS_FreeValue(ctx, value);-        resolve_reject[1] = JS_UNDEFINED;--        res = perform_promise_then(ctx, value_wrapper_promise,-                                   (JSValueConst *)resolve_reject,-                                   (JSValueConst *)resolving_funcs);-        JS_FreeValue(ctx, resolve_reject[0]);-        JS_FreeValue(ctx, value_wrapper_promise);-        JS_FreeValue(ctx, resolving_funcs[0]);-        JS_FreeValue(ctx, resolving_funcs[1]);-        if (res) {-            JS_FreeValue(ctx, promise);-            return JS_EXCEPTION;-        }-    }-    return promise;- fail:-    JS_FreeValue(ctx, value);-    JS_FreeValue(ctx, resolving_funcs[0]);-    JS_FreeValue(ctx, resolving_funcs[1]);-    JS_FreeValue(ctx, promise);-    return JS_EXCEPTION;-}--static const JSCFunctionListEntry js_async_from_sync_iterator_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("next", 1, js_async_from_sync_iterator_next, GEN_MAGIC_NEXT ),-    JS_CFUNC_MAGIC_DEF("return", 1, js_async_from_sync_iterator_next, GEN_MAGIC_RETURN ),-    JS_CFUNC_MAGIC_DEF("throw", 1, js_async_from_sync_iterator_next, GEN_MAGIC_THROW ),-};--/* AsyncGeneratorFunction */--static const JSCFunctionListEntry js_async_generator_function_proto_funcs[] = {-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncGeneratorFunction", JS_PROP_CONFIGURABLE ),-};--/* AsyncGenerator prototype */--static const JSCFunctionListEntry js_async_generator_proto_funcs[] = {-    JS_CFUNC_MAGIC_DEF("next", 1, js_async_generator_next, GEN_MAGIC_NEXT ),-    JS_CFUNC_MAGIC_DEF("return", 1, js_async_generator_next, GEN_MAGIC_RETURN ),-    JS_CFUNC_MAGIC_DEF("throw", 1, js_async_generator_next, GEN_MAGIC_THROW ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncGenerator", JS_PROP_CONFIGURABLE ),-};--static JSClassShortDef const js_async_class_def[] = {-    { JS_ATOM_Promise, js_promise_finalizer, js_promise_mark },                      /* JS_CLASS_PROMISE */-    { JS_ATOM_PromiseResolveFunction, js_promise_resolve_function_finalizer, js_promise_resolve_function_mark }, /* JS_CLASS_PROMISE_RESOLVE_FUNCTION */-    { JS_ATOM_PromiseRejectFunction, js_promise_resolve_function_finalizer, js_promise_resolve_function_mark }, /* JS_CLASS_PROMISE_REJECT_FUNCTION */-    { JS_ATOM_AsyncFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_ASYNC_FUNCTION */-    { JS_ATOM_AsyncFunctionResolve, js_async_function_resolve_finalizer, js_async_function_resolve_mark }, /* JS_CLASS_ASYNC_FUNCTION_RESOLVE */-    { JS_ATOM_AsyncFunctionReject, js_async_function_resolve_finalizer, js_async_function_resolve_mark }, /* JS_CLASS_ASYNC_FUNCTION_REJECT */-    { JS_ATOM_empty_string, js_async_from_sync_iterator_finalizer, js_async_from_sync_iterator_mark }, /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */-    { JS_ATOM_AsyncGeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_ASYNC_GENERATOR_FUNCTION */-    { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark },  /* JS_CLASS_ASYNC_GENERATOR */-};--void JS_AddIntrinsicPromise(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj1;--    if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) {-        init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE,-                         countof(js_async_class_def));-        rt->class_array[JS_CLASS_PROMISE_RESOLVE_FUNCTION].call = js_promise_resolve_function_call;-        rt->class_array[JS_CLASS_PROMISE_REJECT_FUNCTION].call = js_promise_resolve_function_call;-        rt->class_array[JS_CLASS_ASYNC_FUNCTION].call = js_async_function_call;-        rt->class_array[JS_CLASS_ASYNC_FUNCTION_RESOLVE].call = js_async_function_resolve_call;-        rt->class_array[JS_CLASS_ASYNC_FUNCTION_REJECT].call = js_async_function_resolve_call;-        rt->class_array[JS_CLASS_ASYNC_GENERATOR_FUNCTION].call = js_async_generator_function_call;-    }--    /* Promise */-    ctx->class_proto[JS_CLASS_PROMISE] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_PROMISE],-                               js_promise_proto_funcs,-                               countof(js_promise_proto_funcs));-    obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1,-                            JS_CFUNC_constructor, 0);-    ctx->promise_ctor = JS_DupValue(ctx, obj1);-    JS_SetPropertyFunctionList(ctx, obj1,-                               js_promise_funcs,-                               countof(js_promise_funcs));-    JS_NewGlobalCConstructor2(ctx, obj1, "Promise",-                              ctx->class_proto[JS_CLASS_PROMISE]);--    /* AsyncFunction */-    ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);-    obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,-                            "AsyncFunction", 1,-                            JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC,-                            ctx->function_ctor);-    JS_SetPropertyFunctionList(ctx,-                               ctx->class_proto[JS_CLASS_ASYNC_FUNCTION],-                               js_async_function_proto_funcs,-                               countof(js_async_function_proto_funcs));-    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_FUNCTION],-                       0, JS_PROP_CONFIGURABLE);-    JS_FreeValue(ctx, obj1);--    /* AsyncIteratorPrototype */-    ctx->async_iterator_proto = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->async_iterator_proto,-                               js_async_iterator_proto_funcs,-                               countof(js_async_iterator_proto_funcs));--    /* AsyncFromSyncIteratorPrototype */-    ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR] =-        JS_NewObjectProto(ctx, ctx->async_iterator_proto);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR],-                               js_async_from_sync_iterator_proto_funcs,-                               countof(js_async_from_sync_iterator_proto_funcs));--    /* AsyncGeneratorPrototype */-    ctx->class_proto[JS_CLASS_ASYNC_GENERATOR] =-        JS_NewObjectProto(ctx, ctx->async_iterator_proto);-    JS_SetPropertyFunctionList(ctx,-                               ctx->class_proto[JS_CLASS_ASYNC_GENERATOR],-                               js_async_generator_proto_funcs,-                               countof(js_async_generator_proto_funcs));--    /* AsyncGeneratorFunction */-    ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] =-        JS_NewObjectProto(ctx, ctx->function_proto);-    obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,-                            "AsyncGeneratorFunction", 1,-                            JS_CFUNC_constructor_or_func_magic,-                            JS_FUNC_ASYNC_GENERATOR,-                            ctx->function_ctor);-    JS_SetPropertyFunctionList(ctx,-                               ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],-                               js_async_generator_function_proto_funcs,-                               countof(js_async_generator_function_proto_funcs));-    JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],-                       ctx->class_proto[JS_CLASS_ASYNC_GENERATOR],-                       JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE);-    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],-                       0, JS_PROP_CONFIGURABLE);-    JS_FreeValue(ctx, obj1);-}--/* URI handling */--static int string_get_hex(JSString *p, int k, int n) {-    int c = 0, h;-    while (n-- > 0) {-        if ((h = from_hex(string_get(p, k++))) < 0)-            return -1;-        c = (c << 4) | h;-    }-    return c;-}--static int isURIReserved(int c) {-    return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL;-}--static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext *ctx, const char *fmt, ...)-{-    va_list ap;--    va_start(ap, fmt);-    JS_ThrowError(ctx, JS_URI_ERROR, fmt, ap);-    va_end(ap);-    return -1;-}--static int hex_decode(JSContext *ctx, JSString *p, int k) {-    int c;--    if (k >= p->len || string_get(p, k) != '%')-        return js_throw_URIError(ctx, "expecting %%");-    if (k + 2 >= p->len || (c = string_get_hex(p, k + 1, 2)) < 0)-        return js_throw_URIError(ctx, "expecting hex digit");--    return c;-}--static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv, int isComponent)-{-    JSValue str;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int k, c, c1, n, c_min;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return str;--    string_buffer_init(ctx, b, 0);--    p = JS_VALUE_GET_STRING(str);-    for (k = 0; k < p->len;) {-        c = string_get(p, k);-        if (c == '%') {-            c = hex_decode(ctx, p, k);-            if (c < 0)-                goto fail;-            k += 3;-            if (c < 0x80) {-                if (!isComponent && isURIReserved(c)) {-                    c = '%';-                    k -= 2;-                }-            } else {-                /* Decode URI-encoded UTF-8 sequence */-                if (c >= 0xc0 && c <= 0xdf) {-                    n = 1;-                    c_min = 0x80;-                    c &= 0x1f;-                } else if (c >= 0xe0 && c <= 0xef) {-                    n = 2;-                    c_min = 0x800;-                    c &= 0xf;-                } else if (c >= 0xf0 && c <= 0xf7) {-                    n = 3;-                    c_min = 0x10000;-                    c &= 0x7;-                } else {-                    n = 0;-                    c_min = 1;-                    c = 0;-                }-                while (n-- > 0) {-                    c1 = hex_decode(ctx, p, k);-                    if (c1 < 0)-                        goto fail;-                    k += 3;-                    if ((c1 & 0xc0) != 0x80) {-                        c = 0;-                        break;-                    }-                    c = (c << 6) | (c1 & 0x3f);-                }-                if (c < c_min || c > 0x10FFFF ||-                    (c >= 0xd800 && c < 0xe000)) {-                    js_throw_URIError(ctx, "malformed UTF-8");-                    goto fail;-                }-            }-        } else {-            k++;-        }-        string_buffer_putc(b, c);-    }-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);--fail:-    JS_FreeValue(ctx, str);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static int isUnescaped(int c) {-    static char const unescaped_chars[] =-        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"-        "abcdefghijklmnopqrstuvwxyz"-        "0123456789"-        "@*_+-./";-    return c < 0x100 &&-        memchr(unescaped_chars, c, sizeof(unescaped_chars) - 1);-}--static int isURIUnescaped(int c, int isComponent) {-    return c < 0x100 &&-        ((c >= 0x61 && c <= 0x7a) ||-         (c >= 0x41 && c <= 0x5a) ||-         (c >= 0x30 && c <= 0x39) ||-         memchr("-_.!~*'()", c, sizeof("-_.!~*'()") - 1) != NULL ||-         (!isComponent && isURIReserved(c)));-}--static int encodeURI_hex(StringBuffer *b, int c) {-    uint8_t buf[6];-    int n = 0;-    const char *hex = "0123456789ABCDEF";--    buf[n++] = '%';-    if (c >= 256) {-        buf[n++] = 'u';-        buf[n++] = hex[(c >> 12) & 15];-        buf[n++] = hex[(c >>  8) & 15];-    }-    buf[n++] = hex[(c >> 4) & 15];-    buf[n++] = hex[(c >> 0) & 15];-    return string_buffer_write8(b, buf, n);-}--static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv,-                                   int isComponent)-{-    JSValue str;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int k, c, c1;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return str;--    p = JS_VALUE_GET_STRING(str);-    string_buffer_init(ctx, b, p->len);-    for (k = 0; k < p->len;) {-        c = string_get(p, k);-        k++;-        if (isURIUnescaped(c, isComponent)) {-            string_buffer_putc16(b, c);-        } else {-            if (c >= 0xdc00 && c <= 0xdfff) {-                js_throw_URIError(ctx, "invalid character");-                goto fail;-            } else if (c >= 0xd800 && c <= 0xdbff) {-                if (k >= p->len) {-                    js_throw_URIError(ctx, "expecting surrogate pair");-                    goto fail;-                }-                c1 = string_get(p, k);-                k++;-                if (c1 < 0xdc00 || c1 > 0xdfff) {-                    js_throw_URIError(ctx, "expecting surrogate pair");-                    goto fail;-                }-                c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;-            }-            if (c < 0x80) {-                encodeURI_hex(b, c);-            } else {-                /* XXX: use C UTF-8 conversion ? */-                if (c < 0x800) {-                    encodeURI_hex(b, (c >> 6) | 0xc0);-                } else {-                    if (c < 0x10000) {-                        encodeURI_hex(b, (c >> 12) | 0xe0);-                    } else {-                        encodeURI_hex(b, (c >> 18) | 0xf0);-                        encodeURI_hex(b, ((c >> 12) & 0x3f) | 0x80);-                    }-                    encodeURI_hex(b, ((c >> 6) & 0x3f) | 0x80);-                }-                encodeURI_hex(b, (c & 0x3f) | 0x80);-            }-        }-    }-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);--fail:-    JS_FreeValue(ctx, str);-    string_buffer_free(b);-    return JS_EXCEPTION;-}--static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    JSValue str;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int i, len, c;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return str;--    p = JS_VALUE_GET_STRING(str);-    string_buffer_init(ctx, b, p->len);-    for (i = 0, len = p->len; i < len; i++) {-        c = string_get(p, i);-        if (isUnescaped(c)) {-            string_buffer_putc16(b, c);-        } else {-            encodeURI_hex(b, c);-        }-    }-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);-}--static JSValue js_global_unescape(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValue str;-    StringBuffer b_s, *b = &b_s;-    JSString *p;-    int i, len, c, n;--    str = JS_ToString(ctx, argv[0]);-    if (JS_IsException(str))-        return str;--    string_buffer_init(ctx, b, 0);-    p = JS_VALUE_GET_STRING(str);-    for (i = 0, len = p->len; i < len; i++) {-        c = string_get(p, i);-        if (c == '%') {-            if (i + 6 <= len-            &&  string_get(p, i + 1) == 'u'-            &&  (n = string_get_hex(p, i + 2, 4)) >= 0) {-                c = n;-                i += 6 - 1;-            } else-            if (i + 3 <= len-            &&  (n = string_get_hex(p, i + 1, 2)) >= 0) {-                c = n;-                i += 3 - 1;-            }-        }-        string_buffer_putc16(b, c);-    }-    JS_FreeValue(ctx, str);-    return string_buffer_end(b);-}--/* global object */--static const JSCFunctionListEntry js_global_funcs[] = {-    JS_CFUNC_DEF("parseInt", 2, js_parseInt ),-    JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ),-    JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ),-    JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ),--    JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ),-    JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ),-    JS_CFUNC_MAGIC_DEF("encodeURI", 1, js_global_encodeURI, 0 ),-    JS_CFUNC_MAGIC_DEF("encodeURIComponent", 1, js_global_encodeURI, 1 ),-    JS_CFUNC_DEF("escape", 1, js_global_escape ),-    JS_CFUNC_DEF("unescape", 1, js_global_unescape ),-    JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),-    JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),-    JS_PROP_UNDEFINED_DEF("undefined", 0 ),--    /* for the 'Date' implementation */-    JS_CFUNC_DEF("__date_clock", 0, js___date_clock ),-    //JS_CFUNC_DEF("__date_now", 0, js___date_now ),-    //JS_CFUNC_DEF("__date_getTimezoneOffset", 1, js___date_getTimezoneOffset ),-    //JS_CFUNC_DEF("__date_create", 3, js___date_create ),-};--/* Date */--static int64_t math_mod(int64_t a, int64_t b) {-    /* return positive modulo */-    int64_t m = a % b;-    return m + (m < 0) * b;-}--static int64_t floor_div(int64_t a, int64_t b) {-    /* integer division rounding toward -Infinity */-    int64_t m = a % b;-    return (a - (m + (m < 0) * b)) / b;-}--static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv);--static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)-{-    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_DATE && JS_IsNumber(p->u.object_data))-            return JS_ToFloat64(ctx, valp, p->u.object_data);-    }-    JS_ThrowTypeError(ctx, "not a Date object");-    return -1;-}--static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double v)-{-    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_DATE) {-            JS_FreeValue(ctx, p->u.object_data);-            p->u.object_data = __JS_NewFloat64(ctx, v);-            return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a Date object");-}--static int64_t days_from_year(int64_t y) {-    return 365 * (y - 1970) + floor_div(y - 1969, 4) --        floor_div(y - 1901, 100) + floor_div(y - 1601, 400);-}--static int64_t days_in_year(int64_t y) {-    return 365 + !(y % 4) - !(y % 100) + !(y % 400);-}--/* return the year, update days */-static int64_t year_from_days(int64_t *days) {-    int64_t y, d1, nd, d = *days;-    y = floor_div(d * 10000, 3652425) + 1970;-    /* the initial approximation is very good, so only a few-       iterations are necessary */-    for(;;) {-        d1 = d - days_from_year(y);-        if (d1 < 0) {-            y--;-            d1 += days_in_year(y);-        } else {-            nd = days_in_year(y);-            if (d1 < nd)-                break;-            d1 -= nd;-            y++;-        }-    }-    *days = d1;-    return y;-}--static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };-static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";-static char const day_names[] = "SunMonTueWedThuFriSat";--static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,-                                       int64_t fields[9], int is_local, int force)-{-    double dval;-    int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;--    if (JS_ThisTimeValue(ctx, &dval, obj))-        return -1;--    if (isnan(dval)) {-        if (!force)-            return FALSE; /* NaN */-        d = 0;        /* initialize all fields to 0 */-    } else {-        d = dval;-        if (is_local) {-            tz = -getTimezoneOffset(d);-            d += tz * 60000;-        }-    }--    /* result is >= 0, we can use % */-    h = math_mod(d, 86400000);-    days = (d - h) / 86400000;-    ms = h % 1000;-    h = (h - ms) / 1000;-    s = h % 60;-    h = (h - s) / 60;-    m = h % 60;-    h = (h - m) / 60;-    wd = math_mod(days + 4, 7); /* week day */-    y = year_from_days(&days);--    for(i = 0; i < 11; i++) {-        md = month_days[i];-        if (i == 1)-            md += days_in_year(y) - 365;-        if (days < md)-            break;-        days -= md;-    }-    fields[0] = y;-    fields[1] = i;-    fields[2] = days + 1;-    fields[3] = h;-    fields[4] = m;-    fields[5] = s;-    fields[6] = ms;-    fields[7] = wd;-    fields[8] = tz;-    return TRUE;-}--static double time_clip(double t) {-    if (t >= -8.64e15 && t <= 8.64e15)-        return trunc(t) + 0.0;  /* convert -0 to +0 */-    else-        return NAN;-}--static double set_date_fields(int64_t fields[], int is_local) {-    int64_t days, y, m, md, h, d, i;--    i = fields[1];-    m = math_mod(i, 12);-    y = fields[0] + (i - m) / 12;-    days = days_from_year(y);--    for(i = 0; i < m; i++) {-        md = month_days[i];-        if (i == 1)-            md += days_in_year(y) - 365;-        days += md;-    }-    days += fields[2] - 1;-    h = ((fields[3] * 60 + fields[4]) * 60 + fields[5]) * 1000 + fields[6];-    d = days * 86400000 + h;-    if (is_local)-        d += getTimezoneOffset(d) * 60000;-    return time_clip(d);-}--static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    // get_date_field(obj, n, is_local)-    int64_t fields[9];-    int res, n, is_local;--    is_local = magic & 0x0F;-    n = (magic >> 4) & 0x0F;-    res = get_date_fields(ctx, this_val, fields, is_local, 0);-    if (res < 0)-        return JS_EXCEPTION;-    if (!res)-        return JS_NAN;--    if (magic & 0x100) {    // getYear-        fields[0] -= 1900;-    }-    return JS_NewInt64(ctx, fields[n]);-}--static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    // _field(obj, first_field, end_field, args, is_local)-    int64_t fields[9];-    int res, first_field, end_field, is_local, i, n;-    double d, a;--    d = NAN;-    first_field = (magic >> 8) & 0x0F;-    end_field = (magic >> 4) & 0x0F;-    is_local = magic & 0x0F;--    res = get_date_fields(ctx, this_val, fields, is_local, first_field == 0);-    if (res < 0)-        return JS_EXCEPTION;-    if (res && argc > 0) {-        n = end_field - first_field;-        if (argc < n)-            n = argc;-        for(i = 0; i < n; i++) {-            if (JS_ToFloat64(ctx, &a, argv[i]))-                return JS_EXCEPTION;-            if (!isfinite(a))-                goto done;-            fields[first_field + i] = trunc(a);-        }-        d = set_date_fields(fields, is_local);-    }-done:-    return JS_SetThisTimeValue(ctx, this_val, d);-}--/* fmt:-   0: toUTCString: "Tue, 02 Jan 2018 23:04:46 GMT"-   1: toString: "Wed Jan 03 2018 00:05:22 GMT+0100 (CET)"-   2: toISOString: "2018-01-02T23:02:56.927Z"-   3: toLocaleString: "1/2/2018, 11:40:40 PM"-   part: 1=date, 2=time 3=all-   XXX: should use a variant of strftime().- */-static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv, int magic)-{-    // _string(obj, fmt, part)-    char buf[64];-    int64_t fields[9];-    int res, fmt, part, pos;-    int y, mon, d, h, m, s, ms, wd, tz;--    fmt = (magic >> 4) & 0x0F;-    part = magic & 0x0F;--    res = get_date_fields(ctx, this_val, fields, fmt & 1, 0);-    if (res < 0)-        return JS_EXCEPTION;-    if (!res) {-        if (fmt == 2)-            return JS_ThrowRangeError(ctx, "Date value is NaN");-        else-            return JS_NewString(ctx, "Invalid Date");-    }--    y = fields[0];-    mon = fields[1];-    d = fields[2];-    h = fields[3];-    m = fields[4];-    s = fields[5];-    ms = fields[6];-    wd = fields[7];-    tz = fields[8];--    pos = 0;--    if (part & 1) { /* date part */-        switch(fmt) {-        case 0:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%.3s, %02d %.3s %0*d ",-                            day_names + wd * 3, d,-                            month_names + mon * 3, 4 + (y < 0), y);-            break;-        case 1:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%.3s %.3s %02d %0*d",-                            day_names + wd * 3,-                            month_names + mon * 3, d, 4 + (y < 0), y);-            if (part == 3) {-                buf[pos++] = ' ';-            }-            break;-        case 2:-            if (y >= 0 && y <= 9999) {-                pos += snprintf(buf + pos, sizeof(buf) - pos,-                                "%04d", y);-            } else {-                pos += snprintf(buf + pos, sizeof(buf) - pos,-                                "%+07d", y);-            }-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "-%02d-%02dT", mon + 1, d);-            break;-        case 3:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d/%02d/%0*d", mon + 1, d, 4 + (y < 0), y);-            if (part == 3) {-                buf[pos++] = ',';-                buf[pos++] = ' ';-            }-            break;-        }-    }-    if (part & 2) { /* time part */-        switch(fmt) {-        case 0:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d:%02d:%02d GMT", h, m, s);-            break;-        case 1:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d:%02d:%02d GMT", h, m, s);-            if (tz < 0) {-                buf[pos++] = '-';-                tz = -tz;-            } else {-                buf[pos++] = '+';-            }-            /* tz is >= 0, can use % */-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d%02d", tz / 60, tz % 60);-            /* XXX: tack the time zone code? */-            break;-        case 2:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d:%02d:%02d.%03dZ", h, m, s, ms);-            break;-        case 3:-            pos += snprintf(buf + pos, sizeof(buf) - pos,-                            "%02d:%02d:%02d %cM", (h + 1) % 12 - 1, m, s,-                            (h < 12) ? 'A' : 'P');-            break;-        }-    }-    return JS_NewStringLen(ctx, buf, pos);-}--/* OS dependent: return the UTC time in ms since 1970. */-static int64_t date_now(void) {-    struct timeval tv;-    gettimeofday(&tv, NULL);-    return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);-}--static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,-                                   int argc, JSValueConst *argv)-{-    // Date(y, mon, d, h, m, s, ms)-    JSValue rv;-    int i, n;-    double a, val;--    if (JS_IsUndefined(new_target)) {-        /* invoked as function */-        argc = 0;-    }-    n = argc;-    if (n == 0) {-        val = date_now();-    } else if (n == 1) {-        JSValue v, dv;-        if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) {-            JSObject *p = JS_VALUE_GET_OBJ(argv[0]);-            if (p->class_id == JS_CLASS_DATE && JS_IsNumber(p->u.object_data)) {-                if (JS_ToFloat64(ctx, &val, p->u.object_data))-                    return JS_EXCEPTION;-                val = time_clip(val);-                goto has_val;-            }-        }-        v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);-        if (JS_IsString(v)) {-            dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);-            JS_FreeValue(ctx, v);-            if (JS_IsException(dv))-                return JS_EXCEPTION;-            if (JS_ToFloat64Free(ctx, &val, dv))-                return JS_EXCEPTION;-        } else {-            if (JS_ToFloat64Free(ctx, &val, v))-                return JS_EXCEPTION;-        }-        val = time_clip(val);-    } else {-        int64_t fields[] = { 0, 0, 1, 0, 0, 0, 0 };-        if (n > 7)-            n = 7;-        for(i = 0; i < n; i++) {-            if (JS_ToFloat64(ctx, &a, argv[i]))-                return JS_EXCEPTION;-            if (!isfinite(a))-                break;-            fields[i] = trunc(a);-            if (i == 0 && fields[0] >= 0 && fields[0] < 100)-                fields[0] += 1900;-        }-        val = (i == n) ? set_date_fields(fields, 1) : NAN;-    }-has_val:-#if 0-    JSValueConst args[3];-    args[0] = new_target;-    args[1] = ctx->class_proto[JS_CLASS_DATE];-    args[2] = __JS_NewFloat64(ctx, val);-    rv = js___date_create(ctx, JS_UNDEFINED, 3, args);-#else-    rv = js_create_from_ctor(ctx, new_target, JS_CLASS_DATE);-    if (!JS_IsException(rv))-        JS_SetObjectData(ctx, rv, __JS_NewFloat64(ctx, val));-#endif-    if (!JS_IsException(rv) && JS_IsUndefined(new_target)) {-        /* invoked as a function, return (new Date()).toString(); */-        JSValue s;-        s = get_date_string(ctx, rv, 0, NULL, 0x13);-        JS_FreeValue(ctx, rv);-        rv = s;-    }-    return rv;-}--static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,-                           int argc, JSValueConst *argv)-{-    // UTC(y, mon, d, h, m, s, ms)-    int64_t fields[] = { 0, 0, 1, 0, 0, 0, 0 };-    int i, n;-    double a;--    n = argc;-    if (n == 0)-        return JS_NAN;-    if (n > 7)-        n = 7;-    for(i = 0; i < n; i++) {-        if (JS_ToFloat64(ctx, &a, argv[i]))-            return JS_EXCEPTION;-        if (!isfinite(a))-            return JS_NAN;-        fields[i] = trunc(a);-        if (i == 0 && fields[0] >= 0 && fields[0] < 100)-            fields[0] += 1900;-    }-    return __JS_NewFloat64(ctx, set_date_fields(fields, 0));-}--static void string_skip_spaces(JSString *sp, int *pp) {-    while (*pp < sp->len && string_get(sp, *pp) == ' ')-        *pp += 1;-}--static void string_skip_non_spaces(JSString *sp, int *pp) {-    while (*pp < sp->len && string_get(sp, *pp) != ' ')-        *pp += 1;-}--/* parse a numeric field */-static int string_get_field(JSString *sp, int *pp, int64_t *pval) {-    int64_t v = 0;-    int c, p = *pp;--    /* skip non digits, should only skip spaces? */-    while (p < sp->len) {-        c = string_get(sp, p);-        if (c >= '0' && c <= '9')-            break;-        p++;-    }-    if (p >= sp->len)-        return -1;-    while (p < sp->len) {-        c = string_get(sp, p);-        if (!(c >= '0' && c <= '9'))-            break;-        v = v * 10 + c - '0';-        p++;-    }-    *pval = v;-    *pp = p;-    return 0;-}--/* parse a fixed width numeric field */-static int string_get_digits(JSString *sp, int *pp, int n, int64_t *pval) {-    int64_t v = 0;-    int i, c, p = *pp;--    for(i = 0; i < n; i++) {-        if (p >= sp->len)-            return -1;-        c = string_get(sp, p);-        if (!(c >= '0' && c <= '9'))-            return -1;-        v = v * 10 + c - '0';-        p++;-    }-    *pval = v;-    *pp = p;-    return 0;-}--/* parse a signed numeric field */-static int string_get_signed_field(JSString *sp, int *pp, int64_t *pval) {-    int sgn, res;--    if (*pp >= sp->len)-        return -1;--    sgn = string_get(sp, *pp);-    if (sgn == '-' || sgn == '+')-        *pp += 1;--    res = string_get_field(sp, pp, pval);-    if (res == 0 && sgn == '-')-        *pval = -*pval;-    return res;-}--static int find_abbrev(JSString *sp, int p, const char *list, int count) {-    int n, i;--    if (p + 3 <= sp->len) {-        for (n = 0; n < count; n++) {-            for (i = 0; i < 3; i++) {-                if (string_get(sp, p + i) != month_names[n * 3 + i])-                    goto next;-            }-            return n;-        next:;-        }-    }-    return -1;-}--static int string_get_month(JSString *sp, int *pp, int64_t *pval) {-    int n;--    string_skip_spaces(sp, pp);-    n = find_abbrev(sp, *pp, month_names, 12);-    if (n < 0)-        return -1;--    *pval = n;-    *pp += 3;-    return 0;-}--static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,-                             int argc, JSValueConst *argv)-{-    // parse(s)-    JSValue s, rv;-    int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 };-    int64_t tz, hh, mm;-    double d;-    int p, i, c, sgn;-    JSString *sp;-    BOOL is_local;-    -    rv = JS_NAN;--    s = JS_ToString(ctx, argv[0]);-    if (JS_IsException(s))-        return JS_EXCEPTION;-    -    sp = JS_VALUE_GET_STRING(s);-    p = 0;-    if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) {-        /* ISO format */-        /* year field can be negative */-        /* XXX: could be stricter */-        if (string_get_signed_field(sp, &p, &fields[0]))-            goto done;--        is_local = TRUE;-        for (i = 1; i < 6; i++) {-            if (string_get_field(sp, &p, &fields[i]))-                break;-        }-        if (i <= 3) {-            /* no time: UTC by default */-            is_local = FALSE;-        } else if (i == 6 && p < sp->len && string_get(sp, p) == '.') {-            /* parse milliseconds as a fractional part, round to nearest */-            /* XXX: the spec does not indicate which rounding should be used */-            int mul = 1000, ms = 0;-            while (++p < sp->len) {-                int c = string_get(sp, p);-                if (!(c >= '0' && c <= '9'))-                    break;-                if (mul == 1 && c >= '5')-                    ms += 1;-                ms += (c - '0') * (mul /= 10);-            }-            fields[6] = ms;-        }-        fields[1] -= 1;--        /* parse the time zone offset if present: [+-]HH:mm */-        tz = 0;-        if (p < sp->len) {-            sgn = string_get(sp, p);-            if (sgn == '+' || sgn == '-') {-                if (string_get_field(sp, &p, &hh))-                    goto done;-                if (string_get_field(sp, &p, &mm))-                    goto done;-                tz = hh * 60 + mm;-                if (sgn == '-')-                    tz = -tz;-                is_local = FALSE;-            } else if (sgn == 'Z') {-                is_local = FALSE;-            }-        }-    } else {-        /* toString or toUTCString format */-        /* skip the day of the week */-        string_skip_non_spaces(sp, &p);-        string_skip_spaces(sp, &p);-        if (p >= sp->len)-            goto done;-        c = string_get(sp, p);-        if (c >= '0' && c <= '9') {-            /* day of month first */-            if (string_get_field(sp, &p, &fields[2]))-                goto done;-            if (string_get_month(sp, &p, &fields[1]))-                goto done;-        } else {-            /* month first */-            if (string_get_month(sp, &p, &fields[1]))-                goto done;-            if (string_get_field(sp, &p, &fields[2]))-                goto done;-        }-        string_skip_spaces(sp, &p);-        if (string_get_signed_field(sp, &p, &fields[0]))-            goto done;--        /* hour, min, seconds */-        for(i = 0; i < 3; i++) {-            if (string_get_field(sp, &p, &fields[3 + i]))-                goto done;-        }-        // XXX: parse optional milliseconds?--        /* parse the time zone offset if present: [+-]HHmm */-        is_local = FALSE;-        tz = 0;-        for (tz = 0; p < sp->len; p++) {-            sgn = string_get(sp, p);-            if (sgn == '+' || sgn == '-') {-                p++;-                if (string_get_digits(sp, &p, 2, &hh))-                    goto done;-                if (string_get_digits(sp, &p, 2, &mm))-                    goto done;-                tz = hh * 60 + mm;-                if (sgn == '-')-                    tz = -tz;-                break;-            }-        }-    }-    d = set_date_fields(fields, is_local) - tz * 60000;-    rv = __JS_NewFloat64(ctx, d);--done:-    JS_FreeValue(ctx, s);-    return rv;-}--static JSValue js_Date_now(JSContext *ctx, JSValueConst this_val,-                           int argc, JSValueConst *argv)-{-    // now()-    return JS_NewInt64(ctx, date_now());-}--static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,-                                          int argc, JSValueConst *argv)-{-    // Symbol_toPrimitive(hint)-    JSValueConst obj = this_val;-    JSAtom hint = JS_ATOM_NULL;-    int hint_num;--    if (!JS_IsObject(obj))-        return JS_ThrowTypeErrorNotAnObject(ctx);--    if (JS_IsString(argv[0])) {-        hint = JS_ValueToAtom(ctx, argv[0]);-        if (hint == JS_ATOM_NULL)-            return JS_EXCEPTION;-        JS_FreeAtom(ctx, hint);-    }-    switch (hint) {-    case JS_ATOM_number:-#ifdef CONFIG_BIGNUM-    case JS_ATOM_integer:-#endif-        hint_num = HINT_NUMBER;-        break;-    case JS_ATOM_string:-    case JS_ATOM_default:-        hint_num = HINT_STRING;-        break;-    default:-        return JS_ThrowTypeError(ctx, "invalid hint");-    }-    return JS_ToPrimitive(ctx, obj, hint_num | HINT_FORCE_ORDINARY);-}--static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    // getTimezoneOffset()-    double v;--    if (JS_ThisTimeValue(ctx, &v, this_val))-        return JS_EXCEPTION;-    if (isnan(v))-        return JS_NAN;-    else-        return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));-}--static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    // getTime()-    double v;--    if (JS_ThisTimeValue(ctx, &v, this_val))-        return JS_EXCEPTION;-    return __JS_NewFloat64(ctx, v);-}--static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    // setTime(v)-    double v;--    if (JS_ThisTimeValue(ctx, &v, this_val) || JS_ToFloat64(ctx, &v, argv[0]))-        return JS_EXCEPTION;-    return JS_SetThisTimeValue(ctx, this_val, time_clip(v));-}--static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val,-                               int argc, JSValueConst *argv)-{-    // setYear(y)-    double y;-    JSValueConst args[1];--    if (JS_ThisTimeValue(ctx, &y, this_val) || JS_ToFloat64(ctx, &y, argv[0]))-        return JS_EXCEPTION;-    y = +y;-    if (isfinite(y)) {-        y = trunc(y);-        if (y >= 0 && y < 100)-            y += 1900;-    }-    args[0] = __JS_NewFloat64(ctx, y);-    return set_date_field(ctx, this_val, 1, args, 0x011);-}--static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val,-                              int argc, JSValueConst *argv)-{-    // toJSON(key)-    JSValue obj, tv, method, rv;-    double d;--    rv = JS_EXCEPTION;-    tv = JS_UNDEFINED;--    obj = JS_ToObject(ctx, this_val);-    tv = JS_ToPrimitive(ctx, obj, HINT_NUMBER);-    if (JS_IsException(tv))-        goto exception;-    if (JS_IsNumber(tv)) {-        if (JS_ToFloat64(ctx, &d, tv) < 0)-            goto exception;-        if (!isfinite(d)) {-            rv = JS_NULL;-            goto done;-        }-    }-    method = JS_GetPropertyStr(ctx, obj, "toISOString");-    if (JS_IsException(method))-        goto exception;-    if (!JS_IsFunction(ctx, method)) {-        JS_ThrowTypeError(ctx, "object needs toISOString method");-        JS_FreeValue(ctx, method);-        goto exception;-    }-    rv = JS_CallFree(ctx, method, obj, 0, NULL);-exception:-done:-    JS_FreeValue(ctx, obj);-    JS_FreeValue(ctx, tv);-    return rv;-}--static const JSCFunctionListEntry js_date_funcs[] = {-    JS_CFUNC_DEF("now", 0, js_Date_now ),-    JS_CFUNC_DEF("parse", 1, js_Date_parse ),-    JS_CFUNC_DEF("UTC", 7, js_Date_UTC ),-};--static const JSCFunctionListEntry js_date_proto_funcs[] = {-    JS_CFUNC_DEF("valueOf", 0, js_date_getTime ),-    JS_CFUNC_MAGIC_DEF("toString", 0, get_date_string, 0x13 ),-    JS_CFUNC_DEF("[Symbol.toPrimitive]", 1, js_date_Symbol_toPrimitive ),-    JS_CFUNC_MAGIC_DEF("toUTCString", 0, get_date_string, 0x03 ),-    JS_ALIAS_DEF("toGMTString", "toUTCString" ),-    JS_CFUNC_MAGIC_DEF("toISOString", 0, get_date_string, 0x23 ),-    JS_CFUNC_MAGIC_DEF("toDateString", 0, get_date_string, 0x11 ),-    JS_CFUNC_MAGIC_DEF("toTimeString", 0, get_date_string, 0x12 ),-    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, get_date_string, 0x33 ),-    JS_CFUNC_MAGIC_DEF("toLocaleDateString", 0, get_date_string, 0x31 ),-    JS_CFUNC_MAGIC_DEF("toLocaleTimeString", 0, get_date_string, 0x32 ),-    JS_CFUNC_DEF("getTimezoneOffset", 0, js_date_getTimezoneOffset ),-    JS_CFUNC_DEF("getTime", 0, js_date_getTime ),-    JS_CFUNC_MAGIC_DEF("getYear", 0, get_date_field, 0x101 ),-    JS_CFUNC_MAGIC_DEF("getFullYear", 0, get_date_field, 0x01 ),-    JS_CFUNC_MAGIC_DEF("getUTCFullYear", 0, get_date_field, 0x00 ),-    JS_CFUNC_MAGIC_DEF("getMonth", 0, get_date_field, 0x11 ),-    JS_CFUNC_MAGIC_DEF("getUTCMonth", 0, get_date_field, 0x10 ),-    JS_CFUNC_MAGIC_DEF("getDate", 0, get_date_field, 0x21 ),-    JS_CFUNC_MAGIC_DEF("getUTCDate", 0, get_date_field, 0x20 ),-    JS_CFUNC_MAGIC_DEF("getHours", 0, get_date_field, 0x31 ),-    JS_CFUNC_MAGIC_DEF("getUTCHours", 0, get_date_field, 0x30 ),-    JS_CFUNC_MAGIC_DEF("getMinutes", 0, get_date_field, 0x41 ),-    JS_CFUNC_MAGIC_DEF("getUTCMinutes", 0, get_date_field, 0x40 ),-    JS_CFUNC_MAGIC_DEF("getSeconds", 0, get_date_field, 0x51 ),-    JS_CFUNC_MAGIC_DEF("getUTCSeconds", 0, get_date_field, 0x50 ),-    JS_CFUNC_MAGIC_DEF("getMilliseconds", 0, get_date_field, 0x61 ),-    JS_CFUNC_MAGIC_DEF("getUTCMilliseconds", 0, get_date_field, 0x60 ),-    JS_CFUNC_MAGIC_DEF("getDay", 0, get_date_field, 0x71 ),-    JS_CFUNC_MAGIC_DEF("getUTCDay", 0, get_date_field, 0x70 ),-    JS_CFUNC_DEF("setTime", 1, js_date_setTime ),-    JS_CFUNC_MAGIC_DEF("setMilliseconds", 1, set_date_field, 0x671 ),-    JS_CFUNC_MAGIC_DEF("setUTCMilliseconds", 1, set_date_field, 0x670 ),-    JS_CFUNC_MAGIC_DEF("setSeconds", 2, set_date_field, 0x571 ),-    JS_CFUNC_MAGIC_DEF("setUTCSeconds", 2, set_date_field, 0x570 ),-    JS_CFUNC_MAGIC_DEF("setMinutes", 3, set_date_field, 0x471 ),-    JS_CFUNC_MAGIC_DEF("setUTCMinutes", 3, set_date_field, 0x470 ),-    JS_CFUNC_MAGIC_DEF("setHours", 4, set_date_field, 0x371 ),-    JS_CFUNC_MAGIC_DEF("setUTCHours", 4, set_date_field, 0x370 ),-    JS_CFUNC_MAGIC_DEF("setDate", 1, set_date_field, 0x231 ),-    JS_CFUNC_MAGIC_DEF("setUTCDate", 1, set_date_field, 0x230 ),-    JS_CFUNC_MAGIC_DEF("setMonth", 2, set_date_field, 0x131 ),-    JS_CFUNC_MAGIC_DEF("setUTCMonth", 2, set_date_field, 0x130 ),-    JS_CFUNC_DEF("setYear", 1, js_date_setYear ),-    JS_CFUNC_MAGIC_DEF("setFullYear", 3, set_date_field, 0x031 ),-    JS_CFUNC_MAGIC_DEF("setUTCFullYear", 3, set_date_field, 0x030 ),-    JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ),-};--void JS_AddIntrinsicDate(JSContext *ctx)-{-    JSValueConst obj;--    /* Date */-    ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATE], js_date_proto_funcs,-                               countof(js_date_proto_funcs));-    obj = JS_NewGlobalCConstructor(ctx, "Date", js_date_constructor, 7,-                                   ctx->class_proto[JS_CLASS_DATE]);-    JS_SetPropertyFunctionList(ctx, obj, js_date_funcs, countof(js_date_funcs));-}--/* eval */--void JS_AddIntrinsicEval(JSContext *ctx)-{-    ctx->eval_internal = __JS_EvalInternal;-}--#ifdef CONFIG_BIGNUM--/* Operators */--static void js_operator_set_finalizer(JSRuntime *rt, JSValue val)-{-    JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);-    int i, j;-    JSBinaryOperatorDefEntry *ent;-    -    if (opset) {-        for(i = 0; i < JS_OVOP_COUNT; i++) {-            if (opset->self_ops[i])-                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]));-        }-        for(j = 0; j < opset->left.count; j++) {-            ent = &opset->left.tab[j];-            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {-                if (ent->ops[i])-                    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));-            }-        }-        js_free_rt(rt, opset->left.tab);-        for(j = 0; j < opset->right.count; j++) {-            ent = &opset->right.tab[j];-            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {-                if (ent->ops[i])-                    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));-            }-        }-        js_free_rt(rt, opset->right.tab);-        js_free_rt(rt, opset);-    }-}--static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,-                                 JS_MarkFunc *mark_func)-{-    JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);-    int i, j;-    JSBinaryOperatorDefEntry *ent;-    -    if (opset) {-        for(i = 0; i < JS_OVOP_COUNT; i++) {-            if (opset->self_ops[i])-                JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]),-                             mark_func);-        }-        for(j = 0; j < opset->left.count; j++) {-            ent = &opset->left.tab[j];-            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {-                if (ent->ops[i])-                    JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),-                                 mark_func);-            }-        }-        for(j = 0; j < opset->right.count; j++) {-            ent = &opset->right.tab[j];-            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {-                if (ent->ops[i])-                    JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),-                                 mark_func);-            }-        }-    }-}---/* create an OperatorSet object */-static JSValue js_operators_create_internal(JSContext *ctx,-                                            int argc, JSValueConst *argv,-                                            BOOL is_primitive)-{-    JSValue opset_obj, prop, obj;-    JSOperatorSetData *opset, *opset1;-    JSBinaryOperatorDef *def;-    JSValueConst arg;-    int i, j;-    JSBinaryOperatorDefEntry *new_tab;-    JSBinaryOperatorDefEntry *ent;-    uint32_t op_count;--    if (ctx->rt->operator_count == UINT32_MAX) {-        return JS_ThrowTypeError(ctx, "too many operators");-    }-    opset_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OPERATOR_SET);-    if (JS_IsException(opset_obj))-        goto fail;-    opset = js_mallocz(ctx, sizeof(*opset));-    if (!opset)-        goto fail;-    JS_SetOpaque(opset_obj, opset);-    if (argc >= 1) {-        arg = argv[0];-        /* self operators */-        for(i = 0; i < JS_OVOP_COUNT; i++) {-            prop = JS_GetPropertyStr(ctx, arg, js_overloadable_operator_names[i]);-            if (JS_IsException(prop))-                goto fail;-            if (!JS_IsUndefined(prop)) {-                if (check_function(ctx, prop)) {-                    JS_FreeValue(ctx, prop);-                    goto fail;-                }-                opset->self_ops[i] = JS_VALUE_GET_OBJ(prop);-            }-        }-    }-    /* left & right operators */-    for(j = 1; j < argc; j++) {-        arg = argv[j];-        prop = JS_GetPropertyStr(ctx, arg, "left");-        if (JS_IsException(prop))-            goto fail;-        def = &opset->right;-        if (JS_IsUndefined(prop)) {-            prop = JS_GetPropertyStr(ctx, arg, "right");-            if (JS_IsException(prop))-                goto fail;-            if (JS_IsUndefined(prop)) {-                JS_ThrowTypeError(ctx, "left or right property must be present");-                goto fail;-            }-            def = &opset->left;-        }-        /* get the operator set */-        obj = JS_GetProperty(ctx, prop, JS_ATOM_prototype);-        JS_FreeValue(ctx, prop);-        if (JS_IsException(obj))-            goto fail;-        prop = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);-        JS_FreeValue(ctx, obj);-        if (JS_IsException(prop))-            goto fail;-        opset1 = JS_GetOpaque2(ctx, prop, JS_CLASS_OPERATOR_SET);-        if (!opset1) {-            JS_FreeValue(ctx, prop);-            goto fail;-        }-        op_count = opset1->operator_counter;-        JS_FreeValue(ctx, prop);-        -        /* we assume there are few entries */-        new_tab = js_realloc(ctx, def->tab,-                             (def->count + 1) * sizeof(def->tab[0]));-        if (!new_tab)-            goto fail;-        def->tab = new_tab;-        def->count++;-        ent = def->tab + def->count - 1;-        memset(ent, 0, sizeof(def->tab[0]));-        ent->operator_index = op_count;-        -        for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {-            prop = JS_GetPropertyStr(ctx, arg,-                                     js_overloadable_operator_names[i]);-            if (JS_IsException(prop))-                goto fail;-            if (!JS_IsUndefined(prop)) {-                if (check_function(ctx, prop)) {-                    JS_FreeValue(ctx, prop);-                    goto fail;-                }-                ent->ops[i] = JS_VALUE_GET_OBJ(prop);-            }-        }-    }-    opset->is_primitive = is_primitive;-    opset->operator_counter = ctx->rt->operator_count++;-    return opset_obj;- fail:-    JS_FreeValue(ctx, opset_obj);-    return JS_EXCEPTION;-}--static JSValue js_operators_create(JSContext *ctx, JSValueConst this_val,-                                int argc, JSValueConst *argv)-{-    return js_operators_create_internal(ctx, argc, argv, FALSE);-}--static JSValue js_operators_updateBigIntOperators(JSContext *ctx, JSValueConst this_val,-                                                  int argc, JSValueConst *argv)-{-    JSValue opset_obj, prop;-    JSOperatorSetData *opset;-    const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW };-    JSOverloadableOperatorEnum op;-    int i;-    -    opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT],-                               JS_ATOM_Symbol_operatorSet);-    if (JS_IsException(opset_obj))-        goto fail;-    opset = JS_GetOpaque2(ctx, opset_obj, JS_CLASS_OPERATOR_SET);-    if (!opset)-        goto fail;-    for(i = 0; i < countof(ops); i++) {-        op = ops[i];-        prop = JS_GetPropertyStr(ctx, argv[0],-                                 js_overloadable_operator_names[op]);-        if (JS_IsException(prop))-            goto fail;-        if (!JS_IsUndefined(prop)) {-            if (!JS_IsNull(prop) && check_function(ctx, prop)) {-                JS_FreeValue(ctx, prop);-                goto fail;-            }-            if (opset->self_ops[op])-                JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[op]));-            if (JS_IsNull(prop)) {-                opset->self_ops[op] = NULL;-            } else {-                opset->self_ops[op] = JS_VALUE_GET_PTR(prop);-            }-        }-    }-    JS_FreeValue(ctx, opset_obj);-    return JS_UNDEFINED;- fail:-    JS_FreeValue(ctx, opset_obj);-    return JS_EXCEPTION;-}--static int js_operators_set_default(JSContext *ctx, JSValueConst obj)-{-    JSValue opset_obj;--    if (!JS_IsObject(obj)) /* in case the prototype is not defined */-        return 0;-    opset_obj = js_operators_create_internal(ctx, 0, NULL, TRUE);-    if (JS_IsException(opset_obj))-        return -1;-    /* cannot be modified by the user */-    JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_operatorSet,-                           opset_obj, 0);-    return 0;-}--static JSValue js_dummy_operators_ctor(JSContext *ctx, JSValueConst new_target,-                                       int argc, JSValueConst *argv)-{-    return js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);-}--static JSValue js_global_operators(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    JSValue func_obj, proto, opset_obj;--    func_obj = JS_UNDEFINED;-    proto = JS_NewObject(ctx);-    if (JS_IsException(proto))-        return JS_EXCEPTION;-    opset_obj = js_operators_create_internal(ctx, argc, argv, FALSE);-    if (JS_IsException(opset_obj))-        goto fail;-    JS_DefinePropertyValue(ctx, proto, JS_ATOM_Symbol_operatorSet,-                           opset_obj, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    func_obj = JS_NewCFunction2(ctx, js_dummy_operators_ctor, "Operators",-                                0, JS_CFUNC_constructor, 0);-    if (JS_IsException(func_obj))-        goto fail;-    JS_SetConstructor2(ctx, func_obj, proto,-                       0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    JS_FreeValue(ctx, proto);-    return func_obj;- fail:-    JS_FreeValue(ctx, proto);-    JS_FreeValue(ctx, func_obj);-    return JS_EXCEPTION;-}--static const JSCFunctionListEntry js_operators_funcs[] = {-    JS_CFUNC_DEF("create", 1, js_operators_create ),-    JS_CFUNC_DEF("updateBigIntOperators", 2, js_operators_updateBigIntOperators ),-};--/* must be called after all overloadable base types are initialized */-void JS_AddIntrinsicOperators(JSContext *ctx)-{-    JSValue obj;--    ctx->allow_operator_overloading = TRUE;-    obj = JS_NewCFunction(ctx, js_global_operators, "Operators", 1);-    JS_SetPropertyFunctionList(ctx, obj,-                               js_operators_funcs,-                               countof(js_operators_funcs));-    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_Operators,-                           obj,-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    /* add default operatorSets */-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BOOLEAN]);-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_NUMBER]);-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_STRING]);-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_INT]);-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]);-    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]);-}--/* BigInt */--static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)-{-    uint32_t tag;-- redo:-    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_INT:-    case JS_TAG_BOOL:-        val = JS_NewBigInt64(ctx, JS_VALUE_GET_INT(val));-        break;-    case JS_TAG_BIG_INT:-        break;-    case JS_TAG_FLOAT64:-    case JS_TAG_BIG_FLOAT:-        {-            bf_t *a, a_s;-            -            a = JS_ToBigFloat(ctx, &a_s, val);-            if (!bf_is_finite(a)) {-                JS_FreeValue(ctx, val);-                val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to bigint");-            } else {-                JSValue val1 = JS_NewBigInt(ctx);-                bf_t *r;-                int ret;-                if (JS_IsException(val1)) {-                    JS_FreeValue(ctx, val);-                    return JS_EXCEPTION;-                }-                r = JS_GetBigInt(val1);-                ret = bf_set(r, a);-                ret |= bf_rint(r, BF_RNDZ);-                JS_FreeValue(ctx, val);-                if (ret & BF_ST_MEM_ERROR) {-                    JS_FreeValue(ctx, val1);-                    val = JS_ThrowOutOfMemory(ctx);-                } else if (ret & BF_ST_INEXACT) {-                    JS_FreeValue(ctx, val1);-                    val = JS_ThrowRangeError(ctx, "cannot convert to bigint: not an integer");-                } else {-                    val = JS_CompactBigInt(ctx, val1);-                }-            }-            if (a == &a_s)-                bf_delete(a);-        }-        break;-    case JS_TAG_BIG_DECIMAL:-        val = JS_ToStringFree(ctx, val);-         if (JS_IsException(val))-            break;-        goto redo;-    case JS_TAG_STRING:-        val = JS_StringToBigIntErr(ctx, val);-        break;-    case JS_TAG_OBJECT:-        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);-        if (JS_IsException(val))-            break;-        goto redo;-    case JS_TAG_NULL:-    case JS_TAG_UNDEFINED:-    default:-        JS_FreeValue(ctx, val);-        return JS_ThrowTypeError(ctx, "cannot convert to bigint");-    }-    return val;-}--static JSValue js_bigint_constructor(JSContext *ctx,-                                     JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0]));-}--static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_IsBigInt(ctx, this_val))-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_BIG_INT) {-            if (JS_IsBigInt(ctx, p->u.object_data))-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a bigint");-}--static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,-                                  int argc, JSValueConst *argv)-{-    JSValue val;-    int base;-    JSValue ret;--    val = js_thisBigIntValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (argc == 0 || JS_IsUndefined(argv[0])) {-        base = 10;-    } else {-        base = js_get_radix(ctx, argv[0]);-        if (base < 0)-            goto fail;-    }-    ret = js_bigint_to_string1(ctx, val, base);-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    return js_thisBigIntValue(ctx, this_val);-}--static JSValue js_bigint_div(JSContext *ctx,-                              JSValueConst this_val,-                              int argc, JSValueConst *argv, int magic)-{-    bf_t a_s, b_s, *a, *b, *r, *q;-    int status;-    JSValue q_val, r_val;-    -    q_val = JS_NewBigInt(ctx);-    if (JS_IsException(q_val))-        return JS_EXCEPTION;-    r_val = JS_NewBigInt(ctx);-    if (JS_IsException(r_val))-        goto fail;-    b = NULL;-    a = JS_ToBigInt(ctx, &a_s, argv[0]);-    if (!a)-        goto fail;-    b = JS_ToBigInt(ctx, &b_s, argv[1]);-    if (!b) {-        JS_FreeBigInt(ctx, a, &a_s);-        goto fail;-    }-    q = JS_GetBigInt(q_val);-    r = JS_GetBigInt(r_val);-    status = bf_divrem(q, r, a, b, BF_PREC_INF, BF_RNDZ, magic & 0xf);-    JS_FreeBigInt(ctx, a, &a_s);-    JS_FreeBigInt(ctx, b, &b_s);-    if (unlikely(status)) {-        throw_bf_exception(ctx, status);-        goto fail;-    }-    q_val = JS_CompactBigInt(ctx, q_val);-    if (magic & 0x10) {-        JSValue ret;-        ret = JS_NewArray(ctx);-        if (JS_IsException(ret))-            goto fail;-        JS_SetPropertyUint32(ctx, ret, 0, q_val);-        JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, r_val));-        return ret;-    } else {-        JS_FreeValue(ctx, r_val);-        return q_val;-    }- fail:-    JS_FreeValue(ctx, q_val);-    JS_FreeValue(ctx, r_val);-    return JS_EXCEPTION;-}--static JSValue js_bigint_sqrt(JSContext *ctx,-                               JSValueConst this_val,-                               int argc, JSValueConst *argv, int magic)-{-    bf_t a_s, *a, *r, *rem;-    int status;-    JSValue r_val, rem_val;-    -    r_val = JS_NewBigInt(ctx);-    if (JS_IsException(r_val))-        return JS_EXCEPTION;-    rem_val = JS_NewBigInt(ctx);-    if (JS_IsException(rem_val))-        return JS_EXCEPTION;-    r = JS_GetBigInt(r_val);-    rem = JS_GetBigInt(rem_val);--    a = JS_ToBigInt(ctx, &a_s, argv[0]);-    if (!a)-        goto fail;-    status = bf_sqrtrem(r, rem, a);-    JS_FreeBigInt(ctx, a, &a_s);-    if (unlikely(status & ~BF_ST_INEXACT)) {-        throw_bf_exception(ctx, status);-        goto fail;-    }-    r_val = JS_CompactBigInt(ctx, r_val);-    if (magic) {-        JSValue ret;-        ret = JS_NewArray(ctx);-        if (JS_IsException(ret))-            goto fail;-        JS_SetPropertyUint32(ctx, ret, 0, r_val);-        JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, rem_val));-        return ret;-    } else {-        JS_FreeValue(ctx, rem_val);-        return r_val;-    }- fail:-    JS_FreeValue(ctx, r_val);-    JS_FreeValue(ctx, rem_val);-    return JS_EXCEPTION;-}--static JSValue js_bigint_op1(JSContext *ctx,-                              JSValueConst this_val,-                              int argc, JSValueConst *argv,-                              int magic)-{-    bf_t a_s, *a;-    int64_t res;--    a = JS_ToBigInt(ctx, &a_s, argv[0]);-    if (!a)-        return JS_EXCEPTION;-    switch(magic) {-    case 0: /* floorLog2 */-        if (a->sign || a->expn <= 0) {-            res = -1;-        } else {-            res = a->expn - 1;-        }-        break;-    case 1: /* ctz */-        if (bf_is_zero(a)) {-            res = -1;-        } else {-            res = bf_get_exp_min(a);-        }-        break;-    default:-        abort();-    }-    JS_FreeBigInt(ctx, a, &a_s);-    return JS_NewBigInt64(ctx, res);-}--static JSValue js_bigint_asUintN(JSContext *ctx,-                                  JSValueConst this_val,-                                  int argc, JSValueConst *argv, int asIntN)-{-    uint64_t bits;-    bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s;-    JSValue res;-    -    if (JS_ToIndex(ctx, &bits, argv[0]))-        return JS_EXCEPTION;-    res = JS_NewBigInt(ctx);-    if (JS_IsException(res))-        return JS_EXCEPTION;-    r = JS_GetBigInt(res);-    a = JS_ToBigInt(ctx, &a_s, argv[1]);-    if (!a) {-        JS_FreeValue(ctx, res);-        return JS_EXCEPTION;-    }-    /* XXX: optimize */-    r = JS_GetBigInt(res);-    bf_init(ctx->bf_ctx, mask);-    bf_set_ui(mask, 1);-    bf_mul_2exp(mask, bits, BF_PREC_INF, BF_RNDZ);-    bf_add_si(mask, mask, -1, BF_PREC_INF, BF_RNDZ);-    bf_logic_and(r, a, mask);-    if (asIntN && bits != 0) {-        bf_set_ui(mask, 1);-        bf_mul_2exp(mask, bits - 1, BF_PREC_INF, BF_RNDZ);-        if (bf_cmpu(r, mask) >= 0) {-            bf_set_ui(mask, 1);-            bf_mul_2exp(mask, bits, BF_PREC_INF, BF_RNDZ);-            bf_sub(r, r, mask, BF_PREC_INF, BF_RNDZ);-        }-    }-    bf_delete(mask);-    JS_FreeBigInt(ctx, a, &a_s);-    return JS_CompactBigInt(ctx, res);-}--static const JSCFunctionListEntry js_bigint_funcs[] = {-    JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ),-    JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ),-    /* QuickJS extensions */-    JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ),-    JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ),-    JS_CFUNC_MAGIC_DEF("cdiv", 2, js_bigint_div, BF_RNDU ),-    JS_CFUNC_MAGIC_DEF("ediv", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN ),-    JS_CFUNC_MAGIC_DEF("tdivrem", 2, js_bigint_div, BF_RNDZ | 0x10 ),-    JS_CFUNC_MAGIC_DEF("fdivrem", 2, js_bigint_div, BF_RNDD | 0x10 ),-    JS_CFUNC_MAGIC_DEF("cdivrem", 2, js_bigint_div, BF_RNDU | 0x10 ),-    JS_CFUNC_MAGIC_DEF("edivrem", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN | 0x10 ),-    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigint_sqrt, 0 ),-    JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),-    JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),-    JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),-};--static const JSCFunctionListEntry js_bigint_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_bigint_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_bigint_valueOf ),-    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ),-};--void JS_AddIntrinsicBigInt(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj1;--    rt->bigint_ops.to_string = js_bigint_to_string;-    rt->bigint_ops.from_string = js_string_to_bigint;-    rt->bigint_ops.unary_arith = js_unary_arith_bigint;-    rt->bigint_ops.binary_arith = js_binary_arith_bigint;-    rt->bigint_ops.compare = js_compare_bigfloat;-    -    ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT],-                               js_bigint_proto_funcs,-                               countof(js_bigint_proto_funcs));-    obj1 = JS_NewCFunction(ctx, js_bigint_constructor, "BigInt", 1);-    JS_NewGlobalCConstructor2(ctx, obj1, "BigInt",-                              ctx->class_proto[JS_CLASS_BIG_INT]);-    JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs,-                               countof(js_bigint_funcs));-}--/* BigFloat */--static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_IsBigFloat(this_val))-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_BIG_FLOAT) {-            if (JS_IsBigFloat(p->u.object_data))-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a bigfloat");-}--static JSValue js_bigfloat_toString(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValue val;-    int base;-    JSValue ret;--    val = js_thisBigFloatValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (argc == 0 || JS_IsUndefined(argv[0])) {-        base = 10;-    } else {-        base = js_get_radix(ctx, argv[0]);-        if (base < 0)-            goto fail;-    }-    ret = js_ftoa(ctx, val, base, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigfloat_valueOf(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    return js_thisBigFloatValue(ctx, this_val);-}--static int bigfloat_get_rnd_mode(JSContext *ctx, JSValueConst val)-{-    int rnd_mode;-    if (JS_ToInt32Sat(ctx, &rnd_mode, val))-        return -1;-    if (rnd_mode < BF_RNDN || rnd_mode > BF_RNDF) {-        JS_ThrowRangeError(ctx, "invalid rounding mode");-        return -1;-    }-    return rnd_mode;-}--static JSValue js_bigfloat_toFixed(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t f;-    int rnd_mode, radix;--    val = js_thisBigFloatValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToInt64Sat(ctx, &f, argv[0]))-        goto fail;-    if (f < 0 || f > BF_PREC_MAX) {-        JS_ThrowRangeError(ctx, "invalid number of digits");-        goto fail;-    }-    rnd_mode = BF_RNDNA;-    radix = 10;-    /* XXX: swap parameter order for rounding mode and radix */-    if (argc > 1) {-        rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);-        if (rnd_mode < 0)-            goto fail;-    }-    if (argc > 2) {-        radix = js_get_radix(ctx, argv[2]);-        if (radix < 0)-            goto fail;-    }-    ret = js_ftoa(ctx, val, radix, f, rnd_mode | BF_FTOA_FORMAT_FRAC);-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static BOOL js_bigfloat_is_finite(JSContext *ctx, JSValueConst val)-{-    BOOL res;-    uint32_t tag;--    tag = JS_VALUE_GET_NORM_TAG(val);-    switch(tag) {-    case JS_TAG_BIG_FLOAT:-        {-            JSBigFloat *p = JS_VALUE_GET_PTR(val);-            res = bf_is_finite(&p->num);-        }-        break;-    default:-        res = FALSE;-        break;-    }-    return res;-}--static JSValue js_bigfloat_toExponential(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t f;-    int rnd_mode, radix;--    val = js_thisBigFloatValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToInt64Sat(ctx, &f, argv[0]))-        goto fail;-    if (!js_bigfloat_is_finite(ctx, val)) {-        ret = JS_ToString(ctx, val);-    } else if (JS_IsUndefined(argv[0])) {-        ret = js_ftoa(ctx, val, 10, 0,-                      BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);-    } else {-        if (f < 0 || f > BF_PREC_MAX) {-            JS_ThrowRangeError(ctx, "invalid number of digits");-            goto fail;-        }-        rnd_mode = BF_RNDNA;-        radix = 10;-        if (argc > 1) {-            rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);-            if (rnd_mode < 0)-                goto fail;-        }-        if (argc > 2) {-            radix = js_get_radix(ctx, argv[2]);-            if (radix < 0)-                goto fail;-        }-        ret = js_ftoa(ctx, val, radix, f + 1,-                      rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);-    }-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigfloat_toPrecision(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t p;-    int rnd_mode, radix;--    val = js_thisBigFloatValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_IsUndefined(argv[0]))-        goto to_string;-    if (JS_ToInt64Sat(ctx, &p, argv[0]))-        goto fail;-    if (!js_bigfloat_is_finite(ctx, val)) {-    to_string:-        ret = JS_ToString(ctx, this_val);-    } else {-        if (p < 1 || p > BF_PREC_MAX) {-            JS_ThrowRangeError(ctx, "invalid number of digits");-            goto fail;-        }-        rnd_mode = BF_RNDNA;-        radix = 10;-        if (argc > 1) {-            rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);-            if (rnd_mode < 0)-                goto fail;-        }-        if (argc > 2) {-            radix = js_get_radix(ctx, argv[2]);-            if (radix < 0)-                goto fail;-        }-        ret = js_ftoa(ctx, val, radix, p, rnd_mode | BF_FTOA_FORMAT_FIXED);-    }-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static const JSCFunctionListEntry js_bigfloat_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_bigfloat_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_bigfloat_valueOf ),-    JS_CFUNC_DEF("toPrecision", 1, js_bigfloat_toPrecision ),-    JS_CFUNC_DEF("toFixed", 1, js_bigfloat_toFixed ),-    JS_CFUNC_DEF("toExponential", 1, js_bigfloat_toExponential ),-};--static JSValue js_bigfloat_constructor(JSContext *ctx,-                                       JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue val;-    if (argc == 0) {-        bf_t *r;-        val = JS_NewBigFloat(ctx);-        if (JS_IsException(val))-            return val;-        r = JS_GetBigFloat(val);-        bf_set_zero(r, 0);-    } else {-        val = JS_DupValue(ctx, argv[0]);-    redo:-        switch(JS_VALUE_GET_NORM_TAG(val)) {-        case JS_TAG_BIG_FLOAT:-            break;-        case JS_TAG_FLOAT64:-            {-                bf_t *r;-                double d = JS_VALUE_GET_FLOAT64(val);-                val = JS_NewBigFloat(ctx);-                if (JS_IsException(val))-                    break;-                r = JS_GetBigFloat(val);-                if (bf_set_float64(r, d))-                    goto fail;-            }-            break;-        case JS_TAG_INT:-            {-                bf_t *r;-                int32_t v = JS_VALUE_GET_INT(val);-                val = JS_NewBigFloat(ctx);-                if (JS_IsException(val))-                    break;-                r = JS_GetBigFloat(val);-                if (bf_set_si(r, v))-                    goto fail;-            }-            break;-        case JS_TAG_BIG_INT:-            /* We keep the full precision of the integer */-            {-                JSBigFloat *p = JS_VALUE_GET_PTR(val);-                val = JS_MKPTR(JS_TAG_BIG_FLOAT, p);-            }-            break;-        case JS_TAG_BIG_DECIMAL:-            val = JS_ToStringFree(ctx, val);-            if (JS_IsException(val))-                break;-            goto redo;-        case JS_TAG_STRING:-            {-                const char *str, *p;-                size_t len;-                int err;--                str = JS_ToCStringLen(ctx, &len, val);-                JS_FreeValue(ctx, val);-                if (!str)-                    return JS_EXCEPTION;-                p = str;-                p += skip_spaces(p);-                if ((p - str) == len) {-                    bf_t *r;-                    val = JS_NewBigFloat(ctx);-                    if (JS_IsException(val))-                        break;-                    r = JS_GetBigFloat(val);-                    bf_set_zero(r, 0);-                    err = 0;-                } else {-                    val = js_atof(ctx, p, &p, 0, ATOD_ACCEPT_BIN_OCT |-                                  ATOD_TYPE_BIG_FLOAT |-                                  ATOD_ACCEPT_PREFIX_AFTER_SIGN);-                    if (JS_IsException(val)) {-                        JS_FreeCString(ctx, str);-                        return JS_EXCEPTION;-                    }-                    p += skip_spaces(p);-                    err = ((p - str) != len);-                }-                JS_FreeCString(ctx, str);-                if (err) {-                    JS_FreeValue(ctx, val);-                    return JS_ThrowSyntaxError(ctx, "invalid bigfloat literal");-                }-            }-            break;-        case JS_TAG_OBJECT:-            val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);-            if (JS_IsException(val))-                break;-            goto redo;-        case JS_TAG_NULL:-        case JS_TAG_UNDEFINED:-        default:-            JS_FreeValue(ctx, val);-            return JS_ThrowTypeError(ctx, "cannot convert to bigfloat");-        }-    }-    return val;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigfloat_get_const(JSContext *ctx,-                                     JSValueConst this_val, int magic)-{-    bf_t *r;-    JSValue val;-    val = JS_NewBigFloat(ctx);-    if (JS_IsException(val))-        return val;-    r = JS_GetBigFloat(val);-    switch(magic) {-    case 0: /* PI */-        bf_const_pi(r, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case 1: /* LN2 */-        bf_const_log2(r, ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    case 2: /* MIN_VALUE */-    case 3: /* MAX_VALUE */-        {-            slimb_t e_range, e;-            e_range = (limb_t)1 << (bf_get_exp_bits(ctx->fp_env.flags) - 1);-            bf_set_ui(r, 1);-            if (magic == 2) {-                e = -e_range + 2;-                if (ctx->fp_env.flags & BF_FLAG_SUBNORMAL)-                    e -= ctx->fp_env.prec - 1;-                bf_mul_2exp(r, e, ctx->fp_env.prec, ctx->fp_env.flags);-            } else {-                bf_mul_2exp(r, ctx->fp_env.prec, ctx->fp_env.prec,-                            ctx->fp_env.flags);-                bf_add_si(r, r, -1, ctx->fp_env.prec, ctx->fp_env.flags);-                bf_mul_2exp(r, e_range - ctx->fp_env.prec, ctx->fp_env.prec,-                            ctx->fp_env.flags);-            }-        }-        break;-    case 4: /* EPSILON */-        bf_set_ui(r, 1);-        bf_mul_2exp(r, 1 - ctx->fp_env.prec,-                    ctx->fp_env.prec, ctx->fp_env.flags);-        break;-    default:-        abort();-    }-    return val;-}--static JSValue js_bigfloat_parseFloat(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    bf_t *a;-    const char *str;-    JSValue ret;-    int radix;-    JSFloatEnv *fe;--    str = JS_ToCString(ctx, argv[0]);-    if (!str)-        return JS_EXCEPTION;-    if (JS_ToInt32(ctx, &radix, argv[1])) {-    fail:-        JS_FreeCString(ctx, str);-        return JS_EXCEPTION;-    }-    if (radix != 0 && (radix < 2 || radix > 36)) {-        JS_ThrowRangeError(ctx, "radix must be between 2 and 36");-        goto fail;-    }-    fe = &ctx->fp_env;-    if (argc > 2) {-        fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);-        if (!fe)-            goto fail;-    }-    ret = JS_NewBigFloat(ctx);-    if (JS_IsException(ret))-        goto done;-    a = JS_GetBigFloat(ret);-    /* XXX: use js_atof() */-    bf_atof(a, str, NULL, radix, fe->prec, fe->flags);- done:-    JS_FreeCString(ctx, str);-    return ret;-}--static JSValue js_bigfloat_isFinite(JSContext *ctx, JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValueConst val = argv[0];-    JSBigFloat *p;-    -    if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)-        return JS_FALSE;-    p = JS_VALUE_GET_PTR(val);-    return JS_NewBool(ctx, bf_is_finite(&p->num));-}--static JSValue js_bigfloat_isNaN(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValueConst val = argv[0];-    JSBigFloat *p;-    -    if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)-        return JS_FALSE;-    p = JS_VALUE_GET_PTR(val);-    return JS_NewBool(ctx, bf_is_nan(&p->num));-}--enum {-    MATH_OP_ABS,-    MATH_OP_FLOOR,-    MATH_OP_CEIL,-    MATH_OP_ROUND,-    MATH_OP_TRUNC,-    MATH_OP_SQRT,-    MATH_OP_FPROUND,-    MATH_OP_ACOS,-    MATH_OP_ASIN,-    MATH_OP_ATAN,-    MATH_OP_ATAN2,-    MATH_OP_COS,-    MATH_OP_EXP,-    MATH_OP_LOG,-    MATH_OP_POW,-    MATH_OP_SIN,-    MATH_OP_TAN,-    MATH_OP_FMOD,-    MATH_OP_REM,-    MATH_OP_SIGN,--    MATH_OP_ADD,-    MATH_OP_SUB,-    MATH_OP_MUL,-    MATH_OP_DIV,-};--static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val,-                           int argc, JSValueConst *argv, int magic)-{-    bf_t a_s, *a, *r;-    JSFloatEnv *fe;-    int rnd_mode;-    JSValue op1, res;--    op1 = JS_ToNumeric(ctx, argv[0]);-    if (JS_IsException(op1))-        return op1;-    a = JS_ToBigFloat(ctx, &a_s, op1);-    fe = &ctx->fp_env;-    if (argc > 1) {-        fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV);-        if (!fe)-            goto fail;-    }-    res = JS_NewBigFloat(ctx);-    if (JS_IsException(res)) {-    fail:-        if (a == &a_s)-            bf_delete(a);-        JS_FreeValue(ctx, op1);-        return JS_EXCEPTION;-    }-    r = JS_GetBigFloat(res);-    switch (magic) {-    case MATH_OP_ABS:-        bf_set(r, a);-        r->sign = 0;-        break;-    case MATH_OP_FLOOR:-        rnd_mode = BF_RNDD;-        goto rint;-    case MATH_OP_CEIL:-        rnd_mode = BF_RNDU;-        goto rint;-    case MATH_OP_ROUND:-        rnd_mode = BF_RNDNA;-        goto rint;-    case MATH_OP_TRUNC:-        rnd_mode = BF_RNDZ;-    rint:-        bf_set(r, a);-        fe->status |= bf_rint(r, rnd_mode);-        break;-    case MATH_OP_SQRT:-        fe->status |= bf_sqrt(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_FPROUND:-        bf_set(r, a);-        fe->status |= bf_round(r, fe->prec, fe->flags);-        break;-    case MATH_OP_ACOS:-        fe->status |= bf_acos(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_ASIN:-        fe->status |= bf_asin(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_ATAN:-        fe->status |= bf_atan(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_COS:-        fe->status |= bf_cos(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_EXP:-        fe->status |= bf_exp(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_LOG:-        fe->status |= bf_log(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_SIN:-        fe->status |= bf_sin(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_TAN:-        fe->status |= bf_tan(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_SIGN:-        if (bf_is_nan(a) || bf_is_zero(a)) {-            bf_set(r, a);-        } else {-            bf_set_si(r, 1 - 2 * a->sign);-        }-        break;-    default:-        abort();-    }-    if (a == &a_s)-        bf_delete(a);-    JS_FreeValue(ctx, op1);-    return res;-}--static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,-                            int argc, JSValueConst *argv, int magic)-{-    bf_t a_s, *a, b_s, *b, r_s, *r = &r_s;-    JSFloatEnv *fe;-    JSValue op1, op2, res;--    op1 = JS_ToNumeric(ctx, argv[0]);-    if (JS_IsException(op1))-        return op1;-    op2 = JS_ToNumeric(ctx, argv[1]);-    if (JS_IsException(op2)) {-        JS_FreeValue(ctx, op1);-        return op2;-    }-    a = JS_ToBigFloat(ctx, &a_s, op1);-    b = JS_ToBigFloat(ctx, &b_s, op2);-    fe = &ctx->fp_env;-    if (argc > 2) {-        fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);-        if (!fe)-            goto fail;-    }-    res = JS_NewBigFloat(ctx);-    if (JS_IsException(res)) {-    fail:-        if (a == &a_s)-            bf_delete(a);-        if (b == &b_s)-            bf_delete(b);-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-        return JS_EXCEPTION;-    }-    r = JS_GetBigFloat(res);-    switch (magic) {-    case MATH_OP_ATAN2:-        fe->status |= bf_atan2(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_POW:-        fe->status |= bf_pow(r, a, b, fe->prec, fe->flags | BF_POW_JS_QUIRKS);-        break;-    case MATH_OP_FMOD:-        fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);-        break;-    case MATH_OP_REM:-        fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDN);-        break;-    case MATH_OP_ADD:-        fe->status |= bf_add(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_SUB:-        fe->status |= bf_sub(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_MUL:-        fe->status |= bf_mul(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_DIV:-        fe->status |= bf_div(r, a, b, fe->prec, fe->flags);-        break;-    default:-        abort();-    }-    if (a == &a_s)-        bf_delete(a);-    if (b == &b_s)-        bf_delete(b);-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    return res;-}--static const JSCFunctionListEntry js_bigfloat_funcs[] = {-    JS_CGETSET_MAGIC_DEF("PI", js_bigfloat_get_const, NULL, 0 ),-    JS_CGETSET_MAGIC_DEF("LN2", js_bigfloat_get_const, NULL, 1 ),-    JS_CGETSET_MAGIC_DEF("MIN_VALUE", js_bigfloat_get_const, NULL, 2 ),-    JS_CGETSET_MAGIC_DEF("MAX_VALUE", js_bigfloat_get_const, NULL, 3 ),-    JS_CGETSET_MAGIC_DEF("EPSILON", js_bigfloat_get_const, NULL, 4 ),-    JS_CFUNC_DEF("parseFloat", 1, js_bigfloat_parseFloat ),-    JS_CFUNC_DEF("isFinite", 1, js_bigfloat_isFinite ),-    JS_CFUNC_DEF("isNaN", 1, js_bigfloat_isNaN ),-    JS_CFUNC_MAGIC_DEF("abs", 1, js_bigfloat_fop, MATH_OP_ABS ),-    JS_CFUNC_MAGIC_DEF("fpRound", 1, js_bigfloat_fop, MATH_OP_FPROUND ),-    JS_CFUNC_MAGIC_DEF("floor", 1, js_bigfloat_fop, MATH_OP_FLOOR ),-    JS_CFUNC_MAGIC_DEF("ceil", 1, js_bigfloat_fop, MATH_OP_CEIL ),-    JS_CFUNC_MAGIC_DEF("round", 1, js_bigfloat_fop, MATH_OP_ROUND ),-    JS_CFUNC_MAGIC_DEF("trunc", 1, js_bigfloat_fop, MATH_OP_TRUNC ),-    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigfloat_fop, MATH_OP_SQRT ),-    JS_CFUNC_MAGIC_DEF("acos", 1, js_bigfloat_fop, MATH_OP_ACOS ),-    JS_CFUNC_MAGIC_DEF("asin", 1, js_bigfloat_fop, MATH_OP_ASIN ),-    JS_CFUNC_MAGIC_DEF("atan", 1, js_bigfloat_fop, MATH_OP_ATAN ),-    JS_CFUNC_MAGIC_DEF("atan2", 2, js_bigfloat_fop2, MATH_OP_ATAN2 ),-    JS_CFUNC_MAGIC_DEF("cos", 1, js_bigfloat_fop, MATH_OP_COS ),-    JS_CFUNC_MAGIC_DEF("exp", 1, js_bigfloat_fop, MATH_OP_EXP ),-    JS_CFUNC_MAGIC_DEF("log", 1, js_bigfloat_fop, MATH_OP_LOG ),-    JS_CFUNC_MAGIC_DEF("pow", 2, js_bigfloat_fop2, MATH_OP_POW ),-    JS_CFUNC_MAGIC_DEF("sin", 1, js_bigfloat_fop, MATH_OP_SIN ),-    JS_CFUNC_MAGIC_DEF("tan", 1, js_bigfloat_fop, MATH_OP_TAN ),-    JS_CFUNC_MAGIC_DEF("sign", 1, js_bigfloat_fop, MATH_OP_SIGN ),-    JS_CFUNC_MAGIC_DEF("add", 2, js_bigfloat_fop2, MATH_OP_ADD ),-    JS_CFUNC_MAGIC_DEF("sub", 2, js_bigfloat_fop2, MATH_OP_SUB ),-    JS_CFUNC_MAGIC_DEF("mul", 2, js_bigfloat_fop2, MATH_OP_MUL ),-    JS_CFUNC_MAGIC_DEF("div", 2, js_bigfloat_fop2, MATH_OP_DIV ),-    JS_CFUNC_MAGIC_DEF("fmod", 2, js_bigfloat_fop2, MATH_OP_FMOD ),-    JS_CFUNC_MAGIC_DEF("remainder", 2, js_bigfloat_fop2, MATH_OP_REM ),-};--/* FloatEnv */--static JSValue js_float_env_constructor(JSContext *ctx,-                                        JSValueConst new_target,-                                        int argc, JSValueConst *argv)-{-    JSValue obj;-    JSFloatEnv *fe;-    int64_t prec;-    int flags, rndmode;--    prec = ctx->fp_env.prec;-    flags = ctx->fp_env.flags;-    if (!JS_IsUndefined(argv[0])) {-        if (JS_ToInt64Sat(ctx, &prec, argv[0]))-            return JS_EXCEPTION;-        if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)-            return JS_ThrowRangeError(ctx, "invalid precision");-        flags = BF_RNDN; /* RNDN, max exponent size, no subnormal */-        if (argc > 1 && !JS_IsUndefined(argv[1])) {-            if (JS_ToInt32Sat(ctx, &rndmode, argv[1]))-                return JS_EXCEPTION;-            if (rndmode < BF_RNDN || rndmode > BF_RNDF)-                return JS_ThrowRangeError(ctx, "invalid rounding mode");-            flags = rndmode;-        }-    }--    obj = JS_NewObjectClass(ctx, JS_CLASS_FLOAT_ENV);-    if (JS_IsException(obj))-        return JS_EXCEPTION;-    fe = js_malloc(ctx, sizeof(*fe));-    if (!fe)-        return JS_EXCEPTION;-    fe->prec = prec;-    fe->flags = flags;-    fe->status = 0;-    JS_SetOpaque(obj, fe);-    return obj;-}--static void js_float_env_finalizer(JSRuntime *rt, JSValue val)-{-    JSFloatEnv *fe = JS_GetOpaque(val, JS_CLASS_FLOAT_ENV);-    js_free_rt(rt, fe);-}--static JSValue js_float_env_get_prec(JSContext *ctx, JSValueConst this_val)-{-    return JS_NewInt64(ctx, ctx->fp_env.prec);-}--static JSValue js_float_env_get_expBits(JSContext *ctx, JSValueConst this_val)-{-    return JS_NewInt32(ctx, bf_get_exp_bits(ctx->fp_env.flags));-}--static JSValue js_float_env_setPrec(JSContext *ctx,-                                    JSValueConst this_val,-                                    int argc, JSValueConst *argv)-{-    JSValueConst func;-    int exp_bits, flags, saved_flags;-    JSValue ret;-    limb_t saved_prec;-    int64_t prec;--    func = argv[0];-    if (JS_ToInt64Sat(ctx, &prec, argv[1]))-        return JS_EXCEPTION;-    if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)-        return JS_ThrowRangeError(ctx, "invalid precision");-    exp_bits = BF_EXP_BITS_MAX;--    if (argc > 2 && !JS_IsUndefined(argv[2])) {-        if (JS_ToInt32Sat(ctx, &exp_bits, argv[2]))-            return JS_EXCEPTION;-        if (exp_bits < BF_EXP_BITS_MIN || exp_bits > BF_EXP_BITS_MAX)-            return JS_ThrowRangeError(ctx, "invalid number of exponent bits");-    }--    flags = BF_RNDN | BF_FLAG_SUBNORMAL | bf_set_exp_bits(exp_bits);--    saved_prec = ctx->fp_env.prec;-    saved_flags = ctx->fp_env.flags;--    ctx->fp_env.prec = prec;-    ctx->fp_env.flags = flags;--    ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL);-    /* always restore the floating point precision */-    ctx->fp_env.prec = saved_prec;-    ctx->fp_env.flags = saved_flags;-    return ret;-}--#define FE_PREC      (-1)-#define FE_EXP       (-2)-#define FE_RNDMODE   (-3)-#define FE_SUBNORMAL (-4)--static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_val, int magic)-{-    JSFloatEnv *fe;-    fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);-    if (!fe)-        return JS_EXCEPTION;-    switch(magic) {-    case FE_PREC:-        return JS_NewInt64(ctx, fe->prec);-    case FE_EXP:-        return JS_NewInt32(ctx, bf_get_exp_bits(fe->flags));-    case FE_RNDMODE:-        return JS_NewInt32(ctx, fe->flags & BF_RND_MASK);-    case FE_SUBNORMAL:-        return JS_NewBool(ctx, (fe->flags & BF_FLAG_SUBNORMAL) != 0);-    default:-        return JS_NewBool(ctx, (fe->status & magic) != 0);-    }-}--static JSValue js_float_env_proto_set_status(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic)-{-    JSFloatEnv *fe;-    int b;-    int64_t prec;--    fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);-    if (!fe)-        return JS_EXCEPTION;-    switch(magic) {-    case FE_PREC:-        if (JS_ToInt64Sat(ctx, &prec, val))-            return JS_EXCEPTION;-        if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)-            return JS_ThrowRangeError(ctx, "invalid precision");-        fe->prec = prec;-        break;-    case FE_EXP:-        if (JS_ToInt32Sat(ctx, &b, val))-            return JS_EXCEPTION;-        if (b < BF_EXP_BITS_MIN || b > BF_EXP_BITS_MAX)-            return JS_ThrowRangeError(ctx, "invalid number of exponent bits");-        fe->flags = (fe->flags & ~(BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)) |-            bf_set_exp_bits(b);-        break;-    case FE_RNDMODE:-        b = bigfloat_get_rnd_mode(ctx, val);-        if (b < 0)-            return JS_EXCEPTION;-        fe->flags = (fe->flags & ~BF_RND_MASK) | b;-        break;-    case FE_SUBNORMAL:-        b = JS_ToBool(ctx, val);-        fe->flags = (fe->flags & ~BF_FLAG_SUBNORMAL) | (b ? BF_FLAG_SUBNORMAL: 0);-        break;-    default:-        b = JS_ToBool(ctx, val);-        fe->status = (fe->status & ~magic) & ((-b) & magic);-        break;-    }-    return JS_UNDEFINED;-}--static JSValue js_float_env_clearStatus(JSContext *ctx,-                                        JSValueConst this_val,-                                        int argc, JSValueConst *argv)-{-    JSFloatEnv *fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);-    if (!fe)-        return JS_EXCEPTION;-    fe->status = 0;-    return JS_UNDEFINED;-}--static const JSCFunctionListEntry js_float_env_funcs[] = {-    JS_CGETSET_DEF("prec", js_float_env_get_prec, NULL ),-    JS_CGETSET_DEF("expBits", js_float_env_get_expBits, NULL ),-    JS_CFUNC_DEF("setPrec", 2, js_float_env_setPrec ),-    JS_PROP_INT32_DEF("RNDN", BF_RNDN, 0 ),-    JS_PROP_INT32_DEF("RNDZ", BF_RNDZ, 0 ),-    JS_PROP_INT32_DEF("RNDU", BF_RNDU, 0 ),-    JS_PROP_INT32_DEF("RNDD", BF_RNDD, 0 ),-    JS_PROP_INT32_DEF("RNDNA", BF_RNDNA, 0 ),-    JS_PROP_INT32_DEF("RNDA", BF_RNDA, 0 ),-    JS_PROP_INT32_DEF("RNDF", BF_RNDF, 0 ),-    JS_PROP_INT32_DEF("precMin", BF_PREC_MIN, 0 ),-    JS_PROP_INT64_DEF("precMax", BF_PREC_MAX, 0 ),-    JS_PROP_INT32_DEF("expBitsMin", BF_EXP_BITS_MIN, 0 ),-    JS_PROP_INT32_DEF("expBitsMax", BF_EXP_BITS_MAX, 0 ),-};--static const JSCFunctionListEntry js_float_env_proto_funcs[] = {-    JS_CGETSET_MAGIC_DEF("prec", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, FE_PREC ),-    JS_CGETSET_MAGIC_DEF("expBits", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, FE_EXP ),-    JS_CGETSET_MAGIC_DEF("rndMode", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, FE_RNDMODE ),-    JS_CGETSET_MAGIC_DEF("subnormal", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, FE_SUBNORMAL ),-    JS_CGETSET_MAGIC_DEF("invalidOperation", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, BF_ST_INVALID_OP ),-    JS_CGETSET_MAGIC_DEF("divideByZero", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, BF_ST_DIVIDE_ZERO ),-    JS_CGETSET_MAGIC_DEF("overflow", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, BF_ST_OVERFLOW ),-    JS_CGETSET_MAGIC_DEF("underflow", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, BF_ST_UNDERFLOW ),-    JS_CGETSET_MAGIC_DEF("inexact", js_float_env_proto_get_status,-                         js_float_env_proto_set_status, BF_ST_INEXACT ),-    JS_CFUNC_DEF("clearStatus", 0, js_float_env_clearStatus ),-};--void JS_AddIntrinsicBigFloat(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj1;-    JSValueConst obj2;-    -    rt->bigfloat_ops.to_string = js_bigfloat_to_string;-    rt->bigfloat_ops.from_string = js_string_to_bigfloat;-    rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat;-    rt->bigfloat_ops.binary_arith = js_binary_arith_bigfloat;-    rt->bigfloat_ops.compare = js_compare_bigfloat;-    rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64;-    rt->bigfloat_ops.mul_pow10 = js_mul_pow10;-    -    ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT],-                               js_bigfloat_proto_funcs,-                               countof(js_bigfloat_proto_funcs));-    obj1 = JS_NewCFunction(ctx, js_bigfloat_constructor, "BigFloat", 1);-    JS_NewGlobalCConstructor2(ctx, obj1, "BigFloat",-                              ctx->class_proto[JS_CLASS_BIG_FLOAT]);-    JS_SetPropertyFunctionList(ctx, obj1, js_bigfloat_funcs,-                               countof(js_bigfloat_funcs));--    ctx->class_proto[JS_CLASS_FLOAT_ENV] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FLOAT_ENV],-                               js_float_env_proto_funcs,-                               countof(js_float_env_proto_funcs));-    obj2 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv",-                                        js_float_env_constructor, 1,-                                        ctx->class_proto[JS_CLASS_FLOAT_ENV]);-    JS_SetPropertyFunctionList(ctx, obj2, js_float_env_funcs,-                               countof(js_float_env_funcs));-}--/* BigDecimal */--static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,-                                   BOOL allow_null_or_undefined)-{- redo:-    switch(JS_VALUE_GET_NORM_TAG(val)) {-    case JS_TAG_BIG_DECIMAL:-        break;-    case JS_TAG_NULL:-        if (!allow_null_or_undefined)-            goto fail;-        /* fall thru */-    case JS_TAG_BOOL:-    case JS_TAG_INT:-        {-            bfdec_t *r;-            int32_t v = JS_VALUE_GET_INT(val);--            val = JS_NewBigDecimal(ctx);-            if (JS_IsException(val))-                break;-            r = JS_GetBigDecimal(val);-            if (bfdec_set_si(r, v)) {-                JS_FreeValue(ctx, val);-                val = JS_EXCEPTION;-                break;-            }-        }-        break;-    case JS_TAG_FLOAT64:-    case JS_TAG_BIG_INT:-    case JS_TAG_BIG_FLOAT:-        val = JS_ToStringFree(ctx, val);-        if (JS_IsException(val))-            break;-        goto redo;-    case JS_TAG_STRING:-        {-            const char *str, *p;-            size_t len;-            int err;--            str = JS_ToCStringLen(ctx, &len, val);-            JS_FreeValue(ctx, val);-            if (!str)-                return JS_EXCEPTION;-            p = str;-            p += skip_spaces(p);-            if ((p - str) == len) {-                bfdec_t *r;-                val = JS_NewBigDecimal(ctx);-                if (JS_IsException(val))-                    break;-                r = JS_GetBigDecimal(val);-                bfdec_set_zero(r, 0);-                err = 0;-            } else {-                val = js_atof(ctx, p, &p, 0, ATOD_TYPE_BIG_DECIMAL);-                if (JS_IsException(val)) {-                    JS_FreeCString(ctx, str);-                    return JS_EXCEPTION;-                }-                p += skip_spaces(p);-                err = ((p - str) != len);-            }-            JS_FreeCString(ctx, str);-            if (err) {-                JS_FreeValue(ctx, val);-                return JS_ThrowSyntaxError(ctx, "invalid bigdecimal literal");-            }-        }-        break;-    case JS_TAG_OBJECT:-        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);-        if (JS_IsException(val))-            break;-        goto redo;-    case JS_TAG_UNDEFINED:-        {-            bfdec_t *r;-            if (!allow_null_or_undefined)-                goto fail;-            val = JS_NewBigDecimal(ctx);-            if (JS_IsException(val))-                break;-            r = JS_GetBigDecimal(val);-            bfdec_set_nan(r);-        }-        break;-    default:-    fail:-        JS_FreeValue(ctx, val);-        return JS_ThrowTypeError(ctx, "cannot convert to bigdecimal");-    }-    return val;-}--static JSValue js_bigdecimal_constructor(JSContext *ctx,-                                         JSValueConst this_val,-                                         int argc, JSValueConst *argv)-{-    JSValue val;-    if (argc == 0) {-        bfdec_t *r;-        val = JS_NewBigDecimal(ctx);-        if (JS_IsException(val))-            return val;-        r = JS_GetBigDecimal(val);-        bfdec_set_zero(r, 0);-    } else {-        val = JS_ToBigDecimalFree(ctx, JS_DupValue(ctx, argv[0]), FALSE);-    }-    return val;-}--static JSValue js_thisBigDecimalValue(JSContext *ctx, JSValueConst this_val)-{-    if (JS_IsBigDecimal(this_val))-        return JS_DupValue(ctx, this_val);--    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {-        JSObject *p = JS_VALUE_GET_OBJ(this_val);-        if (p->class_id == JS_CLASS_BIG_DECIMAL) {-            if (JS_IsBigDecimal(p->u.object_data))-                return JS_DupValue(ctx, p->u.object_data);-        }-    }-    return JS_ThrowTypeError(ctx, "not a bigdecimal");-}--static JSValue js_bigdecimal_toString(JSContext *ctx, JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    JSValue val;--    val = js_thisBigDecimalValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    return JS_ToStringFree(ctx, val);-}--static JSValue js_bigdecimal_valueOf(JSContext *ctx, JSValueConst this_val,-                                   int argc, JSValueConst *argv)-{-    return js_thisBigDecimalValue(ctx, this_val);-}--static int js_bigdecimal_get_rnd_mode(JSContext *ctx, JSValueConst obj)-{-    const char *str;-    size_t size;-    int rnd_mode;-    -    str = JS_ToCStringLen(ctx, &size, obj);-    if (!str)-        return -1;-    if (strlen(str) != size)-        goto invalid_rounding_mode;-    if (!strcmp(str, "floor")) {-        rnd_mode = BF_RNDD;-    } else if (!strcmp(str, "ceiling")) {-        rnd_mode = BF_RNDU;-    } else if (!strcmp(str, "down")) {-        rnd_mode = BF_RNDZ;-    } else if (!strcmp(str, "up")) {-        rnd_mode = BF_RNDA;-    } else if (!strcmp(str, "half-even")) {-        rnd_mode = BF_RNDN;-    } else if (!strcmp(str, "half-up")) {-        rnd_mode = BF_RNDNA;-    } else {-    invalid_rounding_mode:-        JS_FreeCString(ctx, str);-        JS_ThrowTypeError(ctx, "invalid rounding mode");-        return -1;-    }-    JS_FreeCString(ctx, str);-    return rnd_mode;-}--typedef struct {-    int64_t prec;-    bf_flags_t flags;-} BigDecimalEnv;--static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe,-                                 JSValueConst obj)-{-    JSValue prop;-    int64_t val;-    BOOL has_prec;-    int rnd_mode;-    -    if (!JS_IsObject(obj)) {-        JS_ThrowTypeErrorNotAnObject(ctx);-        return -1;-    }-    prop = JS_GetProperty(ctx, obj, JS_ATOM_roundingMode);-    if (JS_IsException(prop))-        return -1;-    rnd_mode = js_bigdecimal_get_rnd_mode(ctx, prop);-    JS_FreeValue(ctx, prop);-    if (rnd_mode < 0)-        return -1;-    fe->flags = rnd_mode;-    -    prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits);-    if (JS_IsException(prop))-        return -1;-    has_prec = FALSE;-    if (!JS_IsUndefined(prop)) {-        if (JS_ToInt64SatFree(ctx, &val, prop))-            return -1;-        if (val < 1 || val > BF_PREC_MAX)-            goto invalid_precision;-        fe->prec = val;-        has_prec = TRUE;-    }--    prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumFractionDigits);-    if (JS_IsException(prop))-        return -1;-    if (!JS_IsUndefined(prop)) {-        if (has_prec) {-            JS_FreeValue(ctx, prop);-            JS_ThrowTypeError(ctx, "cannot provide both maximumSignificantDigits and maximumFractionDigits");-            return -1;-        }-        if (JS_ToInt64SatFree(ctx, &val, prop))-            return -1;-        if (val < 0 || val > BF_PREC_MAX) {-        invalid_precision:-            JS_ThrowTypeError(ctx, "invalid precision");-            return -1;-        }-        fe->prec = val;-        fe->flags |= BF_FLAG_RADPNT_PREC;-        has_prec = TRUE;-    }-    if (!has_prec) {-        JS_ThrowTypeError(ctx, "precision must be present");-        return -1;-    }-    return 0;-}---static JSValue js_bigdecimal_fop(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv, int magic)-{-    bfdec_t *a, *b, r_s, *r = &r_s;-    JSValue op1, op2, res;-    BigDecimalEnv fe_s, *fe = &fe_s;-    int op_count, ret;--    if (magic == MATH_OP_SQRT ||-        magic == MATH_OP_ROUND)-        op_count = 1;-    else-        op_count = 2;-    -    op1 = JS_ToNumeric(ctx, argv[0]);-    if (JS_IsException(op1))-        return op1;-    a = JS_ToBigDecimal(ctx, op1);-    if (!a) {-        JS_FreeValue(ctx, op1);-        return JS_EXCEPTION;-    }-    if (op_count >= 2) {-        op2 = JS_ToNumeric(ctx, argv[1]);-        if (JS_IsException(op2)) {-            JS_FreeValue(ctx, op1);-            return op2;-        }-        b = JS_ToBigDecimal(ctx, op2);-        if (!b)-            goto fail;-    } else {-        op2 = JS_UNDEFINED;-        b = NULL;-    }-    fe->flags = BF_RNDZ;-    fe->prec = BF_PREC_INF;-    if (op_count < argc) {-        if (js_bigdecimal_get_env(ctx, fe, argv[op_count]))-            goto fail;-    }--    res = JS_NewBigDecimal(ctx);-    if (JS_IsException(res)) {-    fail:-        JS_FreeValue(ctx, op1);-        JS_FreeValue(ctx, op2);-        return JS_EXCEPTION;-    }-    r = JS_GetBigDecimal(res);-    switch (magic) {-    case MATH_OP_ADD:-        ret = bfdec_add(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_SUB:-        ret = bfdec_sub(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_MUL:-        ret = bfdec_mul(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_DIV:-        ret = bfdec_div(r, a, b, fe->prec, fe->flags);-        break;-    case MATH_OP_FMOD:-        ret = bfdec_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);-        break;-    case MATH_OP_SQRT:-        ret = bfdec_sqrt(r, a, fe->prec, fe->flags);-        break;-    case MATH_OP_ROUND:-        ret = bfdec_set(r, a);-        if (!(ret & BF_ST_MEM_ERROR))-            ret = bfdec_round(r, fe->prec, fe->flags);-        break;-    default:-        abort();-    }-    JS_FreeValue(ctx, op1);-    JS_FreeValue(ctx, op2);-    ret &= BF_ST_MEM_ERROR | BF_ST_DIVIDE_ZERO | BF_ST_INVALID_OP |-        BF_ST_OVERFLOW;-    if (ret != 0) {-        JS_FreeValue(ctx, res);-        return throw_bf_exception(ctx, ret);-    } else {-        return res;-    }-}--static JSValue js_bigdecimal_toFixed(JSContext *ctx, JSValueConst this_val,-                                 int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t f;-    int rnd_mode;--    val = js_thisBigDecimalValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToInt64Sat(ctx, &f, argv[0]))-        goto fail;-    if (f < 0 || f > BF_PREC_MAX) {-        JS_ThrowRangeError(ctx, "invalid number of digits");-        goto fail;-    }-    rnd_mode = BF_RNDNA;-    if (argc > 1) {-        rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);-        if (rnd_mode < 0)-            goto fail;-    }-    ret = js_bigdecimal_to_string1(ctx, val, f, rnd_mode | BF_FTOA_FORMAT_FRAC);-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigdecimal_toExponential(JSContext *ctx, JSValueConst this_val,-                                       int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t f;-    int rnd_mode;--    val = js_thisBigDecimalValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_ToInt64Sat(ctx, &f, argv[0]))-        goto fail;-    if (JS_IsUndefined(argv[0])) {-        ret = js_bigdecimal_to_string1(ctx, val, 0,-                  BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);-    } else {-        if (f < 0 || f > BF_PREC_MAX) {-            JS_ThrowRangeError(ctx, "invalid number of digits");-            goto fail;-        }-        rnd_mode = BF_RNDNA;-        if (argc > 1) {-            rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);-            if (rnd_mode < 0)-                goto fail;-        }-        ret = js_bigdecimal_to_string1(ctx, val, f + 1,-                      rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);-    }-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static JSValue js_bigdecimal_toPrecision(JSContext *ctx, JSValueConst this_val,-                                     int argc, JSValueConst *argv)-{-    JSValue val, ret;-    int64_t p;-    int rnd_mode;--    val = js_thisBigDecimalValue(ctx, this_val);-    if (JS_IsException(val))-        return val;-    if (JS_IsUndefined(argv[0])) {-        return JS_ToStringFree(ctx, val);-    }-    if (JS_ToInt64Sat(ctx, &p, argv[0]))-        goto fail;-    if (p < 1 || p > BF_PREC_MAX) {-        JS_ThrowRangeError(ctx, "invalid number of digits");-        goto fail;-    }-    rnd_mode = BF_RNDNA;-    if (argc > 1) {-        rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);-        if (rnd_mode < 0)-            goto fail;-    }-    ret = js_bigdecimal_to_string1(ctx, val, p,-                                   rnd_mode | BF_FTOA_FORMAT_FIXED);-    JS_FreeValue(ctx, val);-    return ret;- fail:-    JS_FreeValue(ctx, val);-    return JS_EXCEPTION;-}--static const JSCFunctionListEntry js_bigdecimal_proto_funcs[] = {-    JS_CFUNC_DEF("toString", 0, js_bigdecimal_toString ),-    JS_CFUNC_DEF("valueOf", 0, js_bigdecimal_valueOf ),-    JS_CFUNC_DEF("toPrecision", 1, js_bigdecimal_toPrecision ),-    JS_CFUNC_DEF("toFixed", 1, js_bigdecimal_toFixed ),-    JS_CFUNC_DEF("toExponential", 1, js_bigdecimal_toExponential ),-};--static const JSCFunctionListEntry js_bigdecimal_funcs[] = {-    JS_CFUNC_MAGIC_DEF("add", 2, js_bigdecimal_fop, MATH_OP_ADD ),-    JS_CFUNC_MAGIC_DEF("sub", 2, js_bigdecimal_fop, MATH_OP_SUB ),-    JS_CFUNC_MAGIC_DEF("mul", 2, js_bigdecimal_fop, MATH_OP_MUL ),-    JS_CFUNC_MAGIC_DEF("div", 2, js_bigdecimal_fop, MATH_OP_DIV ),-    JS_CFUNC_MAGIC_DEF("mod", 2, js_bigdecimal_fop, MATH_OP_FMOD ),-    JS_CFUNC_MAGIC_DEF("round", 1, js_bigdecimal_fop, MATH_OP_ROUND ),-    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigdecimal_fop, MATH_OP_SQRT ),-};--void JS_AddIntrinsicBigDecimal(JSContext *ctx)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj1;--    rt->bigdecimal_ops.to_string = js_bigdecimal_to_string;-    rt->bigdecimal_ops.from_string = js_string_to_bigdecimal;-    rt->bigdecimal_ops.unary_arith = js_unary_arith_bigdecimal;-    rt->bigdecimal_ops.binary_arith = js_binary_arith_bigdecimal;-    rt->bigdecimal_ops.compare = js_compare_bigdecimal;--    ctx->class_proto[JS_CLASS_BIG_DECIMAL] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL],-                               js_bigdecimal_proto_funcs,-                               countof(js_bigdecimal_proto_funcs));-    obj1 = JS_NewCFunction(ctx, js_bigdecimal_constructor, "BigDecimal", 1);-    JS_NewGlobalCConstructor2(ctx, obj1, "BigDecimal",-                              ctx->class_proto[JS_CLASS_BIG_DECIMAL]);-    JS_SetPropertyFunctionList(ctx, obj1, js_bigdecimal_funcs,-                               countof(js_bigdecimal_funcs));-}--void JS_EnableBignumExt(JSContext *ctx, BOOL enable)-{-    ctx->bignum_ext = enable;-}--#endif /* CONFIG_BIGNUM */--static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = {-    "EvalError", "RangeError", "ReferenceError",-    "SyntaxError", "TypeError", "URIError",-    "InternalError", "AggregateError",-};--/* Minimum amount of objects to be able to compile code and display-   error messages. No JSAtom should be allocated by this function. */-static void JS_AddIntrinsicBasicObjects(JSContext *ctx)-{-    JSValue proto;-    int i;--    ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL);-    ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0,-                                           JS_CFUNC_generic, 0,-                                           ctx->class_proto[JS_CLASS_OBJECT]);-    ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto);-    ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx);-#if 0-    /* these are auto-initialized from js_error_proto_funcs,-       but delaying might be a problem */-    JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_name,-                           JS_AtomToString(ctx, JS_ATOM_Error),-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-    JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_message,-                           JS_AtomToString(ctx, JS_ATOM_empty_string),-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-#endif-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR],-                               js_error_proto_funcs,-                               countof(js_error_proto_funcs));--    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {-        proto = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ERROR]);-        JS_DefinePropertyValue(ctx, proto, JS_ATOM_name,-                               JS_NewAtomString(ctx, native_error_name[i]),-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-        JS_DefinePropertyValue(ctx, proto, JS_ATOM_message,-                               JS_AtomToString(ctx, JS_ATOM_empty_string),-                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);-        ctx->native_error_proto[i] = proto;-    }--    /* the array prototype is an array */-    ctx->class_proto[JS_CLASS_ARRAY] =-        JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                               JS_CLASS_ARRAY);--    ctx->array_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]),-                                     JS_PROP_INITIAL_HASH_SIZE, 1);-    add_shape_property(ctx, &ctx->array_shape, NULL,-                       JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH);--    /* XXX: could test it on first context creation to ensure that no-       new atoms are created in JS_AddIntrinsicBasicObjects(). It is-       necessary to avoid useless renumbering of atoms after-       JS_EvalBinary() if it is done just after-       JS_AddIntrinsicBasicObjects(). */-    //    assert(ctx->rt->atom_count == JS_ATOM_END);-}--void JS_AddIntrinsicBaseObjects(JSContext *ctx)-{-    int i;-    JSValueConst obj, number_obj;-    JSValue obj1;--    ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0);--    /* add caller and arguments properties to throw a TypeError */-    obj1 = JS_NewCFunction(ctx, js_function_proto_caller, NULL, 0);-    JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED,-                      obj1, ctx->throw_type_error,-                      JS_PROP_HAS_GET | JS_PROP_HAS_SET |-                      JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);-    JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED,-                      obj1, ctx->throw_type_error,-                      JS_PROP_HAS_GET | JS_PROP_HAS_SET |-                      JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);-    JS_FreeValue(ctx, obj1);-    JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));--    ctx->global_obj = JS_NewObject(ctx);-    ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);--    /* Object */-    obj = JS_NewGlobalCConstructor(ctx, "Object", js_object_constructor, 1,-                                   ctx->class_proto[JS_CLASS_OBJECT]);-    JS_SetPropertyFunctionList(ctx, obj, js_object_funcs, countof(js_object_funcs));-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                               js_object_proto_funcs, countof(js_object_proto_funcs));--    /* Function */-    JS_SetPropertyFunctionList(ctx, ctx->function_proto, js_function_proto_funcs, countof(js_function_proto_funcs));-    ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor,-                                              "Function", 1, JS_CFUNC_constructor_or_func_magic,-                                              JS_FUNC_NORMAL);-    JS_NewGlobalCConstructor2(ctx, JS_DupValue(ctx, ctx->function_ctor), "Function",-                              ctx->function_proto);--    /* Error */-    obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor,-                                "Error", 1, JS_CFUNC_constructor_or_func_magic, -1);-    JS_NewGlobalCConstructor2(ctx, obj1,-                              "Error", ctx->class_proto[JS_CLASS_ERROR]);--    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {-        JSValue func_obj;-        int n_args;-        n_args = 1 + (i == JS_AGGREGATE_ERROR);-        func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,-                                    native_error_name[i], n_args,-                                    JS_CFUNC_constructor_or_func_magic, i, obj1);-        JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],-                                  ctx->native_error_proto[i]);-    }--    /* Iterator prototype */-    ctx->iterator_proto = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->iterator_proto,-                               js_iterator_proto_funcs,-                               countof(js_iterator_proto_funcs));--    /* Array */-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY],-                               js_array_proto_funcs,-                               countof(js_array_proto_funcs));--    obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1,-                                   ctx->class_proto[JS_CLASS_ARRAY]);-    ctx->array_ctor = JS_DupValue(ctx, obj);-    JS_SetPropertyFunctionList(ctx, obj, js_array_funcs,-                               countof(js_array_funcs));--    /* XXX: create auto_initializer */-    {-        /* initialize Array.prototype[Symbol.unscopables] */-        char const unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" "find" "\0"-            "findIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" "keys" "\0" "values" "\0";-        const char *p = unscopables;-        obj1 = JS_NewObjectProto(ctx, JS_NULL);-        for(p = unscopables; *p; p += strlen(p) + 1) {-            JS_DefinePropertyValueStr(ctx, obj1, p, JS_TRUE, JS_PROP_C_W_E);-        }-        JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ARRAY],-                               JS_ATOM_Symbol_unscopables, obj1,-                               JS_PROP_CONFIGURABLE);-    }--    /* needed to initialize arguments[Symbol.iterator] */-    ctx->array_proto_values =-        JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values);--    ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR],-                               js_array_iterator_proto_funcs,-                               countof(js_array_iterator_proto_funcs));--    /* parseFloat and parseInteger must be defined before Number-       because of the Number.parseFloat and Number.parseInteger-       aliases */-    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs,-                               countof(js_global_funcs));--    /* Number */-    ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                                                               JS_CLASS_NUMBER);-    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0));-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER],-                               js_number_proto_funcs,-                               countof(js_number_proto_funcs));-    number_obj = JS_NewGlobalCConstructor(ctx, "Number", js_number_constructor, 1,-                                          ctx->class_proto[JS_CLASS_NUMBER]);-    JS_SetPropertyFunctionList(ctx, number_obj, js_number_funcs, countof(js_number_funcs));--    /* Boolean */-    ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                                                                JS_CLASS_BOOLEAN);-    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE));-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs,-                               countof(js_boolean_proto_funcs));-    JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1,-                             ctx->class_proto[JS_CLASS_BOOLEAN]);--    /* String */-    ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],-                                                               JS_CLASS_STRING);-    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], JS_AtomToString(ctx, JS_ATOM_empty_string));-    obj = JS_NewGlobalCConstructor(ctx, "String", js_string_constructor, 1,-                                   ctx->class_proto[JS_CLASS_STRING]);-    JS_SetPropertyFunctionList(ctx, obj, js_string_funcs,-                               countof(js_string_funcs));-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs,-                               countof(js_string_proto_funcs));--    ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR],-                               js_string_iterator_proto_funcs,-                               countof(js_string_iterator_proto_funcs));--    /* Math: create as autoinit object */-    js_random_init(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj));--    /* ES6 Reflect: create as autoinit object */-    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj));--    /* ES6 Symbol */-    ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs,-                               countof(js_symbol_proto_funcs));-    obj = JS_NewGlobalCConstructor(ctx, "Symbol", js_symbol_constructor, 0,-                                   ctx->class_proto[JS_CLASS_SYMBOL]);-    JS_SetPropertyFunctionList(ctx, obj, js_symbol_funcs,-                               countof(js_symbol_funcs));-    for(i = JS_ATOM_Symbol_toPrimitive; i < JS_ATOM_END; i++) {-        char buf[ATOM_GET_STR_BUF_SIZE];-        const char *str, *p;-        str = JS_AtomGetStr(ctx, buf, sizeof(buf), i);-        /* skip "Symbol." */-        p = strchr(str, '.');-        if (p)-            str = p + 1;-        JS_DefinePropertyValueStr(ctx, obj, str, JS_AtomToValue(ctx, i), 0);-    }--    /* ES6 Generator */-    ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);-    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR],-                               js_generator_proto_funcs,-                               countof(js_generator_proto_funcs));--    ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);-    obj1 = JS_NewCFunctionMagic(ctx, js_function_constructor,-                                "GeneratorFunction", 1,-                                JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR);-    JS_SetPropertyFunctionList(ctx,-                               ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],-                               js_generator_function_proto_funcs,-                               countof(js_generator_function_proto_funcs));-    JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],-                       ctx->class_proto[JS_CLASS_GENERATOR],-                       JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE);-    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],-                       0, JS_PROP_CONFIGURABLE);-    JS_FreeValue(ctx, obj1);--    /* global properties */-    ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1);-    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval,-                           JS_DupValue(ctx, ctx->eval_obj),-                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);--    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,-                           JS_DupValue(ctx, ctx->global_obj),-                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);-}--/* Typed Arrays */--static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {-    0, 0, 0, 1, 1, 2, 2,-#ifdef CONFIG_BIGNUM-    3, 3, /* BigInt64Array, BigUint64Array */-#endif-    2, 3-};--static JSValue js_array_buffer_constructor3(JSContext *ctx,-                                            JSValueConst new_target,-                                            uint64_t len, JSClassID class_id,-                                            uint8_t *buf,-                                            JSFreeArrayBufferDataFunc *free_func,-                                            void *opaque, BOOL alloc_flag)-{-    JSRuntime *rt = ctx->rt;-    JSValue obj;-    JSArrayBuffer *abuf = NULL;--    obj = js_create_from_ctor(ctx, new_target, class_id);-    if (JS_IsException(obj))-        return obj;-    /* XXX: we are currently limited to 2 GB */-    if (len > INT32_MAX) {-        JS_ThrowRangeError(ctx, "invalid array buffer length");-        goto fail;-    }-    abuf = js_malloc(ctx, sizeof(*abuf));-    if (!abuf)-        goto fail;-    abuf->byte_length = len;-    if (alloc_flag) {-        if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&-            rt->sab_funcs.sab_alloc) {-            abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque,-                                                 max_int(len, 1));-            if (!abuf->data)-                goto fail;-            memset(abuf->data, 0, len);-        } else {-            /* the allocation must be done after the object creation */-            abuf->data = js_mallocz(ctx, max_int(len, 1));-            if (!abuf->data)-                goto fail;-        }-    } else {-        if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&-            rt->sab_funcs.sab_dup) {-            rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf);-        }-        abuf->data = buf;-    }-    init_list_head(&abuf->array_list);-    abuf->detached = FALSE;-    abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER);-    abuf->opaque = opaque;-    abuf->free_func = free_func;-    if (alloc_flag && buf)-        memcpy(abuf->data, buf, len);-    JS_SetOpaque(obj, abuf);-    return obj;- fail:-    JS_FreeValue(ctx, obj);-    js_free(ctx, abuf);-    return JS_EXCEPTION;-}--static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr)-{-    js_free_rt(rt, ptr);-}--static JSValue js_array_buffer_constructor2(JSContext *ctx,-                                            JSValueConst new_target,-                                            uint64_t len, JSClassID class_id)-{-    return js_array_buffer_constructor3(ctx, new_target, len, class_id,-                                        NULL, js_array_buffer_free, NULL,-                                        TRUE);-}--static JSValue js_array_buffer_constructor1(JSContext *ctx,-                                            JSValueConst new_target,-                                            uint64_t len)-{-    return js_array_buffer_constructor2(ctx, new_target, len,-                                        JS_CLASS_ARRAY_BUFFER);-}--JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,-                          JSFreeArrayBufferDataFunc *free_func, void *opaque,-                          BOOL is_shared)-{-    return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,-                                        is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER,-                                        buf, free_func, opaque, FALSE);-}--/* create a new ArrayBuffer of length 'len' and copy 'buf' to it */-JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len)-{-    return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,-                                        JS_CLASS_ARRAY_BUFFER,-                                        (uint8_t *)buf,-                                        js_array_buffer_free, NULL,-                                        TRUE);-}--static JSValue js_array_buffer_constructor(JSContext *ctx,-                                           JSValueConst new_target,-                                           int argc, JSValueConst *argv)-{-    uint64_t len;-    if (JS_ToIndex(ctx, &len, argv[0]))-        return JS_EXCEPTION;-    return js_array_buffer_constructor1(ctx, new_target, len);-}--static JSValue js_shared_array_buffer_constructor(JSContext *ctx,-                                                  JSValueConst new_target,-                                                  int argc, JSValueConst *argv)-{-    uint64_t len;-    if (JS_ToIndex(ctx, &len, argv[0]))-        return JS_EXCEPTION;-    return js_array_buffer_constructor2(ctx, new_target, len,-                                        JS_CLASS_SHARED_ARRAY_BUFFER);-}--/* also used for SharedArrayBuffer */-static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val)-{-    JSObject *p = JS_VALUE_GET_OBJ(val);-    JSArrayBuffer *abuf = p->u.array_buffer;-    if (abuf) {-        /* The ArrayBuffer finalizer may be called before the typed-           array finalizers using it, so abuf->array_list is not-           necessarily empty. */-        // assert(list_empty(&abuf->array_list));-        if (abuf->shared && rt->sab_funcs.sab_free) {-            rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data);-        } else {-            if (abuf->free_func)-                abuf->free_func(rt, abuf->opaque, abuf->data);-        }-        js_free_rt(rt, abuf);-    }-}--static JSValue js_array_buffer_isView(JSContext *ctx,-                                      JSValueConst this_val,-                                      int argc, JSValueConst *argv)-{-    JSObject *p;-    BOOL res;-    res = FALSE;-    if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) {-        p = JS_VALUE_GET_OBJ(argv[0]);-        if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&-            p->class_id <= JS_CLASS_DATAVIEW) {-            res = TRUE;-        }-    }-    return JS_NewBool(ctx, res);-}--static const JSCFunctionListEntry js_array_buffer_funcs[] = {-    JS_CFUNC_DEF("isView", 1, js_array_buffer_isView ),-    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),-};--static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx)-{-    return JS_ThrowTypeError(ctx, "ArrayBuffer is detached");-}--static JSValue js_array_buffer_get_byteLength(JSContext *ctx,-                                              JSValueConst this_val,-                                              int class_id)-{-    JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);-    if (!abuf)-        return JS_EXCEPTION;-    if (abuf->detached)-        return JS_ThrowTypeErrorDetachedArrayBuffer(ctx);+#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 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,+} JSAtomKindEnum;++#define JS_ATOM_HASH_MASK  ((1 << 30) - 1)++struct JSString {+    JSRefCountHeader header; /* must come first, 32-bit */+    uint32_t len : 31;+    uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */+    /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3,+       for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3+       XXX: could change encoding to have one more bit in hash */+    uint32_t hash : 30;+    uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */+    uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */+#ifdef DUMP_LEAKS+    struct list_head link; /* string list */+#endif+    union {+        uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */+        uint16_t str16[0];+    } u;+};++typedef struct JSClosureVar {+    uint8_t is_local : 1;+    uint8_t is_arg : 1;+    uint8_t is_const : 1;+    uint8_t is_lexical : 1;+    uint8_t var_kind : 4; /* see JSVarKindEnum */+    /* 8 bits available */+    uint16_t var_idx; /* is_local = TRUE: index to a normal variable of the+                    parent function. otherwise: index to a closure+                    variable of the parent function */+    JSAtom var_name;+} JSClosureVar;++#define ARG_SCOPE_INDEX 1+#define ARG_SCOPE_END (-2)++typedef struct JSVarScope {+    int parent;  /* index into fd->scopes of the enclosing scope */+    int first;   /* index into fd->vars of the last variable in this scope */+} JSVarScope;++typedef enum {+    /* XXX: add more variable kinds here instead of using bit fields */+    JS_VAR_NORMAL,+    JS_VAR_FUNCTION_DECL, /* lexical var with function declaration */+    JS_VAR_NEW_FUNCTION_DECL, /* lexical var with async/generator+                                 function declaration */+    JS_VAR_CATCH,+    JS_VAR_FUNCTION_NAME, /* function expression name */+    JS_VAR_PRIVATE_FIELD,+    JS_VAR_PRIVATE_METHOD,+    JS_VAR_PRIVATE_GETTER,+    JS_VAR_PRIVATE_SETTER, /* must come after JS_VAR_PRIVATE_GETTER */+    JS_VAR_PRIVATE_GETTER_SETTER, /* must come after JS_VAR_PRIVATE_SETTER */+} JSVarKindEnum;++/* XXX: could use a different structure in bytecode functions to save+   memory */+typedef struct JSVarDef {+    JSAtom var_name;+    /* index into fd->scopes of this variable lexical scope */+    int scope_level;+    /* during compilation: +        - if scope_level = 0: scope in which the variable is defined+        - if scope_level != 0: index into fd->vars of the next+          variable in the same or enclosing lexical scope+       in a bytecode function:+       index into fd->vars of the next+       variable in the same or enclosing lexical scope+    */+    int scope_next;    +    uint8_t is_const : 1;+    uint8_t is_lexical : 1;+    uint8_t is_captured : 1;+    uint8_t var_kind : 4; /* see JSVarKindEnum */+    /* only used during compilation: function pool index for lexical+       variables with var_kind =+       JS_VAR_FUNCTION_DECL/JS_VAR_NEW_FUNCTION_DECL or scope level of+       the definition of the 'var' variables (they have scope_level =+       0) */+    int func_pool_idx : 24; /* only used during compilation : index in+                               the constant pool for hoisted function+                               definition */+} JSVarDef;++/* for the encoding of the pc2line table */+#define PC2LINE_BASE     (-1)+#define PC2LINE_RANGE    5+#define PC2LINE_OP_FIRST 1+#define PC2LINE_DIFF_PC_MAX ((255 - PC2LINE_OP_FIRST) / PC2LINE_RANGE)++typedef enum JSFunctionKindEnum {+    JS_FUNC_NORMAL = 0,+    JS_FUNC_GENERATOR = (1 << 0),+    JS_FUNC_ASYNC = (1 << 1),+    JS_FUNC_ASYNC_GENERATOR = (JS_FUNC_GENERATOR | JS_FUNC_ASYNC),+} JSFunctionKindEnum;++typedef struct JSFunctionBytecode {+    JSGCObjectHeader header; /* must come first */+    uint8_t js_mode;+    uint8_t has_prototype : 1; /* true if a prototype field is necessary */+    uint8_t has_simple_parameter_list : 1;+    uint8_t is_derived_class_constructor : 1;+    /* true if home_object needs to be initialized */+    uint8_t need_home_object : 1;+    uint8_t func_kind : 2;+    uint8_t new_target_allowed : 1;+    uint8_t super_call_allowed : 1;+    uint8_t super_allowed : 1;+    uint8_t arguments_allowed : 1;+    uint8_t has_debug : 1;+    uint8_t backtrace_barrier : 1; /* stop backtrace on this function */+    uint8_t read_only_bytecode : 1;+    /* XXX: 4 bits available */+    uint8_t *byte_code_buf; /* (self pointer) */+    int byte_code_len;+    JSAtom func_name;+    JSVarDef *vardefs; /* arguments + local variables (arg_count + var_count) (self pointer) */+    JSClosureVar *closure_var; /* list of variables in the closure (self pointer) */+    uint16_t arg_count;+    uint16_t var_count;+    uint16_t defined_arg_count; /* for length function property */+    uint16_t stack_size; /* maximum stack size */+    JSContext *realm; /* function realm */+    JSValue *cpool; /* constant pool (self pointer) */+    int cpool_count;+    int closure_var_count;+    struct {+        /* debug info, move to separate structure to save memory? */+        JSAtom filename;+        int line_num;+        int source_len;+        int pc2line_len;+        uint8_t *pc2line_buf;+        char *source;+    } debug;+} JSFunctionBytecode;++typedef struct JSBoundFunction {+    JSValue func_obj;+    JSValue this_val;+    int argc;+    JSValue argv[0];+} JSBoundFunction;++typedef enum JSIteratorKindEnum {+    JS_ITERATOR_KIND_KEY,+    JS_ITERATOR_KIND_VALUE,+    JS_ITERATOR_KIND_KEY_AND_VALUE,+} JSIteratorKindEnum;++typedef struct JSForInIterator {+    JSValue obj;+    BOOL is_array;+    uint32_t array_length;+    uint32_t idx;+} JSForInIterator;++typedef struct JSRegExp {+    JSString *pattern;+    JSString *bytecode; /* also contains the flags */+} JSRegExp;++typedef struct JSProxyData {+    JSValue target;+    JSValue handler;+    uint8_t is_func;+    uint8_t is_revoked;+} JSProxyData;++typedef struct JSArrayBuffer {+    int byte_length; /* 0 if detached */+    uint8_t detached;+    uint8_t shared; /* if shared, the array buffer cannot be detached */+    uint8_t *data; /* NULL if detached */+    struct list_head array_list;+    void *opaque;+    JSFreeArrayBufferDataFunc *free_func;+} JSArrayBuffer;++typedef struct JSTypedArray {+    struct list_head link; /* link to arraybuffer */+    JSObject *obj; /* back pointer to the TypedArray/DataView object */+    JSObject *buffer; /* based array buffer */+    uint32_t offset; /* offset in the array buffer */+    uint32_t length; /* length in the array buffer */+} JSTypedArray;++typedef struct JSAsyncFunctionState {+    JSValue this_val; /* 'this' generator argument */+    int argc; /* number of function arguments */+    BOOL throw_flag; /* used to throw an exception in JS_CallInternal() */+    JSStackFrame frame;+} JSAsyncFunctionState;++/* XXX: could use an object instead to avoid the+   JS_TAG_ASYNC_FUNCTION tag for the GC */+typedef struct JSAsyncFunctionData {+    JSGCObjectHeader header; /* must come first */+    JSValue resolving_funcs[2];+    BOOL is_active; /* true if the async function state is valid */+    JSAsyncFunctionState func_state;+} JSAsyncFunctionData;++typedef enum {+   /* binary operators */+   JS_OVOP_ADD,+   JS_OVOP_SUB,+   JS_OVOP_MUL,+   JS_OVOP_DIV,+   JS_OVOP_MOD,+   JS_OVOP_POW,+   JS_OVOP_OR,+   JS_OVOP_AND,+   JS_OVOP_XOR,+   JS_OVOP_SHL,+   JS_OVOP_SAR,+   JS_OVOP_SHR,+   JS_OVOP_EQ,+   JS_OVOP_LESS,++   JS_OVOP_BINARY_COUNT,+   /* unary operators */+   JS_OVOP_POS = JS_OVOP_BINARY_COUNT,+   JS_OVOP_NEG,+   JS_OVOP_INC,+   JS_OVOP_DEC,+   JS_OVOP_NOT,++   JS_OVOP_COUNT,+} JSOverloadableOperatorEnum;++typedef struct {+    uint32_t operator_index;+    JSObject *ops[JS_OVOP_BINARY_COUNT]; /* self operators */+} JSBinaryOperatorDefEntry;++typedef struct {+    int count;+    JSBinaryOperatorDefEntry *tab;+} JSBinaryOperatorDef;++typedef struct {+    uint32_t operator_counter;+    BOOL is_primitive; /* OperatorSet for a primitive type */+    /* NULL if no operator is defined */+    JSObject *self_ops[JS_OVOP_COUNT]; /* self operators */+    JSBinaryOperatorDef left;+    JSBinaryOperatorDef right;+} JSOperatorSetData;++typedef struct JSReqModuleEntry {+    JSAtom module_name;+    JSModuleDef *module; /* used using resolution */+} JSReqModuleEntry;++typedef enum JSExportTypeEnum {+    JS_EXPORT_TYPE_LOCAL,+    JS_EXPORT_TYPE_INDIRECT,+} JSExportTypeEnum;++typedef struct JSExportEntry {+    union {+        struct {+            int var_idx; /* closure variable index */+            JSVarRef *var_ref; /* if != NULL, reference to the variable */+        } local; /* for local export */+        int req_module_idx; /* module for indirect export */+    } u;+    JSExportTypeEnum export_type;+    JSAtom local_name; /* '*' if export ns from. not used for local+                          export after compilation */+    JSAtom export_name; /* exported variable name */+} JSExportEntry;++typedef struct JSStarExportEntry {+    int req_module_idx; /* in req_module_entries */+} JSStarExportEntry;++typedef struct JSImportEntry {+    int var_idx; /* closure variable index */+    JSAtom import_name;+    int req_module_idx; /* in req_module_entries */+} JSImportEntry;++struct JSModuleDef {+    JSRefCountHeader header; /* must come first, 32-bit */+    JSAtom module_name;+    struct list_head link;++    JSReqModuleEntry *req_module_entries;+    int req_module_entries_count;+    int req_module_entries_size;++    JSExportEntry *export_entries;+    int export_entries_count;+    int export_entries_size;++    JSStarExportEntry *star_export_entries;+    int star_export_entries_count;+    int star_export_entries_size;++    JSImportEntry *import_entries;+    int import_entries_count;+    int import_entries_size;++    JSValue module_ns;+    JSValue func_obj; /* only used for JS modules */+    JSModuleInitFunc *init_func; /* only used for C modules */+    BOOL resolved : 8;+    BOOL func_created : 8;+    BOOL instantiated : 8;+    BOOL evaluated : 8;+    BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */+    /* true if evaluation yielded an exception. It is saved in+       eval_exception */+    BOOL eval_has_exception : 8; +    JSValue eval_exception;+    JSValue meta_obj; /* for import.meta */+};++typedef struct JSJobEntry {+    struct list_head link;+    JSContext *ctx;+    JSJobFunc *job_func;+    int argc;+    JSValue argv[0];+} JSJobEntry;++typedef struct JSProperty {+    union {+        JSValue value;      /* JS_PROP_NORMAL */+        struct {            /* JS_PROP_GETSET */+            JSObject *getter; /* NULL if undefined */+            JSObject *setter; /* NULL if undefined */+        } getset;+        JSVarRef *var_ref;  /* JS_PROP_VARREF */+        struct {            /* JS_PROP_AUTOINIT */+            /* in order to use only 2 pointers, we compress the realm+               and the init function pointer */+            uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x)+                                       in the 2 low bits */+            void *opaque;+        } init;+    } u;+} JSProperty;++#define JS_PROP_INITIAL_SIZE 2+#define JS_PROP_INITIAL_HASH_SIZE 4 /* must be a power of two */+#define JS_ARRAY_INITIAL_SIZE 2++typedef struct JSShapeProperty {+    uint32_t hash_next : 26; /* 0 if last in list */+    uint32_t flags : 6;   /* JS_PROP_XXX */+    JSAtom atom; /* JS_ATOM_NULL = free property entry */+} JSShapeProperty;++struct JSShape {+    /* hash table of size hash_mask + 1 before the start of the+       structure (see prop_hash_end()). */+    JSGCObjectHeader header;+    /* true if the shape is inserted in the shape hash table. If not,+       JSShape.hash is not valid */+    uint8_t is_hashed;+    /* If true, the shape may have small array index properties 'n' with 0+       <= n <= 2^31-1. If false, the shape is guaranteed not to have+       small array index properties */+    uint8_t has_small_array_index;+    uint32_t hash; /* current hash value */+    uint32_t prop_hash_mask;+    int prop_size; /* allocated properties */+    int prop_count; /* include deleted properties */+    int deleted_prop_count;+    JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */+    JSObject *proto;+    JSShapeProperty prop[0]; /* prop_size elements */+};++struct JSObject {+    union {+        JSGCObjectHeader header;+        struct {+            int __gc_ref_count; /* corresponds to header.ref_count */+            uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */+            +            uint8_t extensible : 1;+            uint8_t free_mark : 1; /* only used when freeing objects with cycles */+            uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */+            uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */+            uint8_t is_constructor : 1; /* TRUE if object is a constructor function */+            uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */+            uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */+            uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */+            uint16_t class_id; /* see JS_CLASS_x */+        };+    };+    /* byte offsets: 16/24 */+    JSShape *shape; /* prototype and property names + flag */+    JSProperty *prop; /* array of properties */+    /* byte offsets: 24/40 */+    struct JSMapRecord *first_weak_ref; /* XXX: use a bit and an external hash table? */+    /* byte offsets: 28/48 */+    union {+        void *opaque;+        struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */+        struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */+        struct JSForInIterator *for_in_iterator; /* JS_CLASS_FOR_IN_ITERATOR */+        struct JSArrayBuffer *array_buffer; /* JS_CLASS_ARRAY_BUFFER, JS_CLASS_SHARED_ARRAY_BUFFER */+        struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_DATAVIEW */+#ifdef CONFIG_BIGNUM+        struct JSFloatEnv *float_env; /* JS_CLASS_FLOAT_ENV */+        struct JSOperatorSetData *operator_set; /* JS_CLASS_OPERATOR_SET */+#endif+        struct JSMapState *map_state;   /* JS_CLASS_MAP..JS_CLASS_WEAKSET */+        struct JSMapIteratorData *map_iterator_data; /* JS_CLASS_MAP_ITERATOR, JS_CLASS_SET_ITERATOR */+        struct JSArrayIteratorData *array_iterator_data; /* JS_CLASS_ARRAY_ITERATOR, JS_CLASS_STRING_ITERATOR */+        struct JSRegExpStringIteratorData *regexp_string_iterator_data; /* JS_CLASS_REGEXP_STRING_ITERATOR */+        struct JSGeneratorData *generator_data; /* JS_CLASS_GENERATOR */+        struct JSProxyData *proxy_data; /* JS_CLASS_PROXY */+        struct JSPromiseData *promise_data; /* JS_CLASS_PROMISE */+        struct JSPromiseFunctionData *promise_function_data; /* JS_CLASS_PROMISE_RESOLVE_FUNCTION, JS_CLASS_PROMISE_REJECT_FUNCTION */+        struct JSAsyncFunctionData *async_function_data; /* JS_CLASS_ASYNC_FUNCTION_RESOLVE, JS_CLASS_ASYNC_FUNCTION_REJECT */+        struct JSAsyncFromSyncIteratorData *async_from_sync_iterator_data; /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */+        struct JSAsyncGeneratorData *async_generator_data; /* JS_CLASS_ASYNC_GENERATOR */+        struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */+            /* also used by JS_CLASS_GENERATOR_FUNCTION, JS_CLASS_ASYNC_FUNCTION and JS_CLASS_ASYNC_GENERATOR_FUNCTION */+            struct JSFunctionBytecode *function_bytecode;+            JSVarRef **var_refs;+            JSObject *home_object; /* for 'super' access */+        } func;+        struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */+            JSContext *realm;+            JSCFunctionType c_function;+            uint8_t length;+            uint8_t cproto;+            int16_t magic;+        } cfunc;+        /* array part for fast arrays and typed arrays */+        struct { /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */+            union {+                uint32_t size;          /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */+                struct JSTypedArray *typed_array; /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */+            } u1;+            union {+                JSValue *values;        /* JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS */ +                void *ptr;              /* JS_CLASS_UINT8C_ARRAY..JS_CLASS_FLOAT64_ARRAY */+                int8_t *int8_ptr;       /* JS_CLASS_INT8_ARRAY */+                uint8_t *uint8_ptr;     /* JS_CLASS_UINT8_ARRAY, JS_CLASS_UINT8C_ARRAY */+                int16_t *int16_ptr;     /* JS_CLASS_INT16_ARRAY */+                uint16_t *uint16_ptr;   /* JS_CLASS_UINT16_ARRAY */+                int32_t *int32_ptr;     /* JS_CLASS_INT32_ARRAY */+                uint32_t *uint32_ptr;   /* JS_CLASS_UINT32_ARRAY */+                int64_t *int64_ptr;     /* JS_CLASS_INT64_ARRAY */+                uint64_t *uint64_ptr;   /* JS_CLASS_UINT64_ARRAY */+                float *float_ptr;       /* JS_CLASS_FLOAT32_ARRAY */+                double *double_ptr;     /* JS_CLASS_FLOAT64_ARRAY */+            } u;+            uint32_t count; /* <= 2^31-1. 0 for a detached typed array */+        } array;    /* 12/20 bytes */+        JSRegExp regexp;    /* JS_CLASS_REGEXP: 8/16 bytes */+        JSValue object_data;    /* for JS_SetObjectData(): 8/16/16 bytes */+    } u;+    /* byte sizes: 40/48/72 */+};+enum {+    __JS_ATOM_NULL = JS_ATOM_NULL,+#define DEF(name, str) JS_ATOM_ ## name,+#include "quickjs-atom.h"+#undef DEF+    JS_ATOM_END,+};+#define JS_ATOM_LAST_KEYWORD JS_ATOM_super+#define JS_ATOM_LAST_STRICT_KEYWORD JS_ATOM_yield++static const char js_atom_init[] =+#define DEF(name, str) str "\0"+#include "quickjs-atom.h"+#undef DEF+;++typedef enum OPCodeFormat {+#define FMT(f) OP_FMT_ ## f,+#define DEF(id, size, n_pop, n_push, f)+#include "quickjs-opcode.h"+#undef DEF+#undef FMT+} OPCodeFormat;++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,+};++static int JS_InitAtoms(JSRuntime *rt);+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,+                               int atom_type);+static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p);+static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b);+static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,+                                  JSValueConst this_obj,+                                  int argc, JSValueConst *argv, int flags);+static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,+                                      JSValueConst this_obj,+                                      int argc, JSValueConst *argv, int flags);+static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,+                               JSValueConst this_obj, JSValueConst new_target,+                               int argc, JSValue *argv, int flags);+static JSValue JS_CallConstructorInternal(JSContext *ctx,+                                          JSValueConst func_obj,+                                          JSValueConst new_target,+                                          int argc, JSValue *argv, int flags);+static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,+                           int argc, JSValueConst *argv);+static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,+                             int argc, JSValueConst *argv);+static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,+                                            JSValue val, BOOL is_array_ctor);+static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,+                             JSValueConst val, int flags, int scope_idx);+JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);+static __maybe_unused void JS_DumpAtoms(JSRuntime *rt);+static __maybe_unused void JS_DumpString(JSRuntime *rt,+                                                  const JSString *p);+static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);+static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);+static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);+static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,+                                                      JSValueConst val);+static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);+static __maybe_unused void JS_PrintValue(JSContext *ctx,+                                                  const char *str,+                                                  JSValueConst val);+static __maybe_unused void JS_DumpShapes(JSRuntime *rt);+static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv, int magic);+static void js_array_finalizer(JSRuntime *rt, JSValue val);+static void js_array_mark(JSRuntime *rt, JSValueConst val,+                          JS_MarkFunc *mark_func);+static void js_object_data_finalizer(JSRuntime *rt, JSValue val);+static void js_object_data_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_c_function_finalizer(JSRuntime *rt, JSValue val);+static void js_c_function_mark(JSRuntime *rt, JSValueConst val,+                               JS_MarkFunc *mark_func);+static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);+static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_bound_function_finalizer(JSRuntime *rt, JSValue val);+static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val);+static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_regexp_finalizer(JSRuntime *rt, JSValue val);+static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val);+static void js_typed_array_finalizer(JSRuntime *rt, JSValue val);+static void js_typed_array_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_proxy_finalizer(JSRuntime *rt, JSValue val);+static void js_proxy_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_map_finalizer(JSRuntime *rt, JSValue val);+static void js_map_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val);+static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val);+static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val);+static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_generator_finalizer(JSRuntime *rt, JSValue obj);+static void js_generator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_promise_finalizer(JSRuntime *rt, JSValue val);+static void js_promise_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val);+static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func);+#ifdef CONFIG_BIGNUM+static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);+static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,+                                 JS_MarkFunc *mark_func);+#endif+static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);+static int JS_ToBoolFree(JSContext *ctx, JSValue val);+static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);+static int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val);+static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val);+static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,+                                 JSValueConst flags);+static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,+                                              JSValue pattern, JSValue bc);+static void gc_decref(JSRuntime *rt);+static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,+                        const JSClassDef *class_def, JSAtom name);++typedef enum JSStrictEqModeEnum {+    JS_EQ_STRICT,+    JS_EQ_SAME_VALUE,+    JS_EQ_SAME_VALUE_ZERO,+} JSStrictEqModeEnum;++static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,+                          JSStrictEqModeEnum eq_mode);+static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2);+static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2);+static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2);+static JSValue JS_ToObject(JSContext *ctx, JSValueConst val);+static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val);+static JSProperty *add_property(JSContext *ctx,+                                JSObject *p, JSAtom prop, int prop_flags);+#ifdef CONFIG_BIGNUM+static void js_float_env_finalizer(JSRuntime *rt, JSValue val);+static JSValue JS_NewBigFloat(JSContext *ctx);+static inline bf_t *JS_GetBigFloat(JSValueConst val)+{+    JSBigFloat *p = JS_VALUE_GET_PTR(val);+    return &p->num;+}+static JSValue JS_NewBigDecimal(JSContext *ctx);+static inline bfdec_t *JS_GetBigDecimal(JSValueConst val)+{+    JSBigDecimal *p = JS_VALUE_GET_PTR(val);+    return &p->num;+}+static JSValue JS_NewBigInt(JSContext *ctx);+static inline bf_t *JS_GetBigInt(JSValueConst val)+{+    JSBigFloat *p = JS_VALUE_GET_PTR(val);+    return &p->num;+}+static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,+                                 BOOL convert_to_safe_integer);+static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val);+static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val);+static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val);+static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf);+static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val);+static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,+                                   BOOL allow_null_or_undefined);+static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val);+#endif+JSValue JS_ThrowOutOfMemory(JSContext *ctx);+static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx);+static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj);+static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,+                                   JSValueConst proto_val, BOOL throw_flag);+static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj);+static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj);+static int js_proxy_isArray(JSContext *ctx, JSValueConst obj);+static int JS_CreateProperty(JSContext *ctx, JSObject *p,+                             JSAtom prop, JSValueConst val,+                             JSValueConst getter, JSValueConst setter,+                             int flags);+static int js_string_memcmp(const JSString *p1, const JSString *p2, int len);+static void reset_weak_ref(JSRuntime *rt, JSObject *p);+static JSValue js_array_buffer_constructor3(JSContext *ctx,+                                            JSValueConst new_target,+                                            uint64_t len, JSClassID class_id,+                                            uint8_t *buf,+                                            JSFreeArrayBufferDataFunc *free_func,+                                            void *opaque, BOOL alloc_flag);+static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj);+static JSValue js_typed_array_constructor(JSContext *ctx,+                                          JSValueConst this_val,+                                          int argc, JSValueConst *argv,+                                          int classid);+static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p);+static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p);+static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx);+static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx,+                             BOOL is_arg);+static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,+                                          JSValueConst this_obj,+                                          int argc, JSValueConst *argv,+                                          int flags);+static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val);+static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,+                                           JS_MarkFunc *mark_func);+static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,+                               const char *input, size_t input_len,+                               const char *filename, int flags, int scope_idx);+static void js_free_module_def(JSContext *ctx, JSModuleDef *m);+static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,+                               JS_MarkFunc *mark_func);+static JSValue js_import_meta(JSContext *ctx);+static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier);+static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);+static JSValue js_new_promise_capability(JSContext *ctx,+                                         JSValue *resolving_funcs,+                                         JSValueConst ctor);+static __exception int perform_promise_then(JSContext *ctx,+                                            JSValueConst promise,+                                            JSValueConst *resolve_reject,+                                            JSValueConst *cap_resolving_funcs);+static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv, int magic);+static int js_string_compare(JSContext *ctx,+                             const JSString *p1, const JSString *p2);+static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val);+static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,+                               JSValue prop, JSValue val, int flags);+static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val);+static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val);+static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val);+static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,+                                     JSObject *p, JSAtom prop);+static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc);+static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,+                            JS_MarkFunc *mark_func);+static void JS_AddIntrinsicBasicObjects(JSContext *ctx);+static void js_free_shape(JSRuntime *rt, JSShape *sh);+static void js_free_shape_null(JSRuntime *rt, JSShape *sh);+static int js_shape_prepare_update(JSContext *ctx, JSObject *p,+                                   JSShapeProperty **pprs);+static int init_shape_hash(JSRuntime *rt);+static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,+                                       JSValueConst obj);+static __exception int js_get_length64(JSContext *ctx, int64_t *pres,+                                       JSValueConst obj);+static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len);+static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,+                               JSValueConst array_arg);+static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,+                              JSValue **arrpp, uint32_t *countp);+static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,+                                              JSValueConst sync_iter);+static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val);+static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,+                                    JS_MarkFunc *mark_func);+static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,+                                       JSValueConst this_val,+                                       int argc, JSValueConst *argv, int flags);+static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val);+static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,+                          JSGCObjectTypeEnum type);+static void remove_gc_object(JSGCObjectHeader *h);+static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);+static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);+static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,+                                 void *opaque);+static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,+                                               JSAtom atom, void *opaque);+void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag);++static const JSClassExoticMethods js_arguments_exotic_methods;+static const JSClassExoticMethods js_string_exotic_methods;+static const JSClassExoticMethods js_proxy_exotic_methods;+static const JSClassExoticMethods js_module_ns_exotic_methods;+static JSClassID js_class_id_alloc = JS_CLASS_INIT_COUNT;++static void js_trigger_gc(JSRuntime *rt, size_t size)+{+    BOOL force_gc;+#ifdef FORCE_GC_AT_MALLOC+    force_gc = TRUE;+#else+    force_gc = ((rt->malloc_state.malloc_size + size) >+                rt->malloc_gc_threshold);+#endif+    if (force_gc) {+#ifdef DUMP_GC+        printf("GC: size=%" PRIu64 "\n",+               (uint64_t)rt->malloc_state.malloc_size);+#endif+        JS_RunGC(rt);+        rt->malloc_gc_threshold = rt->malloc_state.malloc_size ++            (rt->malloc_state.malloc_size >> 1);+    }+}++static size_t js_malloc_usable_size_unknown(const void *ptr)+{+    return 0;+}++void *js_malloc_rt(JSRuntime *rt, size_t size)+{+    return rt->mf.js_malloc(&rt->malloc_state, size);+}++void js_free_rt(JSRuntime *rt, void *ptr)+{+    rt->mf.js_free(&rt->malloc_state, ptr);+}++void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size)+{+    return rt->mf.js_realloc(&rt->malloc_state, ptr, size);+}++size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr)+{+    return rt->mf.js_malloc_usable_size(ptr);+}++void *js_mallocz_rt(JSRuntime *rt, size_t size)+{+    void *ptr;+    ptr = js_malloc_rt(rt, size);+    if (!ptr)+        return NULL;+    return memset(ptr, 0, size);+}++#ifdef CONFIG_BIGNUM+/* called by libbf */+static void *js_bf_realloc(void *opaque, void *ptr, size_t size)+{+    JSRuntime *rt = opaque;+    return js_realloc_rt(rt, ptr, size);+}+#endif /* CONFIG_BIGNUM */++/* Throw out of memory in case of error */+void *js_malloc(JSContext *ctx, size_t size)+{+    void *ptr;+    ptr = js_malloc_rt(ctx->rt, size);+    if (unlikely(!ptr)) {+        JS_ThrowOutOfMemory(ctx);+        return NULL;+    }+    return ptr;+}++/* Throw out of memory in case of error */+void *js_mallocz(JSContext *ctx, size_t size)+{+    void *ptr;+    ptr = js_mallocz_rt(ctx->rt, size);+    if (unlikely(!ptr)) {+        JS_ThrowOutOfMemory(ctx);+        return NULL;+    }+    return ptr;+}++void js_free(JSContext *ctx, void *ptr)+{+    js_free_rt(ctx->rt, ptr);+}++/* Throw out of memory in case of error */+void *js_realloc(JSContext *ctx, void *ptr, size_t size)+{+    void *ret;+    ret = js_realloc_rt(ctx->rt, ptr, size);+    if (unlikely(!ret && size != 0)) {+        JS_ThrowOutOfMemory(ctx);+        return NULL;+    }+    return ret;+}++/* store extra allocated size in *pslack if successful */+void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack)+{+    void *ret;+    ret = js_realloc_rt(ctx->rt, ptr, size);+    if (unlikely(!ret && size != 0)) {+        JS_ThrowOutOfMemory(ctx);+        return NULL;+    }+    if (pslack) {+        size_t new_size = js_malloc_usable_size_rt(ctx->rt, ret);+        *pslack = (new_size > size) ? new_size - size : 0;+    }+    return ret;+}++size_t js_malloc_usable_size(JSContext *ctx, const void *ptr)+{+    return js_malloc_usable_size_rt(ctx->rt, ptr);+}++/* Throw out of memory exception in case of error */+char *js_strndup(JSContext *ctx, const char *s, size_t n)+{+    char *ptr;+    ptr = js_malloc(ctx, n + 1);+    if (ptr) {+        memcpy(ptr, s, n);+        ptr[n] = '\0';+    }+    return ptr;+}++char *js_strdup(JSContext *ctx, const char *str)+{+    return js_strndup(ctx, str, strlen(str));+}++static no_inline int js_realloc_array(JSContext *ctx, void **parray,+                                      int elem_size, int *psize, int req_size)+{+    int new_size;+    size_t slack;+    void *new_array;+    /* XXX: potential arithmetic overflow */+    new_size = max_int(req_size, *psize * 3 / 2);+    new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack);+    if (!new_array)+        return -1;+    new_size += slack / elem_size;+    *psize = new_size;+    *parray = new_array;+    return 0;+}++/* resize the array and update its size if req_size > *psize */+static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size,+                                  int *psize, int req_size)+{+    if (unlikely(req_size > *psize))+        return js_realloc_array(ctx, parray, elem_size, psize, req_size);+    else+        return 0;+}++static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)+{+    dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);+}++static inline int is_digit(int c) {+    return c >= '0' && c <= '9';+}++typedef struct JSClassShortDef {+    JSAtom class_name;+    JSClassFinalizer *finalizer;+    JSClassGCMark *gc_mark;+} JSClassShortDef;++static JSClassShortDef const js_std_class_def[] = {+    { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_OBJECT */+    { JS_ATOM_Array, js_array_finalizer, js_array_mark },       /* JS_CLASS_ARRAY */+    { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */+    { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */+    { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */+    { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */+    { JS_ATOM_Symbol, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_SYMBOL */+    { JS_ATOM_Arguments, js_array_finalizer, js_array_mark },   /* JS_CLASS_ARGUMENTS */+    { JS_ATOM_Arguments, NULL, NULL },                          /* JS_CLASS_MAPPED_ARGUMENTS */+    { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */+    { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_MODULE_NS */+    { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */+    { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */+    { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */+    { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */+    { JS_ATOM_GeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_GENERATOR_FUNCTION */+    { JS_ATOM_ForInIterator, js_for_in_iterator_finalizer, js_for_in_iterator_mark },      /* JS_CLASS_FOR_IN_ITERATOR */+    { JS_ATOM_RegExp, js_regexp_finalizer, NULL },                              /* JS_CLASS_REGEXP */+    { JS_ATOM_ArrayBuffer, js_array_buffer_finalizer, NULL },                   /* JS_CLASS_ARRAY_BUFFER */+    { JS_ATOM_SharedArrayBuffer, js_array_buffer_finalizer, NULL },             /* JS_CLASS_SHARED_ARRAY_BUFFER */+    { JS_ATOM_Uint8ClampedArray, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT8C_ARRAY */+    { JS_ATOM_Int8Array, js_typed_array_finalizer, js_typed_array_mark },       /* JS_CLASS_INT8_ARRAY */+    { JS_ATOM_Uint8Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_UINT8_ARRAY */+    { JS_ATOM_Int16Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_INT16_ARRAY */+    { JS_ATOM_Uint16Array, js_typed_array_finalizer, js_typed_array_mark },     /* JS_CLASS_UINT16_ARRAY */+    { JS_ATOM_Int32Array, js_typed_array_finalizer, js_typed_array_mark },      /* JS_CLASS_INT32_ARRAY */+    { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark },     /* JS_CLASS_UINT32_ARRAY */+#ifdef CONFIG_BIGNUM+    { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark },   /* JS_CLASS_BIG_INT64_ARRAY */+    { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark },  /* JS_CLASS_BIG_UINT64_ARRAY */+#endif+    { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark },    /* JS_CLASS_FLOAT32_ARRAY */+    { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark },    /* JS_CLASS_FLOAT64_ARRAY */+    { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark },        /* JS_CLASS_DATAVIEW */+#ifdef CONFIG_BIGNUM+    { JS_ATOM_BigInt, js_object_data_finalizer, js_object_data_mark },      /* JS_CLASS_BIG_INT */+    { JS_ATOM_BigFloat, js_object_data_finalizer, js_object_data_mark },    /* JS_CLASS_BIG_FLOAT */+    { JS_ATOM_BigFloatEnv, js_float_env_finalizer, NULL },      /* JS_CLASS_FLOAT_ENV */+    { JS_ATOM_BigDecimal, js_object_data_finalizer, js_object_data_mark },    /* JS_CLASS_BIG_DECIMAL */+    { JS_ATOM_OperatorSet, js_operator_set_finalizer, js_operator_set_mark },    /* JS_CLASS_OPERATOR_SET */+#endif+    { JS_ATOM_Map, js_map_finalizer, js_map_mark },             /* JS_CLASS_MAP */+    { JS_ATOM_Set, js_map_finalizer, js_map_mark },             /* JS_CLASS_SET */+    { JS_ATOM_WeakMap, js_map_finalizer, js_map_mark },         /* JS_CLASS_WEAKMAP */+    { JS_ATOM_WeakSet, js_map_finalizer, js_map_mark },         /* JS_CLASS_WEAKSET */+    { JS_ATOM_Map_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_MAP_ITERATOR */+    { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */+    { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */+    { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */+    { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */+    { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */+};++static int init_class_range(JSRuntime *rt, JSClassShortDef const *tab,+                            int start, int count)+{+    JSClassDef cm_s, *cm = &cm_s;+    int i, class_id;++    for(i = 0; i < count; i++) {+        class_id = i + start;+        memset(cm, 0, sizeof(*cm));+        cm->finalizer = tab[i].finalizer;+        cm->gc_mark = tab[i].gc_mark;+        if (JS_NewClass1(rt, class_id, cm, tab[i].class_name) < 0)+            return -1;+    }+    return 0;+}++#ifdef CONFIG_BIGNUM+static JSValue JS_ThrowUnsupportedOperation(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "unsupported operation");+}++static JSValue invalid_to_string(JSContext *ctx, JSValueConst val)+{+    return JS_ThrowUnsupportedOperation(ctx);+}++static JSValue invalid_from_string(JSContext *ctx, const char *buf,+                                   int radix, int flags, slimb_t *pexponent)+{+    return JS_NAN;+}++static int invalid_unary_arith(JSContext *ctx,+                               JSValue *pres, OPCodeEnum op, JSValue op1)+{+    JS_FreeValue(ctx, op1);+    JS_ThrowUnsupportedOperation(ctx);+    return -1;+}++static int invalid_binary_arith(JSContext *ctx, OPCodeEnum op,+                                JSValue *pres, JSValue op1, JSValue op2)+{+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    JS_ThrowUnsupportedOperation(ctx);+    return -1;+}++static JSValue invalid_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,+                                            int64_t exponent)+{+    return JS_ThrowUnsupportedOperation(ctx);+}++static int invalid_mul_pow10(JSContext *ctx, JSValue *sp)+{+    JS_ThrowUnsupportedOperation(ctx);+    return -1;+}++static void set_dummy_numeric_ops(JSNumericOperations *ops)+{+    ops->to_string = invalid_to_string;+    ops->from_string = invalid_from_string;+    ops->unary_arith = invalid_unary_arith;+    ops->binary_arith = invalid_binary_arith;+    ops->mul_pow10_to_float64 = invalid_mul_pow10_to_float64;+    ops->mul_pow10 = invalid_mul_pow10;+}++#endif /* CONFIG_BIGNUM */++#if !defined(CONFIG_STACK_CHECK)+/* no stack limitation */+static inline uint8_t *js_get_stack_pointer(void)+{+    return NULL;+}++static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)+{+    return FALSE;+}+#else+/* Note: OS and CPU dependent */+static inline uint8_t *js_get_stack_pointer(void)+{+    return __builtin_frame_address(0);+}++static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)+{+    size_t size;+    size = rt->stack_top - js_get_stack_pointer();+    return unlikely((size + alloca_size) > rt->stack_size);+}+#endif++JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)+{+    JSRuntime *rt;+    JSMallocState ms;++    memset(&ms, 0, sizeof(ms));+    ms.opaque = opaque;+    ms.malloc_limit = -1;++    rt = mf->js_malloc(&ms, sizeof(JSRuntime));+    if (!rt)+        return NULL;+    memset(rt, 0, sizeof(*rt));+    rt->mf = *mf;+    if (!rt->mf.js_malloc_usable_size) {+        /* use dummy function if none provided */+        rt->mf.js_malloc_usable_size = js_malloc_usable_size_unknown;+    }+    rt->malloc_state = ms;+    rt->malloc_gc_threshold = 256 * 1024;++#ifdef CONFIG_BIGNUM+    bf_context_init(&rt->bf_ctx, js_bf_realloc, rt);+    set_dummy_numeric_ops(&rt->bigint_ops);+    set_dummy_numeric_ops(&rt->bigfloat_ops);+    set_dummy_numeric_ops(&rt->bigdecimal_ops);+#endif++    init_list_head(&rt->context_list);+    init_list_head(&rt->gc_obj_list);+    init_list_head(&rt->gc_zero_ref_count_list);+    rt->gc_phase = JS_GC_PHASE_NONE;+    +#ifdef DUMP_LEAKS+    init_list_head(&rt->string_list);+#endif+    init_list_head(&rt->job_list);++    if (JS_InitAtoms(rt))+        goto fail;++    /* create the object, array and function classes */+    if (init_class_range(rt, js_std_class_def, JS_CLASS_OBJECT,+                         countof(js_std_class_def)) < 0)+        goto fail;+    rt->class_array[JS_CLASS_ARGUMENTS].exotic = &js_arguments_exotic_methods;+    rt->class_array[JS_CLASS_STRING].exotic = &js_string_exotic_methods;+    rt->class_array[JS_CLASS_MODULE_NS].exotic = &js_module_ns_exotic_methods;++    rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function;+    rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_c_function_data_call;+    rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function;+    rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_generator_function_call;+    if (init_shape_hash(rt))+        goto fail;++    rt->stack_top = js_get_stack_pointer();+    rt->stack_size = JS_DEFAULT_STACK_SIZE;+    rt->current_exception = JS_NULL;++    return rt;+ fail:+    JS_FreeRuntime(rt);+    return NULL;+}++void *JS_GetRuntimeOpaque(JSRuntime *rt)+{+    return rt->user_opaque;+}++void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)+{+    rt->user_opaque = opaque;+}++/* default memory allocation functions with memory limitation */+static inline size_t js_def_malloc_usable_size(void *ptr)+{+#if defined(__APPLE__)+    return malloc_size(ptr);+#elif defined(_WIN32)+    return _msize(ptr);+#elif defined(EMSCRIPTEN)+    return 0;+#elif defined(__linux__)+    return malloc_usable_size(ptr);+#else+    /* change this to `return 0;` if compilation fails */+    return malloc_usable_size(ptr);+#endif+}++static void *js_def_malloc(JSMallocState *s, size_t size)+{+    void *ptr;++    /* Do not allocate zero bytes: behavior is platform dependent */+    assert(size != 0);++    if (unlikely(s->malloc_size + size > s->malloc_limit))+        return NULL;++    ptr = malloc(size);+    if (!ptr)+        return NULL;++    s->malloc_count++;+    s->malloc_size += js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;+    return ptr;+}++static void js_def_free(JSMallocState *s, void *ptr)+{+    if (!ptr)+        return;++    s->malloc_count--;+    s->malloc_size -= js_def_malloc_usable_size(ptr) + MALLOC_OVERHEAD;+    free(ptr);+}++static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)+{+    size_t old_size;++    if (!ptr) {+        if (size == 0)+            return NULL;+        return js_def_malloc(s, size);+    }+    old_size = js_def_malloc_usable_size(ptr);+    if (size == 0) {+        s->malloc_count--;+        s->malloc_size -= old_size + MALLOC_OVERHEAD;+        free(ptr);+        return NULL;+    }+    if (s->malloc_size + size - old_size > s->malloc_limit)+        return NULL;++    ptr = realloc(ptr, size);+    if (!ptr)+        return NULL;++    s->malloc_size += js_def_malloc_usable_size(ptr) - old_size;+    return ptr;+}++static const JSMallocFunctions def_malloc_funcs = {+    js_def_malloc,+    js_def_free,+    js_def_realloc,+#if defined(__APPLE__)+    malloc_size,+#elif defined(_WIN32)+    (size_t (*)(const void *))_msize,+#elif defined(EMSCRIPTEN)+    NULL,+#elif defined(__linux__)+    (size_t (*)(const void *))malloc_usable_size,+#else+    /* change this to `NULL,` if compilation fails */+    malloc_usable_size,+#endif+};++JSRuntime *JS_NewRuntime(void)+{+    return JS_NewRuntime2(&def_malloc_funcs, NULL);+}++void JS_SetMemoryLimit(JSRuntime *rt, size_t limit)+{+    rt->malloc_state.malloc_limit = limit;+}++/* use -1 to disable automatic GC */+void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold)+{+    rt->malloc_gc_threshold = gc_threshold;+}++#define malloc(s) malloc_is_forbidden(s)+#define free(p) free_is_forbidden(p)+#define realloc(p,s) realloc_is_forbidden(p,s)++void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque)+{+    rt->interrupt_handler = cb;+    rt->interrupt_opaque = opaque;+}++void JS_SetCanBlock(JSRuntime *rt, BOOL can_block)+{+    rt->can_block = can_block;+}++void JS_SetSharedArrayBufferFunctions(JSRuntime *rt,+                                      const JSSharedArrayBufferFunctions *sf)+{+    rt->sab_funcs = *sf;+}++/* return 0 if OK, < 0 if exception */+int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,+                  int argc, JSValueConst *argv)+{+    JSRuntime *rt = ctx->rt;+    JSJobEntry *e;+    int i;++    e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));+    if (!e)+        return -1;+    e->ctx = ctx;+    e->job_func = job_func;+    e->argc = argc;+    for(i = 0; i < argc; i++) {+        e->argv[i] = JS_DupValue(ctx, argv[i]);+    }+    list_add_tail(&e->link, &rt->job_list);+    return 0;+}++BOOL JS_IsJobPending(JSRuntime *rt)+{+    return !list_empty(&rt->job_list);+}++/* return < 0 if exception, 0 if no job pending, 1 if a job was+   executed successfully. the context of the job is stored in '*pctx' */+int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)+{+    JSContext *ctx;+    JSJobEntry *e;+    JSValue res;+    int i, ret;++    if (list_empty(&rt->job_list)) {+        *pctx = NULL;+        return 0;+    }++    /* get the first pending job and execute it */+    e = list_entry(rt->job_list.next, JSJobEntry, link);+    list_del(&e->link);+    ctx = e->ctx;+    res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv);+    for(i = 0; i < e->argc; i++)+        JS_FreeValue(ctx, e->argv[i]);+    if (JS_IsException(res))+        ret = -1;+    else+        ret = 1;+    JS_FreeValue(ctx, res);+    js_free(ctx, e);+    *pctx = ctx;+    return ret;+}++static inline uint32_t atom_get_free(const JSAtomStruct *p)+{+    return (uintptr_t)p >> 1;+}++static inline BOOL atom_is_free(const JSAtomStruct *p)+{+    return (uintptr_t)p & 1;+}++static inline JSAtomStruct *atom_set_free(uint32_t v)+{+    return (JSAtomStruct *)(((uintptr_t)v << 1) | 1);+}++/* Note: the string contents are uninitialized */+static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char)+{+    JSString *str;+    str = js_malloc_rt(rt, sizeof(JSString) + (max_len << is_wide_char) + 1 - is_wide_char);+    if (unlikely(!str))+        return NULL;+    str->header.ref_count = 1;+    str->is_wide_char = is_wide_char;+    str->len = max_len;+    str->atom_type = 0;+    str->hash = 0;          /* optional but costless */+    str->hash_next = 0;     /* optional */+#ifdef DUMP_LEAKS+    list_add_tail(&str->link, &rt->string_list);+#endif+    return str;+}++static JSString *js_alloc_string(JSContext *ctx, int max_len, int is_wide_char)+{+    JSString *p;+    p = js_alloc_string_rt(ctx->rt, max_len, is_wide_char);+    if (unlikely(!p)) {+        JS_ThrowOutOfMemory(ctx);+        return NULL;+    }+    return p;+}++/* same as JS_FreeValueRT() but faster */+static inline void js_free_string(JSRuntime *rt, JSString *str)+{+    if (--str->header.ref_count <= 0) {+        if (str->atom_type) {+            JS_FreeAtomStruct(rt, str);+        } else {+#ifdef DUMP_LEAKS+            list_del(&str->link);+#endif+            js_free_rt(rt, str);+        }+    }+}++void JS_SetRuntimeInfo(JSRuntime *rt, const char *s)+{+    if (rt)+        rt->rt_info = s;+}++void JS_FreeRuntime(JSRuntime *rt)+{+    struct list_head *el, *el1;+    int i;++    JS_FreeValueRT(rt, rt->current_exception);++    list_for_each_safe(el, el1, &rt->job_list) {+        JSJobEntry *e = list_entry(el, JSJobEntry, link);+        for(i = 0; i < e->argc; i++)+            JS_FreeValueRT(rt, e->argv[i]);+        js_free_rt(rt, e);+    }+    init_list_head(&rt->job_list);++    JS_RunGC(rt);++#ifdef DUMP_LEAKS+    /* leaking objects */+    {+        BOOL header_done;+        JSGCObjectHeader *p;+        int count;++        /* remove the internal refcounts to display only the object+           referenced externally */+        list_for_each(el, &rt->gc_obj_list) {+            p = list_entry(el, JSGCObjectHeader, link);+            p->mark = 0;+        }+        gc_decref(rt);++        header_done = FALSE;+        list_for_each(el, &rt->gc_obj_list) {+            p = list_entry(el, JSGCObjectHeader, link);+            if (p->ref_count != 0) {+                if (!header_done) {+                    printf("Object leaks:\n");+                    JS_DumpObjectHeader(rt);+                    header_done = TRUE;+                }+                JS_DumpGCObject(rt, p);+            }+        }++        count = 0;+        list_for_each(el, &rt->gc_obj_list) {+            p = list_entry(el, JSGCObjectHeader, link);+            if (p->ref_count == 0) {+                count++;+            }+        }+        if (count != 0)+            printf("Secondary object leaks: %d\n", count);+    }+#endif+    assert(list_empty(&rt->gc_obj_list));++    /* free the classes */+    for(i = 0; i < rt->class_count; i++) {+        JSClass *cl = &rt->class_array[i];+        if (cl->class_id != 0) {+            JS_FreeAtomRT(rt, cl->class_name);+        }+    }+    js_free_rt(rt, rt->class_array);++#ifdef CONFIG_BIGNUM+    bf_context_end(&rt->bf_ctx);+#endif++#ifdef DUMP_LEAKS+    /* only the atoms defined in JS_InitAtoms() should be left */+    {+        BOOL header_done = FALSE;++        for(i = 0; i < rt->atom_size; i++) {+            JSAtomStruct *p = rt->atom_array[i];+            if (!atom_is_free(p) /* && p->str*/) {+                if (i >= JS_ATOM_END || p->header.ref_count != 1) {+                    if (!header_done) {+                        header_done = TRUE;+                        if (rt->rt_info) {+                            printf("%s:1: atom leakage:", rt->rt_info);+                        } else {+                            printf("Atom leaks:\n"+                                   "    %6s %6s %s\n",+                                   "ID", "REFCNT", "NAME");+                        }+                    }+                    if (rt->rt_info) {+                        printf(" ");+                    } else {+                        printf("    %6u %6u ", i, p->header.ref_count);+                    }+                    switch (p->atom_type) {+                    case JS_ATOM_TYPE_STRING:+                        JS_DumpString(rt, p);+                        break;+                    case JS_ATOM_TYPE_GLOBAL_SYMBOL:+                        printf("Symbol.for(");+                        JS_DumpString(rt, p);+                        printf(")");+                        break;+                    case JS_ATOM_TYPE_SYMBOL:+                        if (p->hash == JS_ATOM_HASH_SYMBOL) {+                            printf("Symbol(");+                            JS_DumpString(rt, p);+                            printf(")");+                        } else {+                            printf("Private(");+                            JS_DumpString(rt, p);+                            printf(")");+                        }+                        break;+                    }+                    if (rt->rt_info) {+                        printf(":%u", p->header.ref_count);+                    } else {+                        printf("\n");+                    }+                }+            }+        }+        if (rt->rt_info && header_done)+            printf("\n");+    }+#endif++    /* free the atoms */+    for(i = 0; i < rt->atom_size; i++) {+        JSAtomStruct *p = rt->atom_array[i];+        if (!atom_is_free(p)) {+#ifdef DUMP_LEAKS+            list_del(&p->link);+#endif+            js_free_rt(rt, p);+        }+    }+    js_free_rt(rt, rt->atom_array);+    js_free_rt(rt, rt->atom_hash);+    js_free_rt(rt, rt->shape_hash);+#ifdef DUMP_LEAKS+    if (!list_empty(&rt->string_list)) {+        if (rt->rt_info) {+            printf("%s:1: string leakage:", rt->rt_info);+        } else {+            printf("String leaks:\n"+                   "    %6s %s\n",+                   "REFCNT", "VALUE");+        }+        list_for_each_safe(el, el1, &rt->string_list) {+            JSString *str = list_entry(el, JSString, link);+            if (rt->rt_info) {+                printf(" ");+            } else {+                printf("    %6u ", str->header.ref_count);+            }+            JS_DumpString(rt, str);+            if (rt->rt_info) {+                printf(":%u", str->header.ref_count);+            } else {+                printf("\n");+            }+            list_del(&str->link);+            js_free_rt(rt, str);+        }+        if (rt->rt_info)+            printf("\n");+    }+    {+        JSMallocState *s = &rt->malloc_state;+        if (s->malloc_count > 1) {+            if (rt->rt_info)+                printf("%s:1: ", rt->rt_info);+            printf("Memory leak: %"PRIu64" bytes lost in %"PRIu64" block%s\n",+                   (uint64_t)(s->malloc_size - sizeof(JSRuntime)),+                   (uint64_t)(s->malloc_count - 1), &"s"[s->malloc_count == 2]);+        }+    }+#endif++    {+        JSMallocState ms = rt->malloc_state;+        rt->mf.js_free(&ms, rt);+    }+}++JSContext *JS_NewContextRaw(JSRuntime *rt)+{+    JSContext *ctx;+    int i;++    ctx = js_mallocz_rt(rt, sizeof(JSContext));+    if (!ctx)+        return NULL;+    ctx->header.ref_count = 1;+    add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT);++    ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) *+                                    rt->class_count);+    if (!ctx->class_proto) {+        js_free_rt(rt, ctx);+        return NULL;+    }+    ctx->rt = rt;+    list_add_tail(&ctx->link, &rt->context_list);+#ifdef CONFIG_BIGNUM+    ctx->bf_ctx = &rt->bf_ctx;+    ctx->fp_env.prec = 113;+    ctx->fp_env.flags = bf_set_exp_bits(15) | BF_RNDN | BF_FLAG_SUBNORMAL;+#endif+    for(i = 0; i < rt->class_count; i++)+        ctx->class_proto[i] = JS_NULL;+    ctx->array_ctor = JS_NULL;+    ctx->regexp_ctor = JS_NULL;+    ctx->promise_ctor = JS_NULL;+    init_list_head(&ctx->loaded_modules);++    JS_AddIntrinsicBasicObjects(ctx);+    return ctx;+}++JSContext *JS_NewContext(JSRuntime *rt)+{+    JSContext *ctx;++    ctx = JS_NewContextRaw(rt);+    if (!ctx)+        return NULL;++    JS_AddIntrinsicBaseObjects(ctx);+    JS_AddIntrinsicDate(ctx);+    JS_AddIntrinsicEval(ctx);+    JS_AddIntrinsicStringNormalize(ctx);+    JS_AddIntrinsicRegExp(ctx);+    JS_AddIntrinsicJSON(ctx);+    JS_AddIntrinsicProxy(ctx);+    JS_AddIntrinsicMapSet(ctx);+    JS_AddIntrinsicTypedArrays(ctx);+    JS_AddIntrinsicPromise(ctx);+#ifdef CONFIG_BIGNUM+    JS_AddIntrinsicBigInt(ctx);+#endif+    return ctx;+}++void *JS_GetContextOpaque(JSContext *ctx)+{+    return ctx->user_opaque;+}++void JS_SetContextOpaque(JSContext *ctx, void *opaque)+{+    ctx->user_opaque = opaque;+}++/* set the new value and free the old value after (freeing the value+   can reallocate the object data) */+static inline void set_value(JSContext *ctx, JSValue *pval, JSValue new_val)+{+    JSValue old_val;+    old_val = *pval;+    *pval = new_val;+    JS_FreeValue(ctx, old_val);+}++void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj)+{+    JSRuntime *rt = ctx->rt;+    assert(class_id < rt->class_count);+    set_value(ctx, &ctx->class_proto[class_id], obj);+}++JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id)+{+    JSRuntime *rt = ctx->rt;+    assert(class_id < rt->class_count);+    return JS_DupValue(ctx, ctx->class_proto[class_id]);+}++typedef enum JSFreeModuleEnum {+    JS_FREE_MODULE_ALL,+    JS_FREE_MODULE_NOT_RESOLVED,+    JS_FREE_MODULE_NOT_EVALUATED,+} JSFreeModuleEnum;++/* XXX: would be more efficient with separate module lists */+static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)+{+    struct list_head *el, *el1;+    list_for_each_safe(el, el1, &ctx->loaded_modules) {+        JSModuleDef *m = list_entry(el, JSModuleDef, link);+        if (flag == JS_FREE_MODULE_ALL ||+            (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved) ||+            (flag == JS_FREE_MODULE_NOT_EVALUATED && !m->evaluated)) {+            js_free_module_def(ctx, m);+        }+    }+}++JSContext *JS_DupContext(JSContext *ctx)+{+    ctx->header.ref_count++;+    return ctx;+}++/* used by the GC */+static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,+                           JS_MarkFunc *mark_func)+{+    int i;+    struct list_head *el;++    /* modules are not seen by the GC, so we directly mark the objects+       referenced by each module */+    list_for_each(el, &ctx->loaded_modules) {+        JSModuleDef *m = list_entry(el, JSModuleDef, link);+        js_mark_module_def(rt, m, mark_func);+    }++    JS_MarkValue(rt, ctx->global_obj, mark_func);+    JS_MarkValue(rt, ctx->global_var_obj, mark_func);++    JS_MarkValue(rt, ctx->throw_type_error, mark_func);+    JS_MarkValue(rt, ctx->eval_obj, mark_func);++    JS_MarkValue(rt, ctx->array_proto_values, mark_func);+    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {+        JS_MarkValue(rt, ctx->native_error_proto[i], mark_func);+    }+    for(i = 0; i < rt->class_count; i++) {+        JS_MarkValue(rt, ctx->class_proto[i], mark_func);+    }+    JS_MarkValue(rt, ctx->iterator_proto, mark_func);+    JS_MarkValue(rt, ctx->async_iterator_proto, mark_func);+    JS_MarkValue(rt, ctx->promise_ctor, mark_func);+    JS_MarkValue(rt, ctx->array_ctor, mark_func);+    JS_MarkValue(rt, ctx->regexp_ctor, mark_func);+    JS_MarkValue(rt, ctx->function_ctor, mark_func);+    JS_MarkValue(rt, ctx->function_proto, mark_func);++    if (ctx->array_shape)+        mark_func(rt, &ctx->array_shape->header);+}++void JS_FreeContext(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    int i;++    if (--ctx->header.ref_count > 0)+        return;+    assert(ctx->header.ref_count == 0);+    +#ifdef DUMP_ATOMS+    JS_DumpAtoms(ctx->rt);+#endif+#ifdef DUMP_SHAPES+    JS_DumpShapes(ctx->rt);+#endif+#ifdef DUMP_OBJECTS+    {+        struct list_head *el;+        JSGCObjectHeader *p;+        printf("JSObjects: {\n");+        JS_DumpObjectHeader(ctx->rt);+        list_for_each(el, &rt->gc_obj_list) {+            p = list_entry(el, JSGCObjectHeader, link);+            JS_DumpGCObject(rt, p);+        }+        printf("}\n");+    }+#endif+#ifdef DUMP_MEM+    {+        JSMemoryUsage stats;+        JS_ComputeMemoryUsage(rt, &stats);+        JS_DumpMemoryUsage(stdout, &stats, rt);+    }+#endif++    js_free_modules(ctx, JS_FREE_MODULE_ALL);++    JS_FreeValue(ctx, ctx->global_obj);+    JS_FreeValue(ctx, ctx->global_var_obj);++    JS_FreeValue(ctx, ctx->throw_type_error);+    JS_FreeValue(ctx, ctx->eval_obj);++    JS_FreeValue(ctx, ctx->array_proto_values);+    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {+        JS_FreeValue(ctx, ctx->native_error_proto[i]);+    }+    for(i = 0; i < rt->class_count; i++) {+        JS_FreeValue(ctx, ctx->class_proto[i]);+    }+    js_free_rt(rt, ctx->class_proto);+    JS_FreeValue(ctx, ctx->iterator_proto);+    JS_FreeValue(ctx, ctx->async_iterator_proto);+    JS_FreeValue(ctx, ctx->promise_ctor);+    JS_FreeValue(ctx, ctx->array_ctor);+    JS_FreeValue(ctx, ctx->regexp_ctor);+    JS_FreeValue(ctx, ctx->function_ctor);+    JS_FreeValue(ctx, ctx->function_proto);++    js_free_shape_null(ctx->rt, ctx->array_shape);++    list_del(&ctx->link);+    remove_gc_object(&ctx->header);+    js_free_rt(ctx->rt, ctx);+}++JSRuntime *JS_GetRuntime(JSContext *ctx)+{+    return ctx->rt;+}++void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size)+{+    rt->stack_size = stack_size;+}++static inline BOOL is_strict_mode(JSContext *ctx)+{+    JSStackFrame *sf = ctx->rt->current_stack_frame;+    return (sf && (sf->js_mode & JS_MODE_STRICT));+}++#ifdef CONFIG_BIGNUM+static inline BOOL is_math_mode(JSContext *ctx)+{+    JSStackFrame *sf = ctx->rt->current_stack_frame;+    return (sf && (sf->js_mode & JS_MODE_MATH));+}+#endif++/* JSAtom support */++#define JS_ATOM_TAG_INT (1U << 31)+#define JS_ATOM_MAX_INT (JS_ATOM_TAG_INT - 1)+#define JS_ATOM_MAX     ((1U << 30) - 1)++/* return the max count from the hash size */+#define JS_ATOM_COUNT_RESIZE(n) ((n) * 2)++static inline BOOL __JS_AtomIsConst(JSAtom v)+{+#if defined(DUMP_LEAKS) && DUMP_LEAKS > 1+        return (int32_t)v <= 0;+#else+        return (int32_t)v < JS_ATOM_END;+#endif+}++static inline BOOL __JS_AtomIsTaggedInt(JSAtom v)+{+    return (v & JS_ATOM_TAG_INT) != 0;+}++static inline JSAtom __JS_AtomFromUInt32(uint32_t v)+{+    return v | JS_ATOM_TAG_INT;+}++static inline uint32_t __JS_AtomToUInt32(JSAtom atom)+{+    return atom & ~JS_ATOM_TAG_INT;+}++static inline int is_num(int c)+{+    return c >= '0' && c <= '9';+}++/* return TRUE if the string is a number n with 0 <= n <= 2^32-1 */+static inline BOOL is_num_string(uint32_t *pval, const JSString *p)+{+    uint32_t n;+    uint64_t n64;+    int c, i, len;++    len = p->len;+    if (len == 0 || len > 10)+        return FALSE;+    if (p->is_wide_char)+        c = p->u.str16[0];+    else+        c = p->u.str8[0];+    if (is_num(c)) {+        if (c == '0') {+            if (len != 1)+                return FALSE;+            n = 0;+        } else {+            n = c - '0';+            for(i = 1; i < len; i++) {+                if (p->is_wide_char)+                    c = p->u.str16[i];+                else+                    c = p->u.str8[i];+                if (!is_num(c))+                    return FALSE;+                n64 = (uint64_t)n * 10 + (c - '0');+                if ((n64 >> 32) != 0)+                    return FALSE;+                n = n64;+            }+        }+        *pval = n;+        return TRUE;+    } else {+        return FALSE;+    }+}++/* XXX: could use faster version ? */+static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h)+{+    size_t i;++    for(i = 0; i < len; i++)+        h = h * 263 + str[i];+    return h;+}++static inline uint32_t hash_string16(const uint16_t *str,+                                     size_t len, uint32_t h)+{+    size_t i;++    for(i = 0; i < len; i++)+        h = h * 263 + str[i];+    return h;+}++static uint32_t hash_string(const JSString *str, uint32_t h)+{+    if (str->is_wide_char)+        h = hash_string16(str->u.str16, str->len, h);+    else+        h = hash_string8(str->u.str8, str->len, h);+    return h;+}++static __maybe_unused void JS_DumpString(JSRuntime *rt,+                                                  const JSString *p)+{+    int i, c, sep;++    if (p == NULL) {+        printf("<null>");+        return;+    }+    printf("%d", p->header.ref_count);+    sep = (p->header.ref_count == 1) ? '\"' : '\'';+    putchar(sep);+    for(i = 0; i < p->len; i++) {+        if (p->is_wide_char)+            c = p->u.str16[i];+        else+            c = p->u.str8[i];+        if (c == sep || c == '\\') {+            putchar('\\');+            putchar(c);+        } else if (c >= ' ' && c <= 126) {+            putchar(c);+        } else if (c == '\n') {+            putchar('\\');+            putchar('n');+        } else {+            printf("\\u%04x", c);+        }+    }+    putchar(sep);+}++static __maybe_unused void JS_DumpAtoms(JSRuntime *rt)+{+    JSAtomStruct *p;+    int h, i;+    /* This only dumps hashed atoms, not JS_ATOM_TYPE_SYMBOL atoms */+    printf("JSAtom count=%d size=%d hash_size=%d:\n",+           rt->atom_count, rt->atom_size, rt->atom_hash_size);+    printf("JSAtom hash table: {\n");+    for(i = 0; i < rt->atom_hash_size; i++) {+        h = rt->atom_hash[i];+        if (h) {+            printf("  %d:", i);+            while (h) {+                p = rt->atom_array[h];+                printf(" ");+                JS_DumpString(rt, p);+                h = p->hash_next;+            }+            printf("\n");+        }+    }+    printf("}\n");+    printf("JSAtom table: {\n");+    for(i = 0; i < rt->atom_size; i++) {+        p = rt->atom_array[i];+        if (!atom_is_free(p)) {+            printf("  %d: { %d %08x ", i, p->atom_type, p->hash);+            if (!(p->len == 0 && p->is_wide_char != 0))+                JS_DumpString(rt, p);+            printf(" %d }\n", p->hash_next);+        }+    }+    printf("}\n");+}++static int JS_ResizeAtomHash(JSRuntime *rt, int new_hash_size)+{+    JSAtomStruct *p;+    uint32_t new_hash_mask, h, i, hash_next1, j, *new_hash;++    assert((new_hash_size & (new_hash_size - 1)) == 0); /* power of two */+    new_hash_mask = new_hash_size - 1;+    new_hash = js_mallocz_rt(rt, sizeof(rt->atom_hash[0]) * new_hash_size);+    if (!new_hash)+        return -1;+    for(i = 0; i < rt->atom_hash_size; i++) {+        h = rt->atom_hash[i];+        while (h != 0) {+            p = rt->atom_array[h];+            hash_next1 = p->hash_next;+            /* add in new hash table */+            j = p->hash & new_hash_mask;+            p->hash_next = new_hash[j];+            new_hash[j] = h;+            h = hash_next1;+        }+    }+    js_free_rt(rt, rt->atom_hash);+    rt->atom_hash = new_hash;+    rt->atom_hash_size = new_hash_size;+    rt->atom_count_resize = JS_ATOM_COUNT_RESIZE(new_hash_size);+    //    JS_DumpAtoms(rt);+    return 0;+}++static int JS_InitAtoms(JSRuntime *rt)+{+    int i, len, atom_type;+    const char *p;++    rt->atom_hash_size = 0;+    rt->atom_hash = NULL;+    rt->atom_count = 0;+    rt->atom_size = 0;+    rt->atom_free_index = 0;+    if (JS_ResizeAtomHash(rt, 256))     /* there are at least 195 predefined atoms */+        return -1;++    p = js_atom_init;+    for(i = 1; i < JS_ATOM_END; i++) {+        if (i == JS_ATOM_Private_brand)+            atom_type = JS_ATOM_TYPE_PRIVATE;+        else if (i >= JS_ATOM_Symbol_toPrimitive)+            atom_type = JS_ATOM_TYPE_SYMBOL;+        else+            atom_type = JS_ATOM_TYPE_STRING;+        len = strlen(p);+        if (__JS_NewAtomInit(rt, p, len, atom_type) == JS_ATOM_NULL)+            return -1;+        p = p + len + 1;+    }+    return 0;+}++static JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v)+{+    JSAtomStruct *p;++    if (!__JS_AtomIsConst(v)) {+        p = rt->atom_array[v];+        p->header.ref_count++;+    }+    return v;+}++JSAtom JS_DupAtom(JSContext *ctx, JSAtom v)+{+    JSRuntime *rt;+    JSAtomStruct *p;++    if (!__JS_AtomIsConst(v)) {+        rt = ctx->rt;+        p = rt->atom_array[v];+        p->header.ref_count++;+    }+    return v;+}++static JSAtomKindEnum JS_AtomGetKind(JSContext *ctx, JSAtom v)+{+    JSRuntime *rt;+    JSAtomStruct *p;++    rt = ctx->rt;+    if (__JS_AtomIsTaggedInt(v))+        return JS_ATOM_KIND_STRING;+    p = rt->atom_array[v];+    switch(p->atom_type) {+    case JS_ATOM_TYPE_STRING:+        return JS_ATOM_KIND_STRING;+    case JS_ATOM_TYPE_GLOBAL_SYMBOL:+        return JS_ATOM_KIND_SYMBOL;+    case JS_ATOM_TYPE_SYMBOL:+        switch(p->hash) {+        case JS_ATOM_HASH_SYMBOL:+            return JS_ATOM_KIND_SYMBOL;+        case JS_ATOM_HASH_PRIVATE:+            return JS_ATOM_KIND_PRIVATE;+        default:+            abort();+        }+    default:+        abort();+    }+}++static BOOL JS_AtomIsString(JSContext *ctx, JSAtom v)+{+    return JS_AtomGetKind(ctx, v) == JS_ATOM_KIND_STRING;+}++static JSAtom js_get_atom_index(JSRuntime *rt, JSAtomStruct *p)+{+    uint32_t i = p->hash_next;  /* atom_index */+    if (p->atom_type != JS_ATOM_TYPE_SYMBOL) {+        JSAtomStruct *p1;++        i = rt->atom_hash[p->hash & (rt->atom_hash_size - 1)];+        p1 = rt->atom_array[i];+        while (p1 != p) {+            assert(i != 0);+            i = p1->hash_next;+            p1 = rt->atom_array[i];+        }+    }+    return i;+}++/* string case (internal). Return JS_ATOM_NULL if error. 'str' is+   freed. */+static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type)+{+    uint32_t h, h1, i;+    JSAtomStruct *p;+    int len;++#if 0+    printf("__JS_NewAtom: ");  JS_DumpString(rt, str); printf("\n");+#endif+    if (atom_type < JS_ATOM_TYPE_SYMBOL) {+        /* str is not NULL */+        if (str->atom_type == atom_type) {+            /* str is the atom, return its index */+            i = js_get_atom_index(rt, str);+            /* reduce string refcount and increase atom's unless constant */+            if (__JS_AtomIsConst(i))+                str->header.ref_count--;+            return i;+        }+        /* try and locate an already registered atom */+        len = str->len;+        h = hash_string(str, atom_type);+        h &= JS_ATOM_HASH_MASK;+        h1 = h & (rt->atom_hash_size - 1);+        i = rt->atom_hash[h1];+        while (i != 0) {+            p = rt->atom_array[i];+            if (p->hash == h &&+                p->atom_type == atom_type &&+                p->len == len &&+                js_string_memcmp(p, str, len) == 0) {+                if (!__JS_AtomIsConst(i))+                    p->header.ref_count++;+                goto done;+            }+            i = p->hash_next;+        }+    } else {+        h1 = 0; /* avoid warning */+        if (atom_type == JS_ATOM_TYPE_SYMBOL) {+            h = JS_ATOM_HASH_SYMBOL;+        } else {+            h = JS_ATOM_HASH_PRIVATE;+            atom_type = JS_ATOM_TYPE_SYMBOL;+        }+    }++    if (rt->atom_free_index == 0) {+        /* allow new atom entries */+        uint32_t new_size, start;+        JSAtomStruct **new_array;++        /* alloc new with size progression 3/2:+           4 6 9 13 19 28 42 63 94 141 211 316 474 711 1066 1599 2398 3597 5395 8092+           preallocating space for predefined atoms (at least 195).+         */+        new_size = max_int(211, rt->atom_size * 3 / 2);+        if (new_size > JS_ATOM_MAX)+            goto fail;+        /* XXX: should use realloc2 to use slack space */+        new_array = js_realloc_rt(rt, rt->atom_array, sizeof(*new_array) * new_size);+        if (!new_array)+            goto fail;+        /* Note: the atom 0 is not used */+        start = rt->atom_size;+        if (start == 0) {+            /* JS_ATOM_NULL entry */+            p = js_mallocz_rt(rt, sizeof(JSAtomStruct));+            if (!p) {+                js_free_rt(rt, new_array);+                goto fail;+            }+            p->header.ref_count = 1;  /* not refcounted */+            p->atom_type = JS_ATOM_TYPE_SYMBOL;+#ifdef DUMP_LEAKS+            list_add_tail(&p->link, &rt->string_list);+#endif+            new_array[0] = p;+            rt->atom_count++;+            start = 1;+        }+        rt->atom_size = new_size;+        rt->atom_array = new_array;+        rt->atom_free_index = start;+        for(i = start; i < new_size; i++) {+            uint32_t next;+            if (i == (new_size - 1))+                next = 0;+            else+                next = i + 1;+            rt->atom_array[i] = atom_set_free(next);+        }+    }++    if (str) {+        if (str->atom_type == 0) {+            p = str;+            p->atom_type = atom_type;+        } else {+            p = js_malloc_rt(rt, sizeof(JSString) ++                             (str->len << str->is_wide_char) ++                             1 - str->is_wide_char);+            if (unlikely(!p))+                goto fail;+            p->header.ref_count = 1;+            p->is_wide_char = str->is_wide_char;+            p->len = str->len;+#ifdef DUMP_LEAKS+            list_add_tail(&p->link, &rt->string_list);+#endif+            memcpy(p->u.str8, str->u.str8, (str->len << str->is_wide_char) ++                   1 - str->is_wide_char);+            js_free_string(rt, str);+        }+    } else {+        p = js_malloc_rt(rt, sizeof(JSAtomStruct)); /* empty wide string */+        if (!p)+            return JS_ATOM_NULL;+        p->header.ref_count = 1;+        p->is_wide_char = 1;    /* Hack to represent NULL as a JSString */+        p->len = 0;+#ifdef DUMP_LEAKS+        list_add_tail(&p->link, &rt->string_list);+#endif+    }++    /* use an already free entry */+    i = rt->atom_free_index;+    rt->atom_free_index = atom_get_free(rt->atom_array[i]);+    rt->atom_array[i] = p;++    p->hash = h;+    p->hash_next = i;   /* atom_index */+    p->atom_type = atom_type;++    rt->atom_count++;++    if (atom_type != JS_ATOM_TYPE_SYMBOL) {+        p->hash_next = rt->atom_hash[h1];+        rt->atom_hash[h1] = i;+        if (unlikely(rt->atom_count >= rt->atom_count_resize))+            JS_ResizeAtomHash(rt, rt->atom_hash_size * 2);+    }++    //    JS_DumpAtoms(rt);+    return i;++ fail:+    i = JS_ATOM_NULL;+ done:+    if (str)+        js_free_string(rt, str);+    return i;+}++/* only works with zero terminated 8 bit strings */+static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len,+                               int atom_type)+{+    JSString *p;+    p = js_alloc_string_rt(rt, len, 0);+    if (!p)+        return JS_ATOM_NULL;+    memcpy(p->u.str8, str, len);+    p->u.str8[len] = '\0';+    return __JS_NewAtom(rt, p, atom_type);+}++static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len,+                            int atom_type)+{+    uint32_t h, h1, i;+    JSAtomStruct *p;++    h = hash_string8((const uint8_t *)str, len, JS_ATOM_TYPE_STRING);+    h &= JS_ATOM_HASH_MASK;+    h1 = h & (rt->atom_hash_size - 1);+    i = rt->atom_hash[h1];+    while (i != 0) {+        p = rt->atom_array[i];+        if (p->hash == h &&+            p->atom_type == JS_ATOM_TYPE_STRING &&+            p->len == len &&+            p->is_wide_char == 0 &&+            memcmp(p->u.str8, str, len) == 0) {+            if (!__JS_AtomIsConst(i))+                p->header.ref_count++;+            return i;+        }+        i = p->hash_next;+    }+    return JS_ATOM_NULL;+}++static void JS_FreeAtomStruct(JSRuntime *rt, JSAtomStruct *p)+{+#if 0   /* JS_ATOM_NULL is not refcounted: __JS_AtomIsConst() includes 0 */+    if (unlikely(i == JS_ATOM_NULL)) {+        p->header.ref_count = INT32_MAX / 2;+        return;+    }+#endif+    uint32_t i = p->hash_next;  /* atom_index */+    if (p->atom_type != JS_ATOM_TYPE_SYMBOL) {+        JSAtomStruct *p0, *p1;+        uint32_t h0;++        h0 = p->hash & (rt->atom_hash_size - 1);+        i = rt->atom_hash[h0];+        p1 = rt->atom_array[i];+        if (p1 == p) {+            rt->atom_hash[h0] = p1->hash_next;+        } else {+            for(;;) {+                assert(i != 0);+                p0 = p1;+                i = p1->hash_next;+                p1 = rt->atom_array[i];+                if (p1 == p) {+                    p0->hash_next = p1->hash_next;+                    break;+                }+            }+        }+    }+    /* insert in free atom list */+    rt->atom_array[i] = atom_set_free(rt->atom_free_index);+    rt->atom_free_index = i;+    /* free the string structure */+#ifdef DUMP_LEAKS+    list_del(&p->link);+#endif+    js_free_rt(rt, p);+    rt->atom_count--;+    assert(rt->atom_count >= 0);+}++static void __JS_FreeAtom(JSRuntime *rt, uint32_t i)+{+    JSAtomStruct *p;++    p = rt->atom_array[i];+    if (--p->header.ref_count > 0)+        return;+    JS_FreeAtomStruct(rt, p);+}++/* Warning: 'p' is freed */+static JSAtom JS_NewAtomStr(JSContext *ctx, JSString *p)+{+    JSRuntime *rt = ctx->rt;+    uint32_t n;+    if (is_num_string(&n, p)) {+        if (n <= JS_ATOM_MAX_INT) {+            js_free_string(rt, p);+            return __JS_AtomFromUInt32(n);+        }+    }+    /* XXX: should generate an exception */+    return __JS_NewAtom(rt, p, JS_ATOM_TYPE_STRING);+}++JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len)+{+    JSValue val;++    if (len == 0 || !is_digit(*str)) {+        JSAtom atom = __JS_FindAtom(ctx->rt, str, len, JS_ATOM_TYPE_STRING);+        if (atom)+            return atom;+    }+    val = JS_NewStringLen(ctx, str, len);+    if (JS_IsException(val))+        return JS_ATOM_NULL;+    return JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(val));+}++JSAtom JS_NewAtom(JSContext *ctx, const char *str)+{+    return JS_NewAtomLen(ctx, str, strlen(str));+}++JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n)+{+    if (n <= JS_ATOM_MAX_INT) {+        return __JS_AtomFromUInt32(n);+    } else {+        char buf[11];+        JSValue val;+        snprintf(buf, sizeof(buf), "%u", n);+        val = JS_NewString(ctx, buf);+        if (JS_IsException(val))+            return JS_ATOM_NULL;+        return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),+                            JS_ATOM_TYPE_STRING);+    }+}++static JSAtom JS_NewAtomInt64(JSContext *ctx, int64_t n)+{+    if ((uint64_t)n <= JS_ATOM_MAX_INT) {+        return __JS_AtomFromUInt32((uint32_t)n);+    } else {+        char buf[24];+        JSValue val;+        snprintf(buf, sizeof(buf), "%" PRId64 , n);+        val = JS_NewString(ctx, buf);+        if (JS_IsException(val))+            return JS_ATOM_NULL;+        return __JS_NewAtom(ctx->rt, JS_VALUE_GET_STRING(val),+                            JS_ATOM_TYPE_STRING);+    }+}++/* 'p' is freed */+static JSValue JS_NewSymbol(JSContext *ctx, JSString *p, int atom_type)+{+    JSRuntime *rt = ctx->rt;+    JSAtom atom;+    atom = __JS_NewAtom(rt, p, atom_type);+    if (atom == JS_ATOM_NULL)+        return JS_ThrowOutOfMemory(ctx);+    return JS_MKPTR(JS_TAG_SYMBOL, rt->atom_array[atom]);+}++/* descr must be a non-numeric string atom */+static JSValue JS_NewSymbolFromAtom(JSContext *ctx, JSAtom descr,+                                    int atom_type)+{+    JSRuntime *rt = ctx->rt;+    JSString *p;++    assert(!__JS_AtomIsTaggedInt(descr));+    assert(descr < rt->atom_size);+    p = rt->atom_array[descr];+    JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));+    return JS_NewSymbol(ctx, p, atom_type);+}++#define ATOM_GET_STR_BUF_SIZE 64++/* Should only be used for debug. */+static const char *JS_AtomGetStrRT(JSRuntime *rt, char *buf, int buf_size,+                                   JSAtom atom)+{+    if (__JS_AtomIsTaggedInt(atom)) {+        snprintf(buf, buf_size, "%u", __JS_AtomToUInt32(atom));+    } else {+        JSAtomStruct *p;+        assert(atom < rt->atom_size);+        if (atom == JS_ATOM_NULL) {+            snprintf(buf, buf_size, "<null>");+        } else {+            int i, c;+            char *q;+            JSString *str;++            q = buf;+            p = rt->atom_array[atom];+            assert(!atom_is_free(p));+            str = p;+            if (str) {+                if (!str->is_wide_char) {+                    /* special case ASCII strings */+                    c = 0;+                    for(i = 0; i < str->len; i++) {+                        c |= str->u.str8[i];+                    }+                    if (c < 0x80)+                        return (const char *)str->u.str8;+                }+                for(i = 0; i < str->len; i++) {+                    if (str->is_wide_char)+                        c = str->u.str16[i];+                    else+                        c = str->u.str8[i];+                    if ((q - buf) >= buf_size - UTF8_CHAR_LEN_MAX)+                        break;+                    if (c < 128) {+                        *q++ = c;+                    } else {+                        q += unicode_to_utf8((uint8_t *)q, c);+                    }+                }+            }+            *q = '\0';+        }+    }+    return buf;+}++static const char *JS_AtomGetStr(JSContext *ctx, char *buf, int buf_size, JSAtom atom)+{+    return JS_AtomGetStrRT(ctx->rt, buf, buf_size, atom);+}++static JSValue __JS_AtomToValue(JSContext *ctx, JSAtom atom, BOOL force_string)+{+    char buf[ATOM_GET_STR_BUF_SIZE];++    if (__JS_AtomIsTaggedInt(atom)) {+        snprintf(buf, sizeof(buf), "%u", __JS_AtomToUInt32(atom));+        return JS_NewString(ctx, buf);+    } else {+        JSRuntime *rt = ctx->rt;+        JSAtomStruct *p;+        assert(atom < rt->atom_size);+        p = rt->atom_array[atom];+        if (p->atom_type == JS_ATOM_TYPE_STRING) {+            goto ret_string;+        } else if (force_string) {+            if (p->len == 0 && p->is_wide_char != 0) {+                /* no description string */+                p = rt->atom_array[JS_ATOM_empty_string];+            }+        ret_string:+            return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));+        } else {+            return JS_DupValue(ctx, JS_MKPTR(JS_TAG_SYMBOL, p));+        }+    }+}++JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom)+{+    return __JS_AtomToValue(ctx, atom, FALSE);+}++JSValue JS_AtomToString(JSContext *ctx, JSAtom atom)+{+    return __JS_AtomToValue(ctx, atom, TRUE);+}++/* return TRUE if the atom is an array index (i.e. 0 <= index <=+   2^32-2 and return its value */+static BOOL JS_AtomIsArrayIndex(JSContext *ctx, uint32_t *pval, JSAtom atom)+{+    if (__JS_AtomIsTaggedInt(atom)) {+        *pval = __JS_AtomToUInt32(atom);+        return TRUE;+    } else {+        JSRuntime *rt = ctx->rt;+        JSAtomStruct *p;+        uint32_t val;++        assert(atom < rt->atom_size);+        p = rt->atom_array[atom];+        if (p->atom_type == JS_ATOM_TYPE_STRING &&+            is_num_string(&val, p) && val != -1) {+            *pval = val;+            return TRUE;+        } else {+            *pval = 0;+            return FALSE;+        }+    }+}++/* This test must be fast if atom is not a numeric index (e.g. a+   method name). Return JS_UNDEFINED if not a numeric+   index. JS_EXCEPTION can also be returned. */+static JSValue JS_AtomIsNumericIndex1(JSContext *ctx, JSAtom atom)+{+    JSRuntime *rt = ctx->rt;+    JSAtomStruct *p1;+    JSString *p;+    int c, len, ret;+    JSValue num, str;++    if (__JS_AtomIsTaggedInt(atom))+        return JS_NewInt32(ctx, __JS_AtomToUInt32(atom));+    assert(atom < rt->atom_size);+    p1 = rt->atom_array[atom];+    if (p1->atom_type != JS_ATOM_TYPE_STRING)+        return JS_UNDEFINED;+    p = p1;+    len = p->len;+    if (p->is_wide_char) {+        const uint16_t *r = p->u.str16, *r_end = p->u.str16 + len;+        if (r >= r_end)+            return JS_UNDEFINED;+        c = *r;+        if (c == '-') {+            if (r >= r_end)+                return JS_UNDEFINED;+            r++;+            c = *r;+            /* -0 case is specific */+            if (c == '0' && len == 2)+                goto minus_zero;+        }+        /* XXX: should test NaN, but the tests do not check it */+        if (!is_num(c)) {+            /* XXX: String should be normalized, therefore 8-bit only */+            const uint16_t nfinity16[7] = { 'n', 'f', 'i', 'n', 'i', 't', 'y' };+            if (!(c =='I' && (r_end - r) == 8 &&+                  !memcmp(r + 1, nfinity16, sizeof(nfinity16))))+                return JS_UNDEFINED;+        }+    } else {+        const uint8_t *r = p->u.str8, *r_end = p->u.str8 + len;+        if (r >= r_end)+            return JS_UNDEFINED;+        c = *r;+        if (c == '-') {+            if (r >= r_end)+                return JS_UNDEFINED;+            r++;+            c = *r;+            /* -0 case is specific */+            if (c == '0' && len == 2) {+            minus_zero:+                return __JS_NewFloat64(ctx, -0.0);+            }+        }+        if (!is_num(c)) {+            if (!(c =='I' && (r_end - r) == 8 &&+                  !memcmp(r + 1, "nfinity", 7)))+                return JS_UNDEFINED;+        }+    }+    /* XXX: bignum: would be better to only accept integer to avoid+       relying on current floating point precision */+    /* this is ECMA CanonicalNumericIndexString primitive */+    num = JS_ToNumber(ctx, JS_MKPTR(JS_TAG_STRING, p));+    if (JS_IsException(num))+        return num;+    str = JS_ToString(ctx, num);+    if (JS_IsException(str)) {+        JS_FreeValue(ctx, num);+        return str;+    }+    ret = js_string_compare(ctx, p, JS_VALUE_GET_STRING(str));+    JS_FreeValue(ctx, str);+    if (ret == 0) {+        return num;+    } else {+        JS_FreeValue(ctx, num);+        return JS_UNDEFINED;+    }+}++/* return -1 if exception or TRUE/FALSE */+static int JS_AtomIsNumericIndex(JSContext *ctx, JSAtom atom)+{+    JSValue num;+    num = JS_AtomIsNumericIndex1(ctx, atom);+    if (likely(JS_IsUndefined(num)))+        return FALSE;+    if (JS_IsException(num))+        return -1;+    JS_FreeValue(ctx, num);+    return TRUE;+}++void JS_FreeAtom(JSContext *ctx, JSAtom v)+{+    if (!__JS_AtomIsConst(v))+        __JS_FreeAtom(ctx->rt, v);+}++void JS_FreeAtomRT(JSRuntime *rt, JSAtom v)+{+    if (!__JS_AtomIsConst(v))+        __JS_FreeAtom(rt, v);+}++/* return TRUE if 'v' is a symbol with a string description */+static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)+{+    JSRuntime *rt;+    JSAtomStruct *p;++    rt = ctx->rt;+    if (__JS_AtomIsTaggedInt(v))+        return FALSE;+    p = rt->atom_array[v];+    return (((p->atom_type == JS_ATOM_TYPE_SYMBOL &&+              p->hash == JS_ATOM_HASH_SYMBOL) ||+             p->atom_type == JS_ATOM_TYPE_GLOBAL_SYMBOL) &&+            !(p->len == 0 && p->is_wide_char != 0));+}++static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    const char *p;+    int i;++    /* XXX: should handle embedded null characters */+    /* XXX: should move encoding code to JS_AtomGetStr */+    p = JS_AtomGetStr(ctx, buf, sizeof(buf), atom);+    for (i = 0; p[i]; i++) {+        int c = (unsigned char)p[i];+        if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||+              (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0)))+            break;+    }+    if (i > 0 && p[i] == '\0') {+        printf("%s", p);+    } else {+        putchar('"');+        printf("%.*s", i, p);+        for (; p[i]; i++) {+            int c = (unsigned char)p[i];+            if (c == '\"' || c == '\\') {+                putchar('\\');+                putchar(c);+            } else if (c >= ' ' && c <= 126) {+                putchar(c);+            } else if (c == '\n') {+                putchar('\\');+                putchar('n');+            } else {+                printf("\\u%04x", c);+            }+        }+        putchar('\"');+    }+}++/* free with JS_FreeCString() */+const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)+{+    JSValue str;+    const char *cstr;++    str = JS_AtomToString(ctx, atom);+    if (JS_IsException(str))+        return NULL;+    cstr = JS_ToCString(ctx, str);+    JS_FreeValue(ctx, str);+    return cstr;+}++/* return a string atom containing name concatenated with str1 */+static JSAtom js_atom_concat_str(JSContext *ctx, JSAtom name, const char *str1)+{+    JSValue str;+    JSAtom atom;+    const char *cstr;+    char *cstr2;+    size_t len, len1;+    +    str = JS_AtomToString(ctx, name);+    if (JS_IsException(str))+        return JS_ATOM_NULL;+    cstr = JS_ToCStringLen(ctx, &len, str);+    if (!cstr)+        goto fail;+    len1 = strlen(str1);+    cstr2 = js_malloc(ctx, len + len1 + 1);+    if (!cstr2)+        goto fail;+    memcpy(cstr2, cstr, len);+    memcpy(cstr2 + len, str1, len1);+    cstr2[len + len1] = '\0';+    atom = JS_NewAtomLen(ctx, cstr2, len + len1);+    js_free(ctx, cstr2);+    JS_FreeCString(ctx, cstr);+    JS_FreeValue(ctx, str);+    return atom;+ fail:+    JS_FreeCString(ctx, cstr);+    JS_FreeValue(ctx, str);+    return JS_ATOM_NULL;+}++static JSAtom js_atom_concat_num(JSContext *ctx, JSAtom name, uint32_t n)+{+    char buf[16];+    snprintf(buf, sizeof(buf), "%u", n);+    return js_atom_concat_str(ctx, name, buf);+}++static inline BOOL JS_IsEmptyString(JSValueConst v)+{+    return JS_VALUE_GET_TAG(v) == JS_TAG_STRING && JS_VALUE_GET_STRING(v)->len == 0;+}++/* JSClass support */++/* a new class ID is allocated if *pclass_id != 0 */+JSClassID JS_NewClassID(JSClassID *pclass_id)+{+    JSClassID class_id;+    /* XXX: make it thread safe */+    class_id = *pclass_id;+    if (class_id == 0) {+        class_id = js_class_id_alloc++;+        *pclass_id = class_id;+    }+    return class_id;+}++BOOL JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id)+{+    return (class_id < rt->class_count &&+            rt->class_array[class_id].class_id != 0);+}++/* create a new object internal class. Return -1 if error, 0 if+   OK. The finalizer can be NULL if none is needed. */+static int JS_NewClass1(JSRuntime *rt, JSClassID class_id,+                        const JSClassDef *class_def, JSAtom name)+{+    int new_size, i;+    JSClass *cl, *new_class_array;+    struct list_head *el;++    if (class_id < rt->class_count &&+        rt->class_array[class_id].class_id != 0)+        return -1;++    if (class_id >= rt->class_count) {+        new_size = max_int(JS_CLASS_INIT_COUNT,+                           max_int(class_id + 1, rt->class_count * 3 / 2));++        /* reallocate the context class prototype array, if any */+        list_for_each(el, &rt->context_list) {+            JSContext *ctx = list_entry(el, JSContext, link);+            JSValue *new_tab;+            new_tab = js_realloc_rt(rt, ctx->class_proto,+                                    sizeof(ctx->class_proto[0]) * new_size);+            if (!new_tab)+                return -1;+            for(i = rt->class_count; i < new_size; i++)+                new_tab[i] = JS_NULL;+            ctx->class_proto = new_tab;+        }+        /* reallocate the class array */+        new_class_array = js_realloc_rt(rt, rt->class_array,+                                        sizeof(JSClass) * new_size);+        if (!new_class_array)+            return -1;+        memset(new_class_array + rt->class_count, 0,+               (new_size - rt->class_count) * sizeof(JSClass));+        rt->class_array = new_class_array;+        rt->class_count = new_size;+    }+    cl = &rt->class_array[class_id];+    cl->class_id = class_id;+    cl->class_name = JS_DupAtomRT(rt, name);+    cl->finalizer = class_def->finalizer;+    cl->gc_mark = class_def->gc_mark;+    cl->call = class_def->call;+    cl->exotic = class_def->exotic;+    return 0;+}++int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def)+{+    int ret, len;+    JSAtom name;++    len = strlen(class_def->class_name);+    name = __JS_FindAtom(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);+    if (name == JS_ATOM_NULL) {+        name = __JS_NewAtomInit(rt, class_def->class_name, len, JS_ATOM_TYPE_STRING);+        if (name == JS_ATOM_NULL)+            return -1;+    }+    ret = JS_NewClass1(rt, class_id, class_def, name);+    JS_FreeAtomRT(rt, name);+    return ret;+}++static JSValue js_new_string8(JSContext *ctx, const uint8_t *buf, int len)+{+    JSString *str;++    if (len <= 0) {+        return JS_AtomToString(ctx, JS_ATOM_empty_string);+    }+    str = js_alloc_string(ctx, len, 0);+    if (!str)+        return JS_EXCEPTION;+    memcpy(str->u.str8, buf, len);+    str->u.str8[len] = '\0';+    return JS_MKPTR(JS_TAG_STRING, str);+}++static JSValue js_new_string16(JSContext *ctx, const uint16_t *buf, int len)+{+    JSString *str;+    str = js_alloc_string(ctx, len, 1);+    if (!str)+        return JS_EXCEPTION;+    memcpy(str->u.str16, buf, len * 2);+    return JS_MKPTR(JS_TAG_STRING, str);+}++static JSValue js_new_string_char(JSContext *ctx, uint16_t c)+{+    if (c < 0x100) {+        uint8_t ch8 = c;+        return js_new_string8(ctx, &ch8, 1);+    } else {+        uint16_t ch16 = c;+        return js_new_string16(ctx, &ch16, 1);+    }+}++static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end)+{+    int len = end - start;+    if (start == 0 && end == p->len) {+        return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));+    }+    if (p->is_wide_char && len > 0) {+        JSString *str;+        int i;+        uint16_t c = 0;+        for (i = start; i < end; i++) {+            c |= p->u.str16[i];+        }+        if (c > 0xFF)+            return js_new_string16(ctx, p->u.str16 + start, len);++        str = js_alloc_string(ctx, len, 0);+        if (!str)+            return JS_EXCEPTION;+        for (i = 0; i < len; i++) {+            str->u.str8[i] = p->u.str16[start + i];+        }+        str->u.str8[len] = '\0';+        return JS_MKPTR(JS_TAG_STRING, str);+    } else {+        return js_new_string8(ctx, p->u.str8 + start, len);+    }+}++typedef struct StringBuffer {+    JSContext *ctx;+    JSString *str;+    int len;+    int size;+    int is_wide_char;+    int error_status;+} StringBuffer;++/* It is valid to call string_buffer_end() and all string_buffer functions even+   if string_buffer_init() or another string_buffer function returns an error.+   If the error_status is set, string_buffer_end() returns JS_EXCEPTION.+ */+static int string_buffer_init2(JSContext *ctx, StringBuffer *s, int size,+                               int is_wide)+{+    s->ctx = ctx;+    s->size = size;+    s->len = 0;+    s->is_wide_char = is_wide;+    s->error_status = 0;+    s->str = js_alloc_string(ctx, size, is_wide);+    if (unlikely(!s->str)) {+        s->size = 0;+        return s->error_status = -1;+    }+#ifdef DUMP_LEAKS+    /* the StringBuffer may reallocate the JSString, only link it at the end */+    list_del(&s->str->link);+#endif+    return 0;+}++static inline int string_buffer_init(JSContext *ctx, StringBuffer *s, int size)+{+    return string_buffer_init2(ctx, s, size, 0);+}++static void string_buffer_free(StringBuffer *s)+{+    js_free(s->ctx, s->str);+    s->str = NULL;+}++static int string_buffer_set_error(StringBuffer *s)+{+    js_free(s->ctx, s->str);+    s->str = NULL;+    s->size = 0;+    s->len = 0;+    return s->error_status = -1;+}++static no_inline int string_buffer_widen(StringBuffer *s, int size)+{+    JSString *str;+    size_t slack;+    int i;++    if (s->error_status)+        return -1;++    str = js_realloc2(s->ctx, s->str, sizeof(JSString) + (size << 1), &slack);+    if (!str)+        return string_buffer_set_error(s);+    size += slack >> 1;+    for(i = s->len; i-- > 0;) {+        str->u.str16[i] = str->u.str8[i];+    }+    s->is_wide_char = 1;+    s->size = size;+    s->str = str;+    return 0;+}++static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c)+{+    JSString *new_str;+    int new_size;+    size_t new_size_bytes, slack;++    if (s->error_status)+        return -1;++    if (new_len > JS_STRING_LEN_MAX) {+        JS_ThrowInternalError(s->ctx, "string too long");+        return string_buffer_set_error(s);+    }+    new_size = min_int(max_int(new_len, s->size * 3 / 2), JS_STRING_LEN_MAX);+    if (!s->is_wide_char && c >= 0x100) {+        return string_buffer_widen(s, new_size);+    }+    new_size_bytes = sizeof(JSString) + (new_size << s->is_wide_char) + 1 - s->is_wide_char;+    new_str = js_realloc2(s->ctx, s->str, new_size_bytes, &slack);+    if (!new_str)+        return string_buffer_set_error(s);+    new_size = min_int(new_size + (slack >> s->is_wide_char), JS_STRING_LEN_MAX);+    s->size = new_size;+    s->str = new_str;+    return 0;+}++static no_inline int string_buffer_putc_slow(StringBuffer *s, uint32_t c)+{+    if (unlikely(s->len >= s->size)) {+        if (string_buffer_realloc(s, s->len + 1, c))+            return -1;+    }+    if (s->is_wide_char) {+        s->str->u.str16[s->len++] = c;+    } else if (c < 0x100) {+        s->str->u.str8[s->len++] = c;+    } else {+        if (string_buffer_widen(s, s->size))+            return -1;+        s->str->u.str16[s->len++] = c;+    }+    return 0;+}++/* 0 <= c <= 0xff */+static int string_buffer_putc8(StringBuffer *s, uint32_t c)+{+    if (unlikely(s->len >= s->size)) {+        if (string_buffer_realloc(s, s->len + 1, c))+            return -1;+    }+    if (s->is_wide_char) {+        s->str->u.str16[s->len++] = c;+    } else {+        s->str->u.str8[s->len++] = c;+    }+    return 0;+}++/* 0 <= c <= 0xffff */+static int string_buffer_putc16(StringBuffer *s, uint32_t c)+{+    if (likely(s->len < s->size)) {+        if (s->is_wide_char) {+            s->str->u.str16[s->len++] = c;+            return 0;+        } else if (c < 0x100) {+            s->str->u.str8[s->len++] = c;+            return 0;+        }+    }+    return string_buffer_putc_slow(s, c);+}++/* 0 <= c <= 0x10ffff */+static int string_buffer_putc(StringBuffer *s, uint32_t c)+{+    if (unlikely(c >= 0x10000)) {+        /* surrogate pair */+        c -= 0x10000;+        if (string_buffer_putc16(s, (c >> 10) + 0xd800))+            return -1;+        c = (c & 0x3ff) + 0xdc00;+    }+    return string_buffer_putc16(s, c);+}++static int string_get(const JSString *p, int idx) {+    return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx];+}++static int string_getc(const JSString *p, int *pidx)+{+    int idx, c, c1;+    idx = *pidx;+    if (p->is_wide_char) {+        c = p->u.str16[idx++];+        if (c >= 0xd800 && c < 0xdc00 && idx < p->len) {+            c1 = p->u.str16[idx];+            if (c1 >= 0xdc00 && c1 < 0xe000) {+                c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;+                idx++;+            }+        }+    } else {+        c = p->u.str8[idx++];+    }+    *pidx = idx;+    return c;+}++static int string_buffer_write8(StringBuffer *s, const uint8_t *p, int len)+{+    int i;++    if (s->len + len > s->size) {+        if (string_buffer_realloc(s, s->len + len, 0))+            return -1;+    }+    if (s->is_wide_char) {+        for (i = 0; i < len; i++) {+            s->str->u.str16[s->len + i] = p[i];+        }+        s->len += len;+    } else {+        memcpy(&s->str->u.str8[s->len], p, len);+        s->len += len;+    }+    return 0;+}++static int string_buffer_write16(StringBuffer *s, const uint16_t *p, int len)+{+    int c = 0, i;++    for (i = 0; i < len; i++) {+        c |= p[i];+    }+    if (s->len + len > s->size) {+        if (string_buffer_realloc(s, s->len + len, c))+            return -1;+    } else if (!s->is_wide_char && c >= 0x100) {+        if (string_buffer_widen(s, s->size))+            return -1;+    }+    if (s->is_wide_char) {+        memcpy(&s->str->u.str16[s->len], p, len << 1);+        s->len += len;+    } else {+        for (i = 0; i < len; i++) {+            s->str->u.str8[s->len + i] = p[i];+        }+        s->len += len;+    }+    return 0;+}++/* appending an ASCII string */+static int string_buffer_puts8(StringBuffer *s, const char *str)+{+    return string_buffer_write8(s, (const uint8_t *)str, strlen(str));+}++static int string_buffer_concat(StringBuffer *s, const JSString *p,+                                uint32_t from, uint32_t to)+{+    if (to <= from)+        return 0;+    if (p->is_wide_char)+        return string_buffer_write16(s, p->u.str16 + from, to - from);+    else+        return string_buffer_write8(s, p->u.str8 + from, to - from);+}++static int string_buffer_concat_value(StringBuffer *s, JSValueConst v)+{+    JSString *p;+    JSValue v1;+    int res;++    if (s->error_status) {+        /* prevent exception overload */+        return -1;+    }+    if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) {+        v1 = JS_ToString(s->ctx, v);+        if (JS_IsException(v1))+            return string_buffer_set_error(s);+        p = JS_VALUE_GET_STRING(v1);+        res = string_buffer_concat(s, p, 0, p->len);+        JS_FreeValue(s->ctx, v1);+        return res;+    }+    p = JS_VALUE_GET_STRING(v);+    return string_buffer_concat(s, p, 0, p->len);+}++static int string_buffer_concat_value_free(StringBuffer *s, JSValue v)+{+    JSString *p;+    int res;++    if (s->error_status) {+        /* prevent exception overload */+        JS_FreeValue(s->ctx, v);+        return -1;+    }+    if (unlikely(JS_VALUE_GET_TAG(v) != JS_TAG_STRING)) {+        v = JS_ToStringFree(s->ctx, v);+        if (JS_IsException(v))+            return string_buffer_set_error(s);+    }+    p = JS_VALUE_GET_STRING(v);+    res = string_buffer_concat(s, p, 0, p->len);+    JS_FreeValue(s->ctx, v);+    return res;+}++static int string_buffer_fill(StringBuffer *s, int c, int count)+{+    /* XXX: optimize */+    if (s->len + count > s->size) {+        if (string_buffer_realloc(s, s->len + count, c))+            return -1;+    }+    while (count-- > 0) {+        if (string_buffer_putc16(s, c))+            return -1;+    }+    return 0;+}++static JSValue string_buffer_end(StringBuffer *s)+{+    JSString *str;+    str = s->str;+    if (s->error_status)+        return JS_EXCEPTION;+    if (s->len == 0) {+        js_free(s->ctx, str);+        s->str = NULL;+        return JS_AtomToString(s->ctx, JS_ATOM_empty_string);+    }+    if (s->len < s->size) {+        /* smaller size so js_realloc should not fail, but OK if it does */+        /* XXX: should add some slack to avoid unnecessary calls */+        /* XXX: might need to use malloc+free to ensure smaller size */+        str = js_realloc_rt(s->ctx->rt, str, sizeof(JSString) ++                            (s->len << s->is_wide_char) + 1 - s->is_wide_char);+        if (str == NULL)+            str = s->str;+        s->str = str;+    }+    if (!s->is_wide_char)+        str->u.str8[s->len] = 0;+#ifdef DUMP_LEAKS+    list_add_tail(&str->link, &s->ctx->rt->string_list);+#endif+    str->is_wide_char = s->is_wide_char;+    str->len = s->len;+    s->str = NULL;+    return JS_MKPTR(JS_TAG_STRING, str);+}++/* create a string from a UTF-8 buffer */+JSValue JS_NewStringLen(JSContext *ctx, const char *buf, size_t buf_len)+{+    const uint8_t *p, *p_end, *p_start, *p_next;+    uint32_t c;+    StringBuffer b_s, *b = &b_s;+    size_t len1;+    +    p_start = (const uint8_t *)buf;+    p_end = p_start + buf_len;+    p = p_start;+    while (p < p_end && *p < 128)+        p++;+    len1 = p - p_start;+    if (len1 > JS_STRING_LEN_MAX)+        return JS_ThrowInternalError(ctx, "string too long");+    if (p == p_end) {+        /* ASCII string */+        return js_new_string8(ctx, (const uint8_t *)buf, buf_len);+    } else {+        if (string_buffer_init(ctx, b, buf_len))+            goto fail;+        string_buffer_write8(b, p_start, len1);+        while (p < p_end) {+            if (*p < 128) {+                string_buffer_putc8(b, *p++);+            } else {+                /* parse utf-8 sequence, return 0xFFFFFFFF for error */+                c = unicode_from_utf8(p, p_end - p, &p_next);+                if (c < 0x10000) {+                    p = p_next;+                } else if (c <= 0x10FFFF) {+                    p = p_next;+                    /* surrogate pair */+                    c -= 0x10000;+                    string_buffer_putc16(b, (c >> 10) + 0xd800);+                    c = (c & 0x3ff) + 0xdc00;+                } else {+                    /* invalid char */+                    c = 0xfffd;+                    /* skip the invalid chars */+                    /* XXX: seems incorrect. Why not just use c = *p++; ? */+                    while (p < p_end && (*p >= 0x80 && *p < 0xc0))+                        p++;+                    if (p < p_end) {+                        p++;+                        while (p < p_end && (*p >= 0x80 && *p < 0xc0))+                            p++;+                    }+                }+                string_buffer_putc16(b, c);+            }+        }+    }+    return string_buffer_end(b);++ fail:+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue JS_ConcatString3(JSContext *ctx, const char *str1,+                                JSValue str2, const char *str3)+{+    StringBuffer b_s, *b = &b_s;+    int len1, len3;+    JSString *p;++    if (unlikely(JS_VALUE_GET_TAG(str2) != JS_TAG_STRING)) {+        str2 = JS_ToStringFree(ctx, str2);+        if (JS_IsException(str2))+            goto fail;+    }+    p = JS_VALUE_GET_STRING(str2);+    len1 = strlen(str1);+    len3 = strlen(str3);++    if (string_buffer_init2(ctx, b, len1 + p->len + len3, p->is_wide_char))+        goto fail;++    string_buffer_write8(b, (const uint8_t *)str1, len1);+    string_buffer_concat(b, p, 0, p->len);+    string_buffer_write8(b, (const uint8_t *)str3, len3);++    JS_FreeValue(ctx, str2);+    return string_buffer_end(b);++ fail:+    JS_FreeValue(ctx, str2);+    return JS_EXCEPTION;+}++JSValue JS_NewString(JSContext *ctx, const char *str)+{+    return JS_NewStringLen(ctx, str, strlen(str));+}++JSValue JS_NewAtomString(JSContext *ctx, const char *str)+{+    JSAtom atom = JS_NewAtom(ctx, str);+    if (atom == JS_ATOM_NULL)+        return JS_EXCEPTION;+    JSValue val = JS_AtomToString(ctx, atom);+    JS_FreeAtom(ctx, atom);+    return val;+}++/* return (NULL, 0) if exception. */+/* return pointer into a JSString with a live ref_count */+/* cesu8 determines if non-BMP1 codepoints are encoded as 1 or 2 utf-8 sequences */+const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, BOOL cesu8)+{+    JSValue val;+    JSString *str, *str_new;+    int pos, len, c, c1;+    uint8_t *q;++    if (JS_VALUE_GET_TAG(val1) != JS_TAG_STRING) {+        val = JS_ToString(ctx, val1);+        if (JS_IsException(val))+            goto fail;+    } else {+        val = JS_DupValue(ctx, val1);+    }++    str = JS_VALUE_GET_STRING(val);+    len = str->len;+    if (!str->is_wide_char) {+        const uint8_t *src = str->u.str8;+        int count;++        /* count the number of non-ASCII characters */+        /* Scanning the whole string is required for ASCII strings,+           and computing the number of non-ASCII bytes is less expensive+           than testing each byte, hence this method is faster for ASCII+           strings, which is the most common case.+         */+        count = 0;+        for (pos = 0; pos < len; pos++) {+            count += src[pos] >> 7;+        }+        if (count == 0) {+            if (plen)+                *plen = len;+            return (const char *)src;+        }+        str_new = js_alloc_string(ctx, len + count, 0);+        if (!str_new)+            goto fail;+        q = str_new->u.str8;+        for (pos = 0; pos < len; pos++) {+            c = src[pos];+            if (c < 0x80) {+                *q++ = c;+            } else {+                *q++ = (c >> 6) | 0xc0;+                *q++ = (c & 0x3f) | 0x80;+            }+        }+    } else {+        const uint16_t *src = str->u.str16;+        /* Allocate 3 bytes per 16 bit code point. Surrogate pairs may+           produce 4 bytes but use 2 code points.+         */+        str_new = js_alloc_string(ctx, len * 3, 0);+        if (!str_new)+            goto fail;+        q = str_new->u.str8;+        pos = 0;+        while (pos < len) {+            c = src[pos++];+            if (c < 0x80) {+                *q++ = c;+            } else {+                if (c >= 0xd800 && c < 0xdc00) {+                    if (pos < len && !cesu8) {+                        c1 = src[pos];+                        if (c1 >= 0xdc00 && c1 < 0xe000) {+                            pos++;+                            /* surrogate pair */+                            c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;+                        } else {+                            /* Keep unmatched surrogate code points */+                            /* c = 0xfffd; */ /* error */+                        }+                    } else {+                        /* Keep unmatched surrogate code points */+                        /* c = 0xfffd; */ /* error */+                    }+                }+                q += unicode_to_utf8(q, c);+            }+        }+    }++    *q = '\0';+    str_new->len = q - str_new->u.str8;+    JS_FreeValue(ctx, val);+    if (plen)+        *plen = str_new->len;+    return (const char *)str_new->u.str8;+ fail:+    if (plen)+        *plen = 0;+    return NULL;+}++void JS_FreeCString(JSContext *ctx, const char *ptr)+{+    JSString *p;+    if (!ptr)+        return;+    /* purposely removing constness */+    p = (JSString *)(void *)(ptr - offsetof(JSString, u));+    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, p));+}++static int memcmp16_8(const uint16_t *src1, const uint8_t *src2, int len)+{+    int c, i;+    for(i = 0; i < len; i++) {+        c = src1[i] - src2[i];+        if (c != 0)+            return c;+    }+    return 0;+}++static int memcmp16(const uint16_t *src1, const uint16_t *src2, int len)+{+    int c, i;+    for(i = 0; i < len; i++) {+        c = src1[i] - src2[i];+        if (c != 0)+            return c;+    }+    return 0;+}++static int js_string_memcmp(const JSString *p1, const JSString *p2, int len)+{+    int res;++    if (likely(!p1->is_wide_char)) {+        if (likely(!p2->is_wide_char))+            res = memcmp(p1->u.str8, p2->u.str8, len);+        else+            res = -memcmp16_8(p2->u.str16, p1->u.str8, len);+    } else {+        if (!p2->is_wide_char)+            res = memcmp16_8(p1->u.str16, p2->u.str8, len);+        else+            res = memcmp16(p1->u.str16, p2->u.str16, len);+    }+    return res;+}++/* return < 0, 0 or > 0 */+static int js_string_compare(JSContext *ctx,+                             const JSString *p1, const JSString *p2)+{+    int res, len;+    len = min_int(p1->len, p2->len);+    res = js_string_memcmp(p1, p2, len);+    if (res == 0) {+        if (p1->len == p2->len)+            res = 0;+        else if (p1->len < p2->len)+            res = -1;+        else+            res = 1;+    }+    return res;+}++static void copy_str16(uint16_t *dst, const JSString *p, int offset, int len)+{+    if (p->is_wide_char) {+        memcpy(dst, p->u.str16 + offset, len * 2);+    } else {+        const uint8_t *src1 = p->u.str8 + offset;+        int i;++        for(i = 0; i < len; i++)+            dst[i] = src1[i];+    }+}++static JSValue JS_ConcatString1(JSContext *ctx,+                                const JSString *p1, const JSString *p2)+{+    JSString *p;+    uint32_t len;+    int is_wide_char;++    len = p1->len + p2->len;+    if (len > JS_STRING_LEN_MAX)+        return JS_ThrowInternalError(ctx, "string too long");+    is_wide_char = p1->is_wide_char | p2->is_wide_char;+    p = js_alloc_string(ctx, len, is_wide_char);+    if (!p)+        return JS_EXCEPTION;+    if (!is_wide_char) {+        memcpy(p->u.str8, p1->u.str8, p1->len);+        memcpy(p->u.str8 + p1->len, p2->u.str8, p2->len);+        p->u.str8[len] = '\0';+    } else {+        copy_str16(p->u.str16, p1, 0, p1->len);+        copy_str16(p->u.str16 + p1->len, p2, 0, p2->len);+    }+    return JS_MKPTR(JS_TAG_STRING, p);+}++/* op1 and op2 are converted to strings. For convience, op1 or op2 =+   JS_EXCEPTION are accepted and return JS_EXCEPTION.  */+static JSValue JS_ConcatString(JSContext *ctx, JSValue op1, JSValue op2)+{+    JSValue ret;+    JSString *p1, *p2;++    if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_STRING)) {+        op1 = JS_ToStringFree(ctx, op1);+        if (JS_IsException(op1)) {+            JS_FreeValue(ctx, op2);+            return JS_EXCEPTION;+        }+    }+    if (unlikely(JS_VALUE_GET_TAG(op2) != JS_TAG_STRING)) {+        op2 = JS_ToStringFree(ctx, op2);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            return JS_EXCEPTION;+        }+    }+    p1 = JS_VALUE_GET_STRING(op1);+    p2 = JS_VALUE_GET_STRING(op2);++    /* XXX: could also check if p1 is empty */+    if (p2->len == 0) {+        goto ret_op1;+    }+    if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char+    &&  js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) {+        /* Concatenate in place in available space at the end of p1 */+        if (p1->is_wide_char) {+            memcpy(p1->u.str16 + p1->len, p2->u.str16, p2->len << 1);+            p1->len += p2->len;+        } else {+            memcpy(p1->u.str8 + p1->len, p2->u.str8, p2->len);+            p1->len += p2->len;+            p1->u.str8[p1->len] = '\0';+        }+    ret_op1:+        JS_FreeValue(ctx, op2);+        return op1;+    }+    ret = JS_ConcatString1(ctx, p1, p2);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return ret;+}++/* Shape support */++static inline size_t get_shape_size(size_t hash_size, size_t prop_size)+{+    return hash_size * sizeof(uint32_t) + sizeof(JSShape) ++        prop_size * sizeof(JSShapeProperty);+}++static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size)+{+    return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size);+}++static inline uint32_t *prop_hash_end(JSShape *sh)+{+    return (uint32_t *)sh;+}++static inline void *get_alloc_from_shape(JSShape *sh)+{+    return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1);+}++static inline JSShapeProperty *get_shape_prop(JSShape *sh)+{+    return sh->prop;+}++static int init_shape_hash(JSRuntime *rt)+{+    rt->shape_hash_bits = 4;   /* 16 shapes */+    rt->shape_hash_size = 1 << rt->shape_hash_bits;+    rt->shape_hash_count = 0;+    rt->shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) *+                                   rt->shape_hash_size);+    if (!rt->shape_hash)+        return -1;+    return 0;+}++/* same magic hash multiplier as the Linux kernel */+static uint32_t shape_hash(uint32_t h, uint32_t val)+{+    return (h + val) * 0x9e370001;+}++/* truncate the shape hash to 'hash_bits' bits */+static uint32_t get_shape_hash(uint32_t h, int hash_bits)+{+    return h >> (32 - hash_bits);+}++static uint32_t shape_initial_hash(JSObject *proto)+{+    uint32_t h;+    h = shape_hash(1, (uintptr_t)proto);+    if (sizeof(proto) > 4)+        h = shape_hash(h, (uint64_t)(uintptr_t)proto >> 32);+    return h;+}++static int resize_shape_hash(JSRuntime *rt, int new_shape_hash_bits)+{+    int new_shape_hash_size, i;+    uint32_t h;+    JSShape **new_shape_hash, *sh, *sh_next;++    new_shape_hash_size = 1 << new_shape_hash_bits;+    new_shape_hash = js_mallocz_rt(rt, sizeof(rt->shape_hash[0]) *+                                   new_shape_hash_size);+    if (!new_shape_hash)+        return -1;+    for(i = 0; i < rt->shape_hash_size; i++) {+        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh_next) {+            sh_next = sh->shape_hash_next;+            h = get_shape_hash(sh->hash, new_shape_hash_bits);+            sh->shape_hash_next = new_shape_hash[h];+            new_shape_hash[h] = sh;+        }+    }+    js_free_rt(rt, rt->shape_hash);+    rt->shape_hash_bits = new_shape_hash_bits;+    rt->shape_hash_size = new_shape_hash_size;+    rt->shape_hash = new_shape_hash;+    return 0;+}++static void js_shape_hash_link(JSRuntime *rt, JSShape *sh)+{+    uint32_t h;+    h = get_shape_hash(sh->hash, rt->shape_hash_bits);+    sh->shape_hash_next = rt->shape_hash[h];+    rt->shape_hash[h] = sh;+    rt->shape_hash_count++;+}++static void js_shape_hash_unlink(JSRuntime *rt, JSShape *sh)+{+    uint32_t h;+    JSShape **psh;++    h = get_shape_hash(sh->hash, rt->shape_hash_bits);+    psh = &rt->shape_hash[h];+    while (*psh != sh)+        psh = &(*psh)->shape_hash_next;+    *psh = sh->shape_hash_next;+    rt->shape_hash_count--;+}++/* create a new empty shape with prototype 'proto' */+static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto,+                                        int hash_size, int prop_size)+{+    JSRuntime *rt = ctx->rt;+    void *sh_alloc;+    JSShape *sh;++    /* resize the shape hash table if necessary */+    if (2 * (rt->shape_hash_count + 1) > rt->shape_hash_size) {+        resize_shape_hash(rt, rt->shape_hash_bits + 1);+    }++    sh_alloc = js_malloc(ctx, get_shape_size(hash_size, prop_size));+    if (!sh_alloc)+        return NULL;+    sh = get_shape_from_alloc(sh_alloc, hash_size);+    sh->header.ref_count = 1;+    add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);+    if (proto)+        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, proto));+    sh->proto = proto;+    memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) *+           hash_size);+    sh->prop_hash_mask = hash_size - 1;+    sh->prop_size = prop_size;+    sh->prop_count = 0;+    sh->deleted_prop_count = 0;+    +    /* insert in the hash table */+    sh->hash = shape_initial_hash(proto);+    sh->is_hashed = TRUE;+    sh->has_small_array_index = FALSE;+    js_shape_hash_link(ctx->rt, sh);+    return sh;+}++static JSShape *js_new_shape(JSContext *ctx, JSObject *proto)+{+    return js_new_shape2(ctx, proto, JS_PROP_INITIAL_HASH_SIZE,+                         JS_PROP_INITIAL_SIZE);+}++/* The shape is cloned. The new shape is not inserted in the shape+   hash table */+static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1)+{+    JSShape *sh;+    void *sh_alloc, *sh_alloc1;+    size_t size;+    JSShapeProperty *pr;+    uint32_t i, hash_size;++    hash_size = sh1->prop_hash_mask + 1;+    size = get_shape_size(hash_size, sh1->prop_size);+    sh_alloc = js_malloc(ctx, size);+    if (!sh_alloc)+        return NULL;+    sh_alloc1 = get_alloc_from_shape(sh1);+    memcpy(sh_alloc, sh_alloc1, size);+    sh = get_shape_from_alloc(sh_alloc, hash_size);+    sh->header.ref_count = 1;+    add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE);+    sh->is_hashed = FALSE;+    if (sh->proto) {+        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));+    }+    for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {+        JS_DupAtom(ctx, pr->atom);+    }+    return sh;+}++static JSShape *js_dup_shape(JSShape *sh)+{+    sh->header.ref_count++;+    return sh;+}++static void js_free_shape0(JSRuntime *rt, JSShape *sh)+{+    uint32_t i;+    JSShapeProperty *pr;++    assert(sh->header.ref_count == 0);+    if (sh->is_hashed)+        js_shape_hash_unlink(rt, sh);+    if (sh->proto != NULL) {+        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, sh->proto));+    }+    pr = get_shape_prop(sh);+    for(i = 0; i < sh->prop_count; i++) {+        JS_FreeAtomRT(rt, pr->atom);+        pr++;+    }+    remove_gc_object(&sh->header);+    js_free_rt(rt, get_alloc_from_shape(sh));+}++static void js_free_shape(JSRuntime *rt, JSShape *sh)+{+    if (unlikely(--sh->header.ref_count <= 0)) {+        js_free_shape0(rt, sh);+    }+}++static void js_free_shape_null(JSRuntime *rt, JSShape *sh)+{+    if (sh)+        js_free_shape(rt, sh);+}++/* make space to hold at least 'count' properties */+static no_inline int resize_properties(JSContext *ctx, JSShape **psh,+                                       JSObject *p, uint32_t count)+{+    JSShape *sh;+    uint32_t new_size, new_hash_size, new_hash_mask, i;+    JSShapeProperty *pr;+    void *sh_alloc;+    intptr_t h;++    sh = *psh;+    new_size = max_int(count, sh->prop_size * 3 / 2);+    /* Reallocate prop array first to avoid crash or size inconsistency+       in case of memory allocation failure */+    if (p) {+        JSProperty *new_prop;+        new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);+        if (unlikely(!new_prop))+            return -1;+        p->prop = new_prop;+    }+    new_hash_size = sh->prop_hash_mask + 1;+    while (new_hash_size < new_size)+        new_hash_size = 2 * new_hash_size;+    if (new_hash_size != (sh->prop_hash_mask + 1)) {+        JSShape *old_sh;+        /* resize the hash table and the properties */+        old_sh = sh;+        sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));+        if (!sh_alloc)+            return -1;+        sh = get_shape_from_alloc(sh_alloc, new_hash_size);+        list_del(&old_sh->header.link);+        /* copy all the fields and the properties */+        memcpy(sh, old_sh,+               sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count);+        list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);+        new_hash_mask = new_hash_size - 1;+        sh->prop_hash_mask = new_hash_mask;+        memset(prop_hash_end(sh) - new_hash_size, 0,+               sizeof(prop_hash_end(sh)[0]) * new_hash_size);+        for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) {+            if (pr->atom != JS_ATOM_NULL) {+                h = ((uintptr_t)pr->atom & new_hash_mask);+                pr->hash_next = prop_hash_end(sh)[-h - 1];+                prop_hash_end(sh)[-h - 1] = i + 1;+            }+        }+        js_free(ctx, get_alloc_from_shape(old_sh));+    } else {+        /* only resize the properties */+        list_del(&sh->header.link);+        sh_alloc = js_realloc(ctx, get_alloc_from_shape(sh),+                              get_shape_size(new_hash_size, new_size));+        if (unlikely(!sh_alloc)) {+            /* insert again in the GC list */+            list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);+            return -1;+        }+        sh = get_shape_from_alloc(sh_alloc, new_hash_size);+        list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);+    }+    *psh = sh;+    sh->prop_size = new_size;+    return 0;+}++/* remove the deleted properties. */+static int compact_properties(JSContext *ctx, JSObject *p)+{+    JSShape *sh, *old_sh;+    void *sh_alloc;+    intptr_t h;+    uint32_t new_hash_size, i, j, new_hash_mask, new_size;+    JSShapeProperty *old_pr, *pr;+    JSProperty *prop, *new_prop;+    +    sh = p->shape;+    assert(!sh->is_hashed);++    new_size = max_int(JS_PROP_INITIAL_SIZE,+                       sh->prop_count - sh->deleted_prop_count);+    assert(new_size <= sh->prop_size);++    new_hash_size = sh->prop_hash_mask + 1;+    while ((new_hash_size / 2) >= new_size)+        new_hash_size = new_hash_size / 2;+    new_hash_mask = new_hash_size - 1;++    /* resize the hash table and the properties */+    old_sh = sh;+    sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size));+    if (!sh_alloc)+        return -1;+    sh = get_shape_from_alloc(sh_alloc, new_hash_size);+    list_del(&old_sh->header.link);+    memcpy(sh, old_sh, sizeof(JSShape));+    list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list);+    +    memset(prop_hash_end(sh) - new_hash_size, 0,+           sizeof(prop_hash_end(sh)[0]) * new_hash_size);++    j = 0;+    old_pr = old_sh->prop;+    pr = sh->prop;+    prop = p->prop;+    for(i = 0; i < sh->prop_count; i++) {+        if (old_pr->atom != JS_ATOM_NULL) {+            pr->atom = old_pr->atom;+            pr->flags = old_pr->flags;+            h = ((uintptr_t)old_pr->atom & new_hash_mask);+            pr->hash_next = prop_hash_end(sh)[-h - 1];+            prop_hash_end(sh)[-h - 1] = j + 1;+            prop[j] = prop[i];+            j++;+            pr++;+        }+        old_pr++;+    }+    assert(j == (sh->prop_count - sh->deleted_prop_count));+    sh->prop_hash_mask = new_hash_mask;+    sh->prop_size = new_size;+    sh->deleted_prop_count = 0;+    sh->prop_count = j;++    p->shape = sh;+    js_free(ctx, get_alloc_from_shape(old_sh));+    +    /* reduce the size of the object properties */+    new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size);+    if (new_prop)+        p->prop = new_prop;+    return 0;+}++static int add_shape_property(JSContext *ctx, JSShape **psh,+                              JSObject *p, JSAtom atom, int prop_flags)+{+    JSRuntime *rt = ctx->rt;+    JSShape *sh = *psh;+    JSShapeProperty *pr, *prop;+    uint32_t hash_mask, new_shape_hash = 0;+    intptr_t h;++    /* update the shape hash */+    if (sh->is_hashed) {+        js_shape_hash_unlink(rt, sh);+        new_shape_hash = shape_hash(shape_hash(sh->hash, atom), prop_flags);+    }++    if (unlikely(sh->prop_count >= sh->prop_size)) {+        if (resize_properties(ctx, psh, p, sh->prop_count + 1)) {+            /* in case of error, reinsert in the hash table.+               sh is still valid if resize_properties() failed */+            if (sh->is_hashed)+                js_shape_hash_link(rt, sh);+            return -1;+        }+        sh = *psh;+    }+    if (sh->is_hashed) {+        sh->hash = new_shape_hash;+        js_shape_hash_link(rt, sh);+    }+    /* Initialize the new shape property.+       The object property at p->prop[sh->prop_count] is uninitialized */+    prop = get_shape_prop(sh);+    pr = &prop[sh->prop_count++];+    pr->atom = JS_DupAtom(ctx, atom);+    pr->flags = prop_flags;+    sh->has_small_array_index |= __JS_AtomIsTaggedInt(atom);+    /* add in hash table */+    hash_mask = sh->prop_hash_mask;+    h = atom & hash_mask;+    pr->hash_next = prop_hash_end(sh)[-h - 1];+    prop_hash_end(sh)[-h - 1] = sh->prop_count;+    return 0;+}++/* find a hashed empty shape matching the prototype. Return NULL if+   not found */+static JSShape *find_hashed_shape_proto(JSRuntime *rt, JSObject *proto)+{+    JSShape *sh1;+    uint32_t h, h1;++    h = shape_initial_hash(proto);+    h1 = get_shape_hash(h, rt->shape_hash_bits);+    for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) {+        if (sh1->hash == h &&+            sh1->proto == proto &&+            sh1->prop_count == 0) {+            return sh1;+        }+    }+    return NULL;+}++/* find a hashed shape matching sh + (prop, prop_flags). Return NULL if+   not found */+static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh,+                                       JSAtom atom, int prop_flags)+{+    JSShape *sh1;+    uint32_t h, h1, i, n;++    h = sh->hash;+    h = shape_hash(h, atom);+    h = shape_hash(h, prop_flags);+    h1 = get_shape_hash(h, rt->shape_hash_bits);+    for(sh1 = rt->shape_hash[h1]; sh1 != NULL; sh1 = sh1->shape_hash_next) {+        /* we test the hash first so that the rest is done only if the+           shapes really match */+        if (sh1->hash == h &&+            sh1->proto == sh->proto &&+            sh1->prop_count == ((n = sh->prop_count) + 1)) {+            for(i = 0; i < n; i++) {+                if (unlikely(sh1->prop[i].atom != sh->prop[i].atom) ||+                    unlikely(sh1->prop[i].flags != sh->prop[i].flags))+                    goto next;+            }+            if (unlikely(sh1->prop[n].atom != atom) ||+                unlikely(sh1->prop[n].flags != prop_flags))+                goto next;+            return sh1;+        }+    next: ;+    }+    return NULL;+}++static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)+{+    char atom_buf[ATOM_GET_STR_BUF_SIZE];+    int j;++    /* XXX: should output readable class prototype */+    printf("%5d %3d%c %14p %5d %5d", i,+           sh->header.ref_count, " *"[sh->is_hashed],+           (void *)sh->proto, sh->prop_size, sh->prop_count);+    for(j = 0; j < sh->prop_count; j++) {+        printf(" %s", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf),+                                      sh->prop[j].atom));+    }+    printf("\n");+}++static __maybe_unused void JS_DumpShapes(JSRuntime *rt)+{+    int i;+    JSShape *sh;+    struct list_head *el;+    JSObject *p;+    JSGCObjectHeader *gp;+    +    printf("JSShapes: {\n");+    printf("%5s %4s %14s %5s %5s %s\n", "SLOT", "REFS", "PROTO", "SIZE", "COUNT", "PROPS");+    for(i = 0; i < rt->shape_hash_size; i++) {+        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) {+            JS_DumpShape(rt, i, sh);+            assert(sh->is_hashed);+        }+    }+    /* dump non-hashed shapes */+    list_for_each(el, &rt->gc_obj_list) {+        gp = list_entry(el, JSGCObjectHeader, link);+        if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {+            p = (JSObject *)gp;+            if (!p->shape->is_hashed) {+                JS_DumpShape(rt, -1, p->shape);+            }+        }+    }+    printf("}\n");+}++static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID class_id)+{+    JSObject *p;++    js_trigger_gc(ctx->rt, sizeof(JSObject));+    p = js_malloc(ctx, sizeof(JSObject));+    if (unlikely(!p))+        goto fail;+    p->class_id = class_id;+    p->extensible = TRUE;+    p->free_mark = 0;+    p->is_exotic = 0;+    p->fast_array = 0;+    p->is_constructor = 0;+    p->is_uncatchable_error = 0;+    p->tmp_mark = 0;+    p->is_HTMLDDA = 0;+    p->first_weak_ref = NULL;+    p->u.opaque = NULL;+    p->shape = sh;+    p->prop = js_malloc(ctx, sizeof(JSProperty) * sh->prop_size);+    if (unlikely(!p->prop)) {+        js_free(ctx, p);+    fail:+        js_free_shape(ctx->rt, sh);+        return JS_EXCEPTION;+    }++    switch(class_id) {+    case JS_CLASS_OBJECT:+        break;+    case JS_CLASS_ARRAY:+        {+            JSProperty *pr;+            p->is_exotic = 1;+            p->fast_array = 1;+            p->u.array.u.values = NULL;+            p->u.array.count = 0;+            p->u.array.u1.size = 0;+            /* the length property is always the first one */+            if (likely(sh == ctx->array_shape)) {+                pr = &p->prop[0];+            } else {+                /* only used for the first array */+                /* cannot fail */+                pr = add_property(ctx, p, JS_ATOM_length,+                                  JS_PROP_WRITABLE | JS_PROP_LENGTH);+            }+            pr->u.value = JS_NewInt32(ctx, 0);+        }+        break;+    case JS_CLASS_C_FUNCTION:+        p->prop[0].u.value = JS_UNDEFINED;+        break;+    case JS_CLASS_ARGUMENTS:+    case JS_CLASS_UINT8C_ARRAY:+    case JS_CLASS_INT8_ARRAY:+    case JS_CLASS_UINT8_ARRAY:+    case JS_CLASS_INT16_ARRAY:+    case JS_CLASS_UINT16_ARRAY:+    case JS_CLASS_INT32_ARRAY:+    case JS_CLASS_UINT32_ARRAY:+#ifdef CONFIG_BIGNUM+    case JS_CLASS_BIG_INT64_ARRAY:+    case JS_CLASS_BIG_UINT64_ARRAY:+#endif+    case JS_CLASS_FLOAT32_ARRAY:+    case JS_CLASS_FLOAT64_ARRAY:+        p->is_exotic = 1;+        p->fast_array = 1;+        p->u.array.u.ptr = NULL;+        p->u.array.count = 0;+        break;+    case JS_CLASS_DATAVIEW:+        p->u.array.u.ptr = NULL;+        p->u.array.count = 0;+        break;+    case JS_CLASS_NUMBER:+    case JS_CLASS_STRING:+    case JS_CLASS_BOOLEAN:+    case JS_CLASS_SYMBOL:+    case JS_CLASS_DATE:+#ifdef CONFIG_BIGNUM+    case JS_CLASS_BIG_INT:+    case JS_CLASS_BIG_FLOAT:+    case JS_CLASS_BIG_DECIMAL:+#endif+        p->u.object_data = JS_UNDEFINED;+        goto set_exotic;+    case JS_CLASS_REGEXP:+        p->u.regexp.pattern = NULL;+        p->u.regexp.bytecode = NULL;+        goto set_exotic;+    default:+    set_exotic:+        if (ctx->rt->class_array[class_id].exotic) {+            p->is_exotic = 1;+        }+        break;+    }+    p->header.ref_count = 1;+    add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT);+    return JS_MKPTR(JS_TAG_OBJECT, p);+}++static JSObject *get_proto_obj(JSValueConst proto_val)+{+    if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT)+        return NULL;+    else+        return JS_VALUE_GET_OBJ(proto_val);+}++/* WARNING: proto must be an object or JS_NULL */+JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto_val,+                               JSClassID class_id)+{+    JSShape *sh;+    JSObject *proto;++    proto = get_proto_obj(proto_val);+    sh = find_hashed_shape_proto(ctx->rt, proto);+    if (likely(sh)) {+        sh = js_dup_shape(sh);+    } else {+        sh = js_new_shape(ctx, proto);+        if (!sh)+            return JS_EXCEPTION;+    }+    return JS_NewObjectFromShape(ctx, sh, class_id);+}++#if 0+static JSValue JS_GetObjectData(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;++    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(obj);+        switch(p->class_id) {+        case JS_CLASS_NUMBER:+        case JS_CLASS_STRING:+        case JS_CLASS_BOOLEAN:+        case JS_CLASS_SYMBOL:+        case JS_CLASS_DATE:+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT:+        case JS_CLASS_BIG_FLOAT:+        case JS_CLASS_BIG_DECIMAL:+#endif+            return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_UNDEFINED;+}+#endif++static int JS_SetObjectData(JSContext *ctx, JSValueConst obj, JSValue val)+{+    JSObject *p;++    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(obj);+        switch(p->class_id) {+        case JS_CLASS_NUMBER:+        case JS_CLASS_STRING:+        case JS_CLASS_BOOLEAN:+        case JS_CLASS_SYMBOL:+        case JS_CLASS_DATE:+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT:+        case JS_CLASS_BIG_FLOAT:+        case JS_CLASS_BIG_DECIMAL:+#endif+            JS_FreeValue(ctx, p->u.object_data);+            p->u.object_data = val;+            return 0;+        }+    }+    JS_FreeValue(ctx, val);+    if (!JS_IsException(obj))+        JS_ThrowTypeError(ctx, "invalid object type");+    return -1;+}++JSValue JS_NewObjectClass(JSContext *ctx, int class_id)+{+    return JS_NewObjectProtoClass(ctx, ctx->class_proto[class_id], class_id);+}++JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto)+{+    return JS_NewObjectProtoClass(ctx, proto, JS_CLASS_OBJECT);+}++JSValue JS_NewArray(JSContext *ctx)+{+    return JS_NewObjectFromShape(ctx, js_dup_shape(ctx->array_shape),+                                 JS_CLASS_ARRAY);+}++JSValue JS_NewObject(JSContext *ctx)+{+    /* inline JS_NewObjectClass(ctx, JS_CLASS_OBJECT); */+    return JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT], JS_CLASS_OBJECT);+}++static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj,+                                       JSAtom name, int len)+{+    /* ES6 feature non compatible with ES5.1: length is configurable */+    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length, JS_NewInt32(ctx, len),+                           JS_PROP_CONFIGURABLE);+    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name,+                           JS_AtomToString(ctx, name), JS_PROP_CONFIGURABLE);+}++static BOOL js_class_has_bytecode(JSClassID class_id)+{+    return (class_id == JS_CLASS_BYTECODE_FUNCTION ||+            class_id == JS_CLASS_GENERATOR_FUNCTION ||+            class_id == JS_CLASS_ASYNC_FUNCTION ||+            class_id == JS_CLASS_ASYNC_GENERATOR_FUNCTION);+}++/* return NULL without exception if not a function or no bytecode */+static JSFunctionBytecode *JS_GetFunctionBytecode(JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return NULL;+    p = JS_VALUE_GET_OBJ(val);+    if (!js_class_has_bytecode(p->class_id))+        return NULL;+    return p->u.func.function_bytecode;+}++static void js_method_set_home_object(JSContext *ctx, JSValueConst func_obj,+                                      JSValueConst home_obj)+{+    JSObject *p, *p1;+    JSFunctionBytecode *b;++    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)+        return;+    p = JS_VALUE_GET_OBJ(func_obj);+    if (!js_class_has_bytecode(p->class_id))+        return;+    b = p->u.func.function_bytecode;+    if (b->need_home_object) {+        p1 = p->u.func.home_object;+        if (p1) {+            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));+        }+        if (JS_VALUE_GET_TAG(home_obj) == JS_TAG_OBJECT)+            p1 = JS_VALUE_GET_OBJ(JS_DupValue(ctx, home_obj));+        else+            p1 = NULL;+        p->u.func.home_object = p1;+    }+}++static JSValue js_get_function_name(JSContext *ctx, JSAtom name)+{+    JSValue name_str;++    name_str = JS_AtomToString(ctx, name);+    if (JS_AtomSymbolHasDescription(ctx, name)) {+        name_str = JS_ConcatString3(ctx, "[", name_str, "]");+    }+    return name_str;+}++/* Modify the name of a method according to the atom and+   'flags'. 'flags' is a bitmask of JS_PROP_HAS_GET and+   JS_PROP_HAS_SET. Also set the home object of the method.+   Return < 0 if exception. */+static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj,+                                    JSAtom name, int flags, JSValueConst home_obj)+{+    JSValue name_str;++    name_str = js_get_function_name(ctx, name);+    if (flags & JS_PROP_HAS_GET) {+        name_str = JS_ConcatString3(ctx, "get ", name_str, "");+    } else if (flags & JS_PROP_HAS_SET) {+        name_str = JS_ConcatString3(ctx, "set ", name_str, "");+    }+    if (JS_IsException(name_str))+        return -1;+    if (JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name_str,+                               JS_PROP_CONFIGURABLE) < 0)+        return -1;+    js_method_set_home_object(ctx, func_obj, home_obj);+    return 0;+}++/* Note: at least 'length' arguments will be readable in 'argv' */+static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,+                                const char *name,+                                int length, JSCFunctionEnum cproto, int magic,+                                JSValueConst proto_val)+{+    JSValue func_obj;+    JSObject *p;+    JSAtom name_atom;+    +    func_obj = JS_NewObjectProtoClass(ctx, proto_val, JS_CLASS_C_FUNCTION);+    if (JS_IsException(func_obj))+        return func_obj;+    p = JS_VALUE_GET_OBJ(func_obj);+    p->u.cfunc.realm = JS_DupContext(ctx);+    p->u.cfunc.c_function.generic = func;+    p->u.cfunc.length = length;+    p->u.cfunc.cproto = cproto;+    p->u.cfunc.magic = magic;+    p->is_constructor = (cproto == JS_CFUNC_constructor ||+                         cproto == JS_CFUNC_constructor_magic ||+                         cproto == JS_CFUNC_constructor_or_func ||+                         cproto == JS_CFUNC_constructor_or_func_magic);+    if (!name)+        name = "";+    name_atom = JS_NewAtom(ctx, name);+    js_function_set_properties(ctx, func_obj, name_atom, length);+    JS_FreeAtom(ctx, name_atom);+    return func_obj;+}++/* Note: at least 'length' arguments will be readable in 'argv' */+JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,+                         const char *name,+                         int length, JSCFunctionEnum cproto, int magic)+{+    return JS_NewCFunction3(ctx, func, name, length, cproto, magic,+                            ctx->function_proto);+}++typedef struct JSCFunctionDataRecord {+    JSCFunctionData *func;+    uint8_t length;+    uint8_t data_len;+    uint16_t magic;+    JSValue data[0];+} JSCFunctionDataRecord;++static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val)+{+    JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA);+    int i;++    if (s) {+        for(i = 0; i < s->data_len; i++) {+            JS_FreeValueRT(rt, s->data[i]);+        }+        js_free_rt(rt, s);+    }+}++static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val,+                                    JS_MarkFunc *mark_func)+{+    JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA);+    int i;++    if (s) {+        for(i = 0; i < s->data_len; i++) {+            JS_MarkValue(rt, s->data[i], mark_func);+        }+    }+}++static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj,+                                       JSValueConst this_val,+                                       int argc, JSValueConst *argv, int flags)+{+    JSCFunctionDataRecord *s = JS_GetOpaque(func_obj, JS_CLASS_C_FUNCTION_DATA);+    JSValueConst *arg_buf;+    int i;++    /* XXX: could add the function on the stack for debug */+    if (unlikely(argc < s->length)) {+        arg_buf = alloca(sizeof(arg_buf[0]) * s->length);+        for(i = 0; i < argc; i++)+            arg_buf[i] = argv[i];+        for(i = argc; i < s->length; i++)+            arg_buf[i] = JS_UNDEFINED;+    } else {+        arg_buf = argv;+    }++    return s->func(ctx, this_val, argc, arg_buf, s->magic, s->data);+}++JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,+                            int length, int magic, int data_len,+                            JSValueConst *data)+{+    JSCFunctionDataRecord *s;+    JSValue func_obj;+    int i;++    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,+                                      JS_CLASS_C_FUNCTION_DATA);+    if (JS_IsException(func_obj))+        return func_obj;+    s = js_malloc(ctx, sizeof(*s) + data_len * sizeof(JSValue));+    if (!s) {+        JS_FreeValue(ctx, func_obj);+        return JS_EXCEPTION;+    }+    s->func = func;+    s->length = length;+    s->data_len = data_len;+    s->magic = magic;+    for(i = 0; i < data_len; i++)+        s->data[i] = JS_DupValue(ctx, data[i]);+    JS_SetOpaque(func_obj, s);+    js_function_set_properties(ctx, func_obj,+                               JS_ATOM_empty_string, length);+    return func_obj;+}++static JSContext *js_autoinit_get_realm(JSProperty *pr)+{+    return (JSContext *)(pr->u.init.realm_and_id & ~3);+}++static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr)+{+    return pr->u.init.realm_and_id & 3;+}++static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)+{+    JS_FreeContext(js_autoinit_get_realm(pr));+}++static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,+                             JS_MarkFunc *mark_func)+{+    mark_func(rt, &js_autoinit_get_realm(pr)->header);+}++static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)+{+    if (unlikely(prop_flags & JS_PROP_TMASK)) {+        if ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+            if (pr->u.getset.getter)+                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));+            if (pr->u.getset.setter)+                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));+        } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+            free_var_ref(rt, pr->u.var_ref);+        } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+            js_autoinit_free(rt, pr);+        }+    } else {+        JS_FreeValueRT(rt, pr->u.value);+    }+}++static force_inline JSShapeProperty *find_own_property1(JSObject *p,+                                                        JSAtom atom)+{+    JSShape *sh;+    JSShapeProperty *pr, *prop;+    intptr_t h;+    sh = p->shape;+    h = (uintptr_t)atom & sh->prop_hash_mask;+    h = prop_hash_end(sh)[-h - 1];+    prop = get_shape_prop(sh);+    while (h) {+        pr = &prop[h - 1];+        if (likely(pr->atom == atom)) {+            return pr;+        }+        h = pr->hash_next;+    }+    return NULL;+}++static force_inline JSShapeProperty *find_own_property(JSProperty **ppr,+                                                       JSObject *p,+                                                       JSAtom atom)+{+    JSShape *sh;+    JSShapeProperty *pr, *prop;+    intptr_t h;+    sh = p->shape;+    h = (uintptr_t)atom & sh->prop_hash_mask;+    h = prop_hash_end(sh)[-h - 1];+    prop = get_shape_prop(sh);+    while (h) {+        pr = &prop[h - 1];+        if (likely(pr->atom == atom)) {+            *ppr = &p->prop[h - 1];+            /* the compiler should be able to assume that pr != NULL here */+            return pr;+        }+        h = pr->hash_next;+    }+    *ppr = NULL;+    return NULL;+}++/* indicate that the object may be part of a function prototype cycle */+static void set_cycle_flag(JSContext *ctx, JSValueConst obj)+{+}++static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref)+{+    if (var_ref) {+        assert(var_ref->header.ref_count > 0);+        if (--var_ref->header.ref_count == 0) {+            if (var_ref->is_detached) {+                JS_FreeValueRT(rt, var_ref->value);+                remove_gc_object(&var_ref->header);+            } else {+                list_del(&var_ref->header.link); /* still on the stack */+            }+            js_free_rt(rt, var_ref);+        }+    }+}++static void js_array_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    int i;++    for(i = 0; i < p->u.array.count; i++) {+        JS_FreeValueRT(rt, p->u.array.u.values[i]);+    }+    js_free_rt(rt, p->u.array.u.values);+}++static void js_array_mark(JSRuntime *rt, JSValueConst val,+                          JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    int i;++    for(i = 0; i < p->u.array.count; i++) {+        JS_MarkValue(rt, p->u.array.u.values[i], mark_func);+    }+}++static void js_object_data_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JS_FreeValueRT(rt, p->u.object_data);+    p->u.object_data = JS_UNDEFINED;+}++static void js_object_data_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JS_MarkValue(rt, p->u.object_data, mark_func);+}++static void js_c_function_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);++    if (p->u.cfunc.realm)+        JS_FreeContext(p->u.cfunc.realm);+}++static void js_c_function_mark(JSRuntime *rt, JSValueConst val,+                               JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);++    if (p->u.cfunc.realm)+        mark_func(rt, &p->u.cfunc.realm->header);+}++static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p1, *p = JS_VALUE_GET_OBJ(val);+    JSFunctionBytecode *b;+    JSVarRef **var_refs;+    int i;++    p1 = p->u.func.home_object;+    if (p1) {+        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, p1));+    }+    b = p->u.func.function_bytecode;+    if (b) {+        var_refs = p->u.func.var_refs;+        if (var_refs) {+            for(i = 0; i < b->closure_var_count; i++)+                free_var_ref(rt, var_refs[i]);+            js_free_rt(rt, var_refs);+        }+        JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b));+    }+}++static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,+                                      JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSVarRef **var_refs = p->u.func.var_refs;+    JSFunctionBytecode *b = p->u.func.function_bytecode;+    int i;++    if (p->u.func.home_object) {+        JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object),+                     mark_func);+    }+    if (b) {+        if (var_refs) {+            for(i = 0; i < b->closure_var_count; i++) {+                JSVarRef *var_ref = var_refs[i];+                if (var_ref && var_ref->is_detached) {+                    mark_func(rt, &var_ref->header);+                }+            }+        }+        /* must mark the function bytecode because template objects may be+           part of a cycle */+        JS_MarkValue(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), mark_func);+    }+}++static void js_bound_function_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSBoundFunction *bf = p->u.bound_function;+    int i;++    JS_FreeValueRT(rt, bf->func_obj);+    JS_FreeValueRT(rt, bf->this_val);+    for(i = 0; i < bf->argc; i++) {+        JS_FreeValueRT(rt, bf->argv[i]);+    }+    js_free_rt(rt, bf);+}++static void js_bound_function_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSBoundFunction *bf = p->u.bound_function;+    int i;++    JS_MarkValue(rt, bf->func_obj, mark_func);+    JS_MarkValue(rt, bf->this_val, mark_func);+    for(i = 0; i < bf->argc; i++)+        JS_MarkValue(rt, bf->argv[i], mark_func);+}++static void js_for_in_iterator_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSForInIterator *it = p->u.for_in_iterator;+    JS_FreeValueRT(rt, it->obj);+    js_free_rt(rt, it);+}++static void js_for_in_iterator_mark(JSRuntime *rt, JSValueConst val,+                                JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSForInIterator *it = p->u.for_in_iterator;+    JS_MarkValue(rt, it->obj, mark_func);+}++static void free_object(JSRuntime *rt, JSObject *p)+{+    int i;+    JSClassFinalizer *finalizer;+    JSShape *sh;+    JSShapeProperty *pr;++    p->free_mark = 1; /* used to tell the object is invalid when+                         freeing cycles */+    /* free all the fields */+    sh = p->shape;+    pr = get_shape_prop(sh);+    for(i = 0; i < sh->prop_count; i++) {+        free_property(rt, &p->prop[i], pr->flags);+        pr++;+    }+    js_free_rt(rt, p->prop);+    /* as an optimization we destroy the shape immediately without+       putting it in gc_zero_ref_count_list */+    js_free_shape(rt, sh);++    /* fail safe */+    p->shape = NULL;+    p->prop = NULL;++    if (unlikely(p->first_weak_ref)) {+        reset_weak_ref(rt, p);+    }++    finalizer = rt->class_array[p->class_id].finalizer;+    if (finalizer)+        (*finalizer)(rt, JS_MKPTR(JS_TAG_OBJECT, p));++    /* fail safe */+    p->class_id = 0;+    p->u.opaque = NULL;+    p->u.func.var_refs = NULL;+    p->u.func.home_object = NULL;++    remove_gc_object(&p->header);+    if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && p->header.ref_count != 0) {+        list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list);+    } else {+        js_free_rt(rt, p);+    }+}++static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)+{+    switch(gp->gc_obj_type) {+    case JS_GC_OBJ_TYPE_JS_OBJECT:+        free_object(rt, (JSObject *)gp);+        break;+    case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:+        free_function_bytecode(rt, (JSFunctionBytecode *)gp);+        break;+    default:+        abort();+    }+}++static void free_zero_refcount(JSRuntime *rt)+{+    struct list_head *el;+    JSGCObjectHeader *p;+    +    rt->gc_phase = JS_GC_PHASE_DECREF;+    for(;;) {+        el = rt->gc_zero_ref_count_list.next;+        if (el == &rt->gc_zero_ref_count_list)+            break;+        p = list_entry(el, JSGCObjectHeader, link);+        assert(p->ref_count == 0);+        free_gc_object(rt, p);+    }+    rt->gc_phase = JS_GC_PHASE_NONE;+}++/* called with the ref_count of 'v' reaches zero. */+void __JS_FreeValueRT(JSRuntime *rt, JSValue v)+{+    uint32_t tag = JS_VALUE_GET_TAG(v);++#ifdef DUMP_FREE+    {+        printf("Freeing ");+        if (tag == JS_TAG_OBJECT) {+            JS_DumpObject(rt, JS_VALUE_GET_OBJ(v));+        } else {+            JS_DumpValueShort(rt, v);+            printf("\n");+        }+    }+#endif++    switch(tag) {+    case JS_TAG_STRING:+        {+            JSString *p = JS_VALUE_GET_STRING(v);+            if (p->atom_type) {+                JS_FreeAtomStruct(rt, p);+            } else {+#ifdef DUMP_LEAKS+                list_del(&p->link);+#endif+                js_free_rt(rt, p);+            }+        }+        break;+    case JS_TAG_OBJECT:+    case JS_TAG_FUNCTION_BYTECODE:+        {+            JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);+            if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {+                list_del(&p->link);+                list_add(&p->link, &rt->gc_zero_ref_count_list);+                if (rt->gc_phase == JS_GC_PHASE_NONE) {+                    free_zero_refcount(rt);+                }+            }+        }+        break;+    case JS_TAG_MODULE:+        abort(); /* never freed here */+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *bf = JS_VALUE_GET_PTR(v);+            bf_delete(&bf->num);+            js_free_rt(rt, bf);+        }+        break;+    case JS_TAG_BIG_DECIMAL:+        {+            JSBigDecimal *bf = JS_VALUE_GET_PTR(v);+            bfdec_delete(&bf->num);+            js_free_rt(rt, bf);+        }+        break;+#endif+    case JS_TAG_SYMBOL:+        {+            JSAtomStruct *p = JS_VALUE_GET_PTR(v);+            JS_FreeAtomStruct(rt, p);+        }+        break;+    default:+        printf("__JS_FreeValue: unknown tag=%d\n", tag);+        abort();+    }+}++void __JS_FreeValue(JSContext *ctx, JSValue v)+{+    __JS_FreeValueRT(ctx->rt, v);+}++/* garbage collection */++static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,+                          JSGCObjectTypeEnum type)+{+    h->mark = 0;+    h->gc_obj_type = type;+    list_add_tail(&h->link, &rt->gc_obj_list);+}++static void remove_gc_object(JSGCObjectHeader *h)+{+    list_del(&h->link);+}++void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)+{+    if (JS_VALUE_HAS_REF_COUNT(val)) {+        switch(JS_VALUE_GET_TAG(val)) {+        case JS_TAG_OBJECT:+        case JS_TAG_FUNCTION_BYTECODE:+            mark_func(rt, JS_VALUE_GET_PTR(val));+            break;+        default:+            break;+        }+    }+}++static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,+                          JS_MarkFunc *mark_func)+{+    switch(gp->gc_obj_type) {+    case JS_GC_OBJ_TYPE_JS_OBJECT:+        {+            JSObject *p = (JSObject *)gp;+            JSShapeProperty *prs;+            JSShape *sh;+            int i;+            sh = p->shape;+            mark_func(rt, &sh->header);+            /* mark all the fields */+            prs = get_shape_prop(sh);+            for(i = 0; i < sh->prop_count; i++) {+                JSProperty *pr = &p->prop[i];+                if (prs->atom != JS_ATOM_NULL) {+                    if (prs->flags & JS_PROP_TMASK) {+                        if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                            if (pr->u.getset.getter)+                                mark_func(rt, &pr->u.getset.getter->header);+                            if (pr->u.getset.setter)+                                mark_func(rt, &pr->u.getset.setter->header);+                        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                            if (pr->u.var_ref->is_detached) {+                                /* Note: the tag does not matter+                                   provided it is a GC object */+                                mark_func(rt, &pr->u.var_ref->header);+                            }+                        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                            js_autoinit_mark(rt, pr, mark_func);+                        }+                    } else {+                        JS_MarkValue(rt, pr->u.value, mark_func);+                    }+                }+                prs++;+            }++            if (p->class_id != JS_CLASS_OBJECT) {+                JSClassGCMark *gc_mark;+                gc_mark = rt->class_array[p->class_id].gc_mark;+                if (gc_mark)+                    gc_mark(rt, JS_MKPTR(JS_TAG_OBJECT, p), mark_func);+            }+        }+        break;+    case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:+        /* the template objects can be part of a cycle */+        {+            JSFunctionBytecode *b = (JSFunctionBytecode *)gp;+            int i;+            for(i = 0; i < b->cpool_count; i++) {+                JS_MarkValue(rt, b->cpool[i], mark_func);+            }+            if (b->realm)+                mark_func(rt, &b->realm->header);+        }+        break;+    case JS_GC_OBJ_TYPE_VAR_REF:+        {+            JSVarRef *var_ref = (JSVarRef *)gp;+            /* only detached variable referenced are taken into account */+            assert(var_ref->is_detached);+            JS_MarkValue(rt, *var_ref->pvalue, mark_func);+        }+        break;+    case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:+        {+            JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp;+            if (s->is_active)+                async_func_mark(rt, &s->func_state, mark_func);+            JS_MarkValue(rt, s->resolving_funcs[0], mark_func);+            JS_MarkValue(rt, s->resolving_funcs[1], mark_func);+        }+        break;+    case JS_GC_OBJ_TYPE_SHAPE:+        {+            JSShape *sh = (JSShape *)gp;+            if (sh->proto != NULL) {+                mark_func(rt, &sh->proto->header);+            }+        }+        break;+    case JS_GC_OBJ_TYPE_JS_CONTEXT:+        {+            JSContext *ctx = (JSContext *)gp;+            JS_MarkContext(rt, ctx, mark_func);+        }+        break;+    default:+        abort();+    }+}++static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p)+{+    assert(p->ref_count > 0);+    p->ref_count--;+    if (p->ref_count == 0 && p->mark == 1) {+        list_del(&p->link);+        list_add_tail(&p->link, &rt->tmp_obj_list);+    }+}++static void gc_decref(JSRuntime *rt)+{+    struct list_head *el, *el1;+    JSGCObjectHeader *p;+    +    init_list_head(&rt->tmp_obj_list);++    /* decrement the refcount of all the children of all the GC+       objects and move the GC objects with zero refcount to+       tmp_obj_list */+    list_for_each_safe(el, el1, &rt->gc_obj_list) {+        p = list_entry(el, JSGCObjectHeader, link);+        assert(p->mark == 0);+        mark_children(rt, p, gc_decref_child);+        p->mark = 1;+        if (p->ref_count == 0) {+            list_del(&p->link);+            list_add_tail(&p->link, &rt->tmp_obj_list);+        }+    }+}++static void gc_scan_incref_child(JSRuntime *rt, JSGCObjectHeader *p)+{+    p->ref_count++;+    if (p->ref_count == 1) {+        /* ref_count was 0: remove from tmp_obj_list and add at the+           end of gc_obj_list */+        list_del(&p->link);+        list_add_tail(&p->link, &rt->gc_obj_list);+        p->mark = 0; /* reset the mark for the next GC call */+    }+}++static void gc_scan_incref_child2(JSRuntime *rt, JSGCObjectHeader *p)+{+    p->ref_count++;+}++static void gc_scan(JSRuntime *rt)+{+    struct list_head *el;+    JSGCObjectHeader *p;++    /* keep the objects with a refcount > 0 and their children. */+    list_for_each(el, &rt->gc_obj_list) {+        p = list_entry(el, JSGCObjectHeader, link);+        assert(p->ref_count > 0);+        p->mark = 0; /* reset the mark for the next GC call */+        mark_children(rt, p, gc_scan_incref_child);+    }+    +    /* restore the refcount of the objects to be deleted. */+    list_for_each(el, &rt->tmp_obj_list) {+        p = list_entry(el, JSGCObjectHeader, link);+        mark_children(rt, p, gc_scan_incref_child2);+    }+}++static void gc_free_cycles(JSRuntime *rt)+{+    struct list_head *el, *el1;+    JSGCObjectHeader *p;+#ifdef DUMP_GC_FREE+    BOOL header_done = FALSE;+#endif++    rt->gc_phase = JS_GC_PHASE_REMOVE_CYCLES;++    for(;;) {+        el = rt->tmp_obj_list.next;+        if (el == &rt->tmp_obj_list)+            break;+        p = list_entry(el, JSGCObjectHeader, link);+        /* Only need to free the GC object associated with JS+           values. The rest will be automatically removed because they+           must be referenced by them. */+        switch(p->gc_obj_type) {+        case JS_GC_OBJ_TYPE_JS_OBJECT:+        case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:+#ifdef DUMP_GC_FREE+            if (!header_done) {+                printf("Freeing cycles:\n");+                JS_DumpObjectHeader(rt);+                header_done = TRUE;+            }+            JS_DumpGCObject(rt, p);+#endif+            free_gc_object(rt, p);+            break;+        default:+            list_del(&p->link);+            list_add_tail(&p->link, &rt->gc_zero_ref_count_list);+            break;+        }+    }+    rt->gc_phase = JS_GC_PHASE_NONE;+           +    list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) {+        p = list_entry(el, JSGCObjectHeader, link);+        assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||+               p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);+        js_free_rt(rt, p);+    }++    init_list_head(&rt->gc_zero_ref_count_list);+}++void JS_RunGC(JSRuntime *rt)+{+    /* decrement the reference of the children of each object. mark =+       1 after this pass. */+    gc_decref(rt);++    /* keep the GC objects with a non zero refcount and their childs */+    gc_scan(rt);++    /* free the GC objects in a cycle */+    gc_free_cycles(rt);+}++/* Return false if not an object or if the object has already been+   freed (zombie objects are visible in finalizers when freeing+   cycles). */+BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj)+{+    JSObject *p;+    if (!JS_IsObject(obj))+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    return !p->free_mark;+}++/* Compute memory used by various object types */+/* XXX: poor man's approach to handling multiply referenced objects */+typedef struct JSMemoryUsage_helper {+    double memory_used_count;+    double str_count;+    double str_size;+    int64_t js_func_count;+    double js_func_size;+    int64_t js_func_code_size;+    int64_t js_func_pc2line_count;+    int64_t js_func_pc2line_size;+} JSMemoryUsage_helper;++static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp);++static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp)+{+    if (!str->atom_type) {  /* atoms are handled separately */+        double s_ref_count = str->header.ref_count;+        hp->str_count += 1 / s_ref_count;+        hp->str_size += ((sizeof(*str) + (str->len << str->is_wide_char) ++                          1 - str->is_wide_char) / s_ref_count);+    }+}++static void compute_bytecode_size(JSFunctionBytecode *b, JSMemoryUsage_helper *hp)+{+    int memory_used_count, js_func_size, i;++    memory_used_count = 0;+    js_func_size = offsetof(JSFunctionBytecode, debug);+    if (b->vardefs) {+        js_func_size += (b->arg_count + b->var_count) * sizeof(*b->vardefs);+    }+    if (b->cpool) {+        js_func_size += b->cpool_count * sizeof(*b->cpool);+        for (i = 0; i < b->cpool_count; i++) {+            JSValueConst val = b->cpool[i];+            compute_value_size(val, hp);+        }+    }+    if (b->closure_var) {+        js_func_size += b->closure_var_count * sizeof(*b->closure_var);+    }+    if (!b->read_only_bytecode && b->byte_code_buf) {+        hp->js_func_code_size += b->byte_code_len;+    }+    if (b->has_debug) {+        js_func_size += sizeof(*b) - offsetof(JSFunctionBytecode, debug);+        if (b->debug.source) {+            memory_used_count++;+            js_func_size += b->debug.source_len + 1;+        }+        if (b->debug.pc2line_len) {+            memory_used_count++;+            hp->js_func_pc2line_count += 1;+            hp->js_func_pc2line_size += b->debug.pc2line_len;+        }+    }+    hp->js_func_size += js_func_size;+    hp->js_func_count += 1;+    hp->memory_used_count += memory_used_count;+}++static void compute_value_size(JSValueConst val, JSMemoryUsage_helper *hp)+{+    switch(JS_VALUE_GET_TAG(val)) {+    case JS_TAG_STRING:+        compute_jsstring_size(JS_VALUE_GET_STRING(val), hp);+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+    case JS_TAG_BIG_DECIMAL:+        /* should track JSBigFloat usage */+        break;+#endif+    }+}++void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)+{+    struct list_head *el, *el1;+    int i;+    JSMemoryUsage_helper mem = { 0 }, *hp = &mem;++    memset(s, 0, sizeof(*s));+    s->malloc_count = rt->malloc_state.malloc_count;+    s->malloc_size = rt->malloc_state.malloc_size;+    s->malloc_limit = rt->malloc_state.malloc_limit;++    s->memory_used_count = 2; /* rt + rt->class_array */+    s->memory_used_size = sizeof(JSRuntime) + sizeof(JSValue) * rt->class_count;++    list_for_each(el, &rt->context_list) {+        JSContext *ctx = list_entry(el, JSContext, link);+        JSShape *sh = ctx->array_shape;+        s->memory_used_count += 2; /* ctx + ctx->class_proto */+        s->memory_used_size += sizeof(JSContext) ++            sizeof(JSValue) * rt->class_count;+        s->binary_object_count += ctx->binary_object_count;+        s->binary_object_size += ctx->binary_object_size;++        /* the hashed shapes are counted separately */+        if (sh && !sh->is_hashed) {+            int hash_size = sh->prop_hash_mask + 1;+            s->shape_count++;+            s->shape_size += get_shape_size(hash_size, sh->prop_size);+        }+        list_for_each(el1, &ctx->loaded_modules) {+            JSModuleDef *m = list_entry(el1, JSModuleDef, link);+            s->memory_used_count += 1;+            s->memory_used_size += sizeof(*m);+            if (m->req_module_entries) {+                s->memory_used_count += 1;+                s->memory_used_size += m->req_module_entries_count * sizeof(*m->req_module_entries);+            }+            if (m->export_entries) {+                s->memory_used_count += 1;+                s->memory_used_size += m->export_entries_count * sizeof(*m->export_entries);+                for (i = 0; i < m->export_entries_count; i++) {+                    JSExportEntry *me = &m->export_entries[i];+                    if (me->export_type == JS_EXPORT_TYPE_LOCAL && me->u.local.var_ref) {+                        /* potential multiple count */+                        s->memory_used_count += 1;+                        compute_value_size(me->u.local.var_ref->value, hp);+                    }+                }+            }+            if (m->star_export_entries) {+                s->memory_used_count += 1;+                s->memory_used_size += m->star_export_entries_count * sizeof(*m->star_export_entries);+            }+            if (m->import_entries) {+                s->memory_used_count += 1;+                s->memory_used_size += m->import_entries_count * sizeof(*m->import_entries);+            }+            compute_value_size(m->module_ns, hp);+            compute_value_size(m->func_obj, hp);+        }+    }++    list_for_each(el, &rt->gc_obj_list) {+        JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link);+        JSObject *p;+        JSShape *sh;+        JSShapeProperty *prs;++        /* XXX: could count the other GC object types too */+        if (gp->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE) {+            compute_bytecode_size((JSFunctionBytecode *)gp, hp);+            continue;+        } else if (gp->gc_obj_type != JS_GC_OBJ_TYPE_JS_OBJECT) {+            continue;+        }+        p = (JSObject *)gp;+        sh = p->shape;+        s->obj_count++;+        if (p->prop) {+            s->memory_used_count++;+            s->prop_size += sh->prop_size * sizeof(*p->prop);+            s->prop_count += sh->prop_count;+            prs = get_shape_prop(sh);+            for(i = 0; i < sh->prop_count; i++) {+                JSProperty *pr = &p->prop[i];+                if (prs->atom != JS_ATOM_NULL && !(prs->flags & JS_PROP_TMASK)) {+                    compute_value_size(pr->u.value, hp);+                }+                prs++;+            }+        }+        /* the hashed shapes are counted separately */+        if (!sh->is_hashed) {+            int hash_size = sh->prop_hash_mask + 1;+            s->shape_count++;+            s->shape_size += get_shape_size(hash_size, sh->prop_size);+        }++        switch(p->class_id) {+        case JS_CLASS_ARRAY:             /* u.array | length */+        case JS_CLASS_ARGUMENTS:         /* u.array | length */+            s->array_count++;+            if (p->fast_array) {+                s->fast_array_count++;+                if (p->u.array.u.values) {+                    s->memory_used_count++;+                    s->memory_used_size += p->u.array.count *+                        sizeof(*p->u.array.u.values);+                    s->fast_array_elements += p->u.array.count;+                    for (i = 0; i < p->u.array.count; i++) {+                        compute_value_size(p->u.array.u.values[i], hp);+                    }+                }+            }+            break;+        case JS_CLASS_NUMBER:            /* u.object_data */+        case JS_CLASS_STRING:            /* u.object_data */+        case JS_CLASS_BOOLEAN:           /* u.object_data */+        case JS_CLASS_SYMBOL:            /* u.object_data */+        case JS_CLASS_DATE:              /* u.object_data */+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT:           /* u.object_data */+        case JS_CLASS_BIG_FLOAT:         /* u.object_data */+        case JS_CLASS_BIG_DECIMAL:         /* u.object_data */+#endif+            compute_value_size(p->u.object_data, hp);+            break;+        case JS_CLASS_C_FUNCTION:        /* u.cfunc */+            s->c_func_count++;+            break;+        case JS_CLASS_BYTECODE_FUNCTION: /* u.func */+            {+                JSFunctionBytecode *b = p->u.func.function_bytecode;+                JSVarRef **var_refs = p->u.func.var_refs;+                /* home_object: object will be accounted for in list scan */+                if (var_refs) {+                    s->memory_used_count++;+                    s->js_func_size += b->closure_var_count * sizeof(*var_refs);+                    for (i = 0; i < b->closure_var_count; i++) {+                        if (var_refs[i]) {+                            double ref_count = var_refs[i]->header.ref_count;+                            s->memory_used_count += 1 / ref_count;+                            s->js_func_size += sizeof(*var_refs[i]) / ref_count;+                            /* handle non object closed values */+                            if (var_refs[i]->pvalue == &var_refs[i]->value) {+                                /* potential multiple count */+                                compute_value_size(var_refs[i]->value, hp);+                            }+                        }+                    }+                }+            }+            break;+        case JS_CLASS_BOUND_FUNCTION:    /* u.bound_function */+            {+                JSBoundFunction *bf = p->u.bound_function;+                /* func_obj and this_val are objects */+                for (i = 0; i < bf->argc; i++) {+                    compute_value_size(bf->argv[i], hp);+                }+                s->memory_used_count += 1;+                s->memory_used_size += sizeof(*bf) + bf->argc * sizeof(*bf->argv);+            }+            break;+        case JS_CLASS_C_FUNCTION_DATA:   /* u.c_function_data_record */+            {+                JSCFunctionDataRecord *fd = p->u.c_function_data_record;+                if (fd) {+                    for (i = 0; i < fd->data_len; i++) {+                        compute_value_size(fd->data[i], hp);+                    }+                    s->memory_used_count += 1;+                    s->memory_used_size += sizeof(*fd) + fd->data_len * sizeof(*fd->data);+                }+            }+            break;+        case JS_CLASS_REGEXP:            /* u.regexp */+            compute_jsstring_size(p->u.regexp.pattern, hp);+            compute_jsstring_size(p->u.regexp.bytecode, hp);+            break;++        case JS_CLASS_FOR_IN_ITERATOR:   /* u.for_in_iterator */+            {+                JSForInIterator *it = p->u.for_in_iterator;+                if (it) {+                    compute_value_size(it->obj, hp);+                    s->memory_used_count += 1;+                    s->memory_used_size += sizeof(*it);+                }+            }+            break;+        case JS_CLASS_ARRAY_BUFFER:      /* u.array_buffer */+        case JS_CLASS_SHARED_ARRAY_BUFFER: /* u.array_buffer */+            {+                JSArrayBuffer *abuf = p->u.array_buffer;+                if (abuf) {+                    s->memory_used_count += 1;+                    s->memory_used_size += sizeof(*abuf);+                    if (abuf->data) {+                        s->memory_used_count += 1;+                        s->memory_used_size += abuf->byte_length;+                    }+                }+            }+            break;+        case JS_CLASS_GENERATOR:         /* u.generator_data */+        case JS_CLASS_UINT8C_ARRAY:      /* u.typed_array / u.array */+        case JS_CLASS_INT8_ARRAY:        /* u.typed_array / u.array */+        case JS_CLASS_UINT8_ARRAY:       /* u.typed_array / u.array */+        case JS_CLASS_INT16_ARRAY:       /* u.typed_array / u.array */+        case JS_CLASS_UINT16_ARRAY:      /* u.typed_array / u.array */+        case JS_CLASS_INT32_ARRAY:       /* u.typed_array / u.array */+        case JS_CLASS_UINT32_ARRAY:      /* u.typed_array / u.array */+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT64_ARRAY:   /* u.typed_array / u.array */+        case JS_CLASS_BIG_UINT64_ARRAY:  /* u.typed_array / u.array */+#endif+        case JS_CLASS_FLOAT32_ARRAY:     /* u.typed_array / u.array */+        case JS_CLASS_FLOAT64_ARRAY:     /* u.typed_array / u.array */+        case JS_CLASS_DATAVIEW:          /* u.typed_array */+#ifdef CONFIG_BIGNUM+        case JS_CLASS_FLOAT_ENV:         /* u.float_env */+#endif+        case JS_CLASS_MAP:               /* u.map_state */+        case JS_CLASS_SET:               /* u.map_state */+        case JS_CLASS_WEAKMAP:           /* u.map_state */+        case JS_CLASS_WEAKSET:           /* u.map_state */+        case JS_CLASS_MAP_ITERATOR:      /* u.map_iterator_data */+        case JS_CLASS_SET_ITERATOR:      /* u.map_iterator_data */+        case JS_CLASS_ARRAY_ITERATOR:    /* u.array_iterator_data */+        case JS_CLASS_STRING_ITERATOR:   /* u.array_iterator_data */+        case JS_CLASS_PROXY:             /* u.proxy_data */+        case JS_CLASS_PROMISE:           /* u.promise_data */+        case JS_CLASS_PROMISE_RESOLVE_FUNCTION:  /* u.promise_function_data */+        case JS_CLASS_PROMISE_REJECT_FUNCTION:   /* u.promise_function_data */+        case JS_CLASS_ASYNC_FUNCTION_RESOLVE:    /* u.async_function_data */+        case JS_CLASS_ASYNC_FUNCTION_REJECT:     /* u.async_function_data */+        case JS_CLASS_ASYNC_FROM_SYNC_ITERATOR:  /* u.async_from_sync_iterator_data */+        case JS_CLASS_ASYNC_GENERATOR:   /* u.async_generator_data */+            /* TODO */+        default:+            /* XXX: class definition should have an opaque block size */+            if (p->u.opaque) {+                s->memory_used_count += 1;+            }+            break;+        }+    }+    s->obj_size += s->obj_count * sizeof(JSObject);++    /* hashed shapes */+    s->memory_used_count++; /* rt->shape_hash */+    s->memory_used_size += sizeof(rt->shape_hash[0]) * rt->shape_hash_size;+    for(i = 0; i < rt->shape_hash_size; i++) {+        JSShape *sh;+        for(sh = rt->shape_hash[i]; sh != NULL; sh = sh->shape_hash_next) {+            int hash_size = sh->prop_hash_mask + 1;+            s->shape_count++;+            s->shape_size += get_shape_size(hash_size, sh->prop_size);+        }+    }++    /* atoms */+    s->memory_used_count += 2; /* rt->atom_array, rt->atom_hash */+    s->atom_count = rt->atom_count;+    s->atom_size = sizeof(rt->atom_array[0]) * rt->atom_size ++        sizeof(rt->atom_hash[0]) * rt->atom_hash_size;+    for(i = 0; i < rt->atom_size; i++) {+        JSAtomStruct *p = rt->atom_array[i];+        if (!atom_is_free(p)) {+            s->atom_size += (sizeof(*p) + (p->len << p->is_wide_char) ++                             1 - p->is_wide_char);+        }+    }+    s->str_count = round(mem.str_count);+    s->str_size = round(mem.str_size);+    s->js_func_count = mem.js_func_count;+    s->js_func_size = round(mem.js_func_size);+    s->js_func_code_size = mem.js_func_code_size;+    s->js_func_pc2line_count = mem.js_func_pc2line_count;+    s->js_func_pc2line_size = mem.js_func_pc2line_size;+    s->memory_used_count += round(mem.memory_used_count) ++        s->atom_count + s->str_count ++        s->obj_count + s->shape_count ++        s->js_func_count + s->js_func_pc2line_count;+    s->memory_used_size += s->atom_size + s->str_size ++        s->obj_size + s->prop_size + s->shape_size ++        s->js_func_size + s->js_func_code_size + s->js_func_pc2line_size;+}++void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt)+{+    fprintf(fp, "QuickJS memory usage -- "+#ifdef CONFIG_BIGNUM+            "BigNum "+#endif+            CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",+            (int)sizeof(void *) * 8, (int64_t)(ssize_t)s->malloc_limit);+#if 1+    if (rt) {+        static const struct {+            const char *name;+            size_t size;+        } object_types[] = {+            { "JSRuntime", sizeof(JSRuntime) },+            { "JSContext", sizeof(JSContext) },+            { "JSObject", sizeof(JSObject) },+            { "JSString", sizeof(JSString) },+            { "JSFunctionBytecode", sizeof(JSFunctionBytecode) },+        };+        int i, usage_size_ok = 0;+        for(i = 0; i < countof(object_types); i++) {+            unsigned int size = object_types[i].size;+            void *p = js_malloc_rt(rt, size);+            if (p) {+                unsigned int size1 = js_malloc_usable_size_rt(rt, p);+                if (size1 >= size) {+                    usage_size_ok = 1;+                    fprintf(fp, "  %3u + %-2u  %s\n",+                            size, size1 - size, object_types[i].name);+                }+                js_free_rt(rt, p);+            }+        }+        if (!usage_size_ok) {+            fprintf(fp, "  malloc_usable_size unavailable\n");+        }+        {+            int obj_classes[JS_CLASS_INIT_COUNT + 1] = { 0 };+            int class_id;+            struct list_head *el;+            list_for_each(el, &rt->gc_obj_list) {+                JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link);+                JSObject *p;+                if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {+                    p = (JSObject *)gp;+                    obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++;+                }+            }+            fprintf(fp, "\n" "JSObject classes\n");+            if (obj_classes[0])+                fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[0], 0, "none");+            for (class_id = 1; class_id < JS_CLASS_INIT_COUNT; class_id++) {+                if (obj_classes[class_id]) {+                    char buf[ATOM_GET_STR_BUF_SIZE];+                    fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[class_id], class_id,+                            JS_AtomGetStrRT(rt, buf, sizeof(buf), js_std_class_def[class_id - 1].class_name));+                }+            }+            if (obj_classes[JS_CLASS_INIT_COUNT])+                fprintf(fp, "  %5d  %2.0d %s\n", obj_classes[JS_CLASS_INIT_COUNT], 0, "other");+        }+        fprintf(fp, "\n");+    }+#endif+    fprintf(fp, "%-20s %8s %8s\n", "NAME", "COUNT", "SIZE");++    if (s->malloc_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per block)\n",+                "memory allocated", s->malloc_count, s->malloc_size,+                (double)s->malloc_size / s->malloc_count);+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%d overhead, %0.1f average slack)\n",+                "memory used", s->memory_used_count, s->memory_used_size,+                MALLOC_OVERHEAD, ((double)(s->malloc_size - s->memory_used_size) /+                                  s->memory_used_count));+    }+    if (s->atom_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per atom)\n",+                "atoms", s->atom_count, s->atom_size,+                (double)s->atom_size / s->atom_count);+    }+    if (s->str_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per string)\n",+                "strings", s->str_count, s->str_size,+                (double)s->str_size / s->str_count);+    }+    if (s->obj_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per object)\n",+                "objects", s->obj_count, s->obj_size,+                (double)s->obj_size / s->obj_count);+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per object)\n",+                "  properties", s->prop_count, s->prop_size,+                (double)s->prop_count / s->obj_count);+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per shape)\n",+                "  shapes", s->shape_count, s->shape_size,+                (double)s->shape_size / s->shape_count);+    }+    if (s->js_func_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",+                "bytecode functions", s->js_func_count, s->js_func_size);+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per function)\n",+                "  bytecode", s->js_func_count, s->js_func_code_size,+                (double)s->js_func_code_size / s->js_func_count);+        if (s->js_func_pc2line_count) {+            fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per function)\n",+                    "  pc2line", s->js_func_pc2line_count,+                    s->js_func_pc2line_size,+                    (double)s->js_func_pc2line_size / s->js_func_pc2line_count);+        }+    }+    if (s->c_func_count) {+        fprintf(fp, "%-20s %8"PRId64"\n", "C functions", s->c_func_count);+    }+    if (s->array_count) {+        fprintf(fp, "%-20s %8"PRId64"\n", "arrays", s->array_count);+        if (s->fast_array_count) {+            fprintf(fp, "%-20s %8"PRId64"\n", "  fast arrays", s->fast_array_count);+            fprintf(fp, "%-20s %8"PRId64" %8"PRId64"  (%0.1f per fast array)\n",+                    "  elements", s->fast_array_elements,+                    s->fast_array_elements * (int)sizeof(JSValue),+                    (double)s->fast_array_elements / s->fast_array_count);+        }+    }+    if (s->binary_object_count) {+        fprintf(fp, "%-20s %8"PRId64" %8"PRId64"\n",+                "binary objects", s->binary_object_count, s->binary_object_size);+    }+}++JSValue JS_GetGlobalObject(JSContext *ctx)+{+    return JS_DupValue(ctx, ctx->global_obj);+}++/* WARNING: obj is freed */+JSValue JS_Throw(JSContext *ctx, JSValue obj)+{+    JSRuntime *rt = ctx->rt;+    JS_FreeValue(ctx, rt->current_exception);+    rt->current_exception = obj;+    return JS_EXCEPTION;+}++/* return the pending exception (cannot be called twice). */+JSValue JS_GetException(JSContext *ctx)+{+    JSValue val;+    JSRuntime *rt = ctx->rt;+    val = rt->current_exception;+    rt->current_exception = JS_NULL;+    return val;+}++static void dbuf_put_leb128(DynBuf *s, uint32_t v)+{+    uint32_t a;+    for(;;) {+        a = v & 0x7f;+        v >>= 7;+        if (v != 0) {+            dbuf_putc(s, a | 0x80);+        } else {+            dbuf_putc(s, a);+            break;+        }+    }+}++static void dbuf_put_sleb128(DynBuf *s, int32_t v1)+{+    uint32_t v = v1;+    dbuf_put_leb128(s, (2 * v) ^ -(v >> 31));+}++static int get_leb128(uint32_t *pval, const uint8_t *buf,+                      const uint8_t *buf_end)+{+    const uint8_t *ptr = buf;+    uint32_t v, a, i;+    v = 0;+    for(i = 0; i < 5; i++) {+        if (unlikely(ptr >= buf_end))+            break;+        a = *ptr++;+        v |= (a & 0x7f) << (i * 7);+        if (!(a & 0x80)) {+            *pval = v;+            return ptr - buf;+        }+    }+    *pval = 0;+    return -1;+}++static int get_sleb128(int32_t *pval, const uint8_t *buf,+                       const uint8_t *buf_end)+{+    int ret;+    uint32_t val;+    ret = get_leb128(&val, buf, buf_end);+    if (ret < 0) {+        *pval = 0;+        return -1;+    }+    *pval = (val >> 1) ^ -(val & 1);+    return ret;+}++static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,+                         uint32_t pc_value)+{+    const uint8_t *p_end, *p;+    int new_line_num, line_num, pc, v, ret;+    unsigned int op;++    if (!b->has_debug || !b->debug.pc2line_buf) {+        /* function was stripped */+        return -1;+    }++    p = b->debug.pc2line_buf;+    p_end = p + b->debug.pc2line_len;+    pc = 0;+    line_num = b->debug.line_num;+    while (p < p_end) {+        op = *p++;+        if (op == 0) {+            uint32_t val;+            ret = get_leb128(&val, p, p_end);+            if (ret < 0)+                goto fail;+            pc += val;+            p += ret;+            ret = get_sleb128(&v, p, p_end);+            if (ret < 0) {+            fail:+                /* should never happen */+                return b->debug.line_num;+            }+            p += ret;+            new_line_num = line_num + v;+        } else {+            op -= PC2LINE_OP_FIRST;+            pc += (op / PC2LINE_RANGE);+            new_line_num = line_num + (op % PC2LINE_RANGE) + PC2LINE_BASE;+        }+        if (pc_value < pc)+            return line_num;+        line_num = new_line_num;+    }+    return line_num;+}++/* in order to avoid executing arbitrary code during the stack trace+   generation, we only look at simple 'name' properties containing a+   string. */+static const char *get_func_name(JSContext *ctx, JSValueConst func)+{+    JSProperty *pr;+    JSShapeProperty *prs;+    JSValueConst val;+    +    if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)+        return NULL;+    prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name);+    if (!prs)+        return NULL;+    if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)+        return NULL;+    val = pr->u.value;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)+        return NULL;+    return JS_ToCString(ctx, val);+}++#define JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL (1 << 0)+/* only taken into account if filename is provided */+#define JS_BACKTRACE_FLAG_SINGLE_LEVEL     (1 << 1)++/* if filename != NULL, an additional level is added with the filename+   and line number information (used for parse error). */+static void build_backtrace(JSContext *ctx, JSValueConst error_obj,+                            const char *filename, int line_num,+                            int backtrace_flags)+{+    JSStackFrame *sf;+    JSValue str;+    DynBuf dbuf;+    const char *func_name_str;+    const char *str1;+    JSObject *p;+    BOOL backtrace_barrier;+    +    js_dbuf_init(ctx, &dbuf);+    if (filename) {+        dbuf_printf(&dbuf, "    at %s", filename);+        if (line_num != -1)+            dbuf_printf(&dbuf, ":%d", line_num);+        dbuf_putc(&dbuf, '\n');+        str = JS_NewString(ctx, filename);+        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+        JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+        if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)+            goto done;+    }+    for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {+        if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {+            backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;+            continue;+        }+        func_name_str = get_func_name(ctx, sf->cur_func);+        if (!func_name_str || func_name_str[0] == '\0')+            str1 = "<anonymous>";+        else+            str1 = func_name_str;+        dbuf_printf(&dbuf, "    at %s", str1);+        JS_FreeCString(ctx, func_name_str);++        p = JS_VALUE_GET_OBJ(sf->cur_func);+        backtrace_barrier = FALSE;+        if (js_class_has_bytecode(p->class_id)) {+            JSFunctionBytecode *b;+            const char *atom_str;+            int line_num1;++            b = p->u.func.function_bytecode;+            backtrace_barrier = b->backtrace_barrier;+            if (b->has_debug) {+                line_num1 = find_line_num(ctx, b,+                                          sf->cur_pc - b->byte_code_buf - 1);+                atom_str = JS_AtomToCString(ctx, b->debug.filename);+                dbuf_printf(&dbuf, " (%s",+                            atom_str ? atom_str : "<null>");+                JS_FreeCString(ctx, atom_str);+                if (line_num1 != -1)+                    dbuf_printf(&dbuf, ":%d", line_num1);+                dbuf_putc(&dbuf, ')');+            }+        } else {+            dbuf_printf(&dbuf, " (native)");+        }+        dbuf_putc(&dbuf, '\n');+        /* stop backtrace if JS_EVAL_FLAG_BACKTRACE_BARRIER was used */+        if (backtrace_barrier)+            break;+    }+ done:+    dbuf_putc(&dbuf, '\0');+    if (dbuf_error(&dbuf))+        str = JS_NULL;+    else+        str = JS_NewString(ctx, (char *)dbuf.buf);+    dbuf_free(&dbuf);+    JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str,+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+}++/* Note: it is important that no exception is returned by this function */+static BOOL is_backtrace_needed(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    if (p->class_id != JS_CLASS_ERROR)+        return FALSE;+    if (find_own_property1(p, JS_ATOM_stack))+        return FALSE;+    return TRUE;+}++JSValue JS_NewError(JSContext *ctx)+{+    return JS_NewObjectClass(ctx, JS_CLASS_ERROR);+}++static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,+                              const char *fmt, va_list ap, BOOL add_backtrace)+{+    char buf[256];+    JSValue obj, ret;++    vsnprintf(buf, sizeof(buf), fmt, ap);+    obj = JS_NewObjectProtoClass(ctx, ctx->native_error_proto[error_num],+                                 JS_CLASS_ERROR);+    if (unlikely(JS_IsException(obj))) {+        /* out of memory: throw JS_NULL to avoid recursing */+        obj = JS_NULL;+    } else {+        JS_DefinePropertyValue(ctx, obj, JS_ATOM_message,+                               JS_NewString(ctx, buf),+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    }+    if (add_backtrace) {+        build_backtrace(ctx, obj, NULL, 0, 0);+    }+    ret = JS_Throw(ctx, obj);+    return ret;+}++static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,+                             const char *fmt, va_list ap)+{+    JSRuntime *rt = ctx->rt;+    JSStackFrame *sf;+    BOOL add_backtrace;++    /* the backtrace is added later if called from a bytecode function */+    sf = rt->current_stack_frame;+    add_backtrace = !rt->in_out_of_memory &&+        (!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL));+    return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);+}++JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)+{+    JSValue val;+    va_list ap;++    va_start(ap, fmt);+    val = JS_ThrowError(ctx, JS_SYNTAX_ERROR, fmt, ap);+    va_end(ap);+    return val;+}++JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)+{+    JSValue val;+    va_list ap;++    va_start(ap, fmt);+    val = JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap);+    va_end(ap);+    return val;+}++static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)+{+    va_list ap;++    if ((flags & JS_PROP_THROW) ||+        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {+        va_start(ap, fmt);+        JS_ThrowError(ctx, JS_TYPE_ERROR, fmt, ap);+        va_end(ap);+        return -1;+    } else {+        return FALSE;+    }+}++/* never use it directly */+static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    return JS_ThrowTypeError(ctx, fmt,+                             JS_AtomGetStr(ctx, buf, sizeof(buf), atom));+}++/* never use it directly */+static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    return JS_ThrowSyntaxError(ctx, fmt,+                             JS_AtomGetStr(ctx, buf, sizeof(buf), atom));+}++/* %s is replaced by 'atom'. The macro is used so that gcc can check+    the format string. */+#define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "")+#define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "")++static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom)+{+    if ((flags & JS_PROP_THROW) ||+        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {+        JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom);+        return -1;+    } else {+        return FALSE;+    }+}++JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)+{+    JSValue val;+    va_list ap;++    va_start(ap, fmt);+    val = JS_ThrowError(ctx, JS_REFERENCE_ERROR, fmt, ap);+    va_end(ap);+    return val;+}++JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)+{+    JSValue val;+    va_list ap;++    va_start(ap, fmt);+    val = JS_ThrowError(ctx, JS_RANGE_ERROR, fmt, ap);+    va_end(ap);+    return val;+}++JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)+{+    JSValue val;+    va_list ap;++    va_start(ap, fmt);+    val = JS_ThrowError(ctx, JS_INTERNAL_ERROR, fmt, ap);+    va_end(ap);+    return val;+}++JSValue JS_ThrowOutOfMemory(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    if (!rt->in_out_of_memory) {+        rt->in_out_of_memory = TRUE;+        JS_ThrowInternalError(ctx, "out of memory");+        rt->in_out_of_memory = FALSE;+    }+    return JS_EXCEPTION;+}++static JSValue JS_ThrowStackOverflow(JSContext *ctx)+{+    return JS_ThrowInternalError(ctx, "stack overflow");+}++static JSValue JS_ThrowTypeErrorNotAnObject(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "not an object");+}++static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "not a symbol");+}++static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    return JS_ThrowReferenceError(ctx, "'%s' is not defined",+                                  JS_AtomGetStr(ctx, buf, sizeof(buf), name));+}++static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    return JS_ThrowReferenceError(ctx, "%s is not initialized",+                                  name == JS_ATOM_NULL ? "lexical variable" :+                                  JS_AtomGetStr(ctx, buf, sizeof(buf), name));+}++static JSValue JS_ThrowReferenceErrorUninitialized2(JSContext *ctx,+                                                    JSFunctionBytecode *b,+                                                    int idx, BOOL is_ref)+{+    JSAtom atom = JS_ATOM_NULL;+    if (is_ref) {+        atom = b->closure_var[idx].var_name;+    } else {+        /* not present if the function is stripped and contains no eval() */+        if (b->vardefs)+            atom = b->vardefs[b->arg_count + idx].var_name;+    }+    return JS_ThrowReferenceErrorUninitialized(ctx, atom);+}++static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)+{+    JSRuntime *rt = ctx->rt;+    JSAtom name;+    name = rt->class_array[class_id].class_name;+    return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name);+}++static no_inline __exception int __js_poll_interrupts(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;+    if (rt->interrupt_handler) {+        if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {+            /* XXX: should set a specific flag to avoid catching */+            JS_ThrowInternalError(ctx, "interrupted");+            JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);+            return -1;+        }+    }+    return 0;+}++static inline __exception int js_poll_interrupts(JSContext *ctx)+{+    if (unlikely(--ctx->interrupt_counter <= 0)) {+        return __js_poll_interrupts(ctx);+    } else {+        return 0;+    }+}++/* return -1 (exception) or TRUE/FALSE */+static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,+                                   JSValueConst proto_val,+                                   BOOL throw_flag)+{+    JSObject *proto, *p, *p1;+    JSShape *sh;++    if (throw_flag) {+        if (JS_VALUE_GET_TAG(obj) == JS_TAG_NULL ||+            JS_VALUE_GET_TAG(obj) == JS_TAG_UNDEFINED)+            goto not_obj;+    } else {+        if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+            goto not_obj;+    }+    p = JS_VALUE_GET_OBJ(obj);+    if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_OBJECT) {+        if (JS_VALUE_GET_TAG(proto_val) != JS_TAG_NULL) {+        not_obj:+            JS_ThrowTypeErrorNotAnObject(ctx);+            return -1;+        }+        proto = NULL;+    } else {+        proto = JS_VALUE_GET_OBJ(proto_val);+    }++    if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return TRUE;++    if (unlikely(p->class_id == JS_CLASS_PROXY))+        return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag);+    sh = p->shape;+    if (sh->proto == proto)+        return TRUE;+    if (!p->extensible) {+        if (throw_flag) {+            JS_ThrowTypeError(ctx, "object is not extensible");+            return -1;+        } else {+            return FALSE;+        }+    }+    if (proto) {+        /* check if there is a cycle */+        p1 = proto;+        do {+            if (p1 == p) {+                if (throw_flag) {+                    JS_ThrowTypeError(ctx, "circular prototype chain");+                    return -1;+                } else {+                    return FALSE;+                }+            }+            /* Note: for Proxy objects, proto is NULL */+            p1 = p1->shape->proto;+        } while (p1 != NULL);+        JS_DupValue(ctx, proto_val);+    }++    if (js_shape_prepare_update(ctx, p, NULL))+        return -1;+    sh = p->shape;+    if (sh->proto)+        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, sh->proto));+    sh->proto = proto;+    return TRUE;+}++/* return -1 (exception) or TRUE/FALSE */+int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val)+{+    return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE);+}++/* Only works for primitive types, otherwise return JS_NULL. */+static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val)+{+    switch(JS_VALUE_GET_NORM_TAG(val)) {+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        val = ctx->class_proto[JS_CLASS_BIG_INT];+        break;+    case JS_TAG_BIG_FLOAT:+        val = ctx->class_proto[JS_CLASS_BIG_FLOAT];+        break;+    case JS_TAG_BIG_DECIMAL:+        val = ctx->class_proto[JS_CLASS_BIG_DECIMAL];+        break;+#endif+    case JS_TAG_INT:+    case JS_TAG_FLOAT64:+        val = ctx->class_proto[JS_CLASS_NUMBER];+        break;+    case JS_TAG_BOOL:+        val = ctx->class_proto[JS_CLASS_BOOLEAN];+        break;+    case JS_TAG_STRING:+        val = ctx->class_proto[JS_CLASS_STRING];+        break;+    case JS_TAG_SYMBOL:+        val = ctx->class_proto[JS_CLASS_SYMBOL];+        break;+    case JS_TAG_OBJECT:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+    default:+        val = JS_NULL;+        break;+    }+    return val;+}++/* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */+JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj)+{+    JSValue val;+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        JSObject *p;+        p = JS_VALUE_GET_OBJ(obj);+        if (unlikely(p->class_id == JS_CLASS_PROXY)) {+            val = js_proxy_getPrototypeOf(ctx, obj);+        } else {+            p = p->shape->proto;+            if (!p)+                val = JS_NULL;+            else+                val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+        }+    } else {+        val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj));+    }+    return val;+}++static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj)+{+    JSValue obj1;+    obj1 = JS_GetPrototype(ctx, obj);+    JS_FreeValue(ctx, obj);+    return obj1;+}++/* return TRUE, FALSE or (-1) in case of exception */+static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val,+                                   JSValueConst obj)+{+    JSValue obj_proto;+    JSObject *proto;+    const JSObject *p, *proto1;+    BOOL ret;++    if (!JS_IsFunction(ctx, obj))+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    if (p->class_id == JS_CLASS_BOUND_FUNCTION) {+        JSBoundFunction *s = p->u.bound_function;+        return JS_IsInstanceOf(ctx, val, s->func_obj);+    }++    /* Only explicitly boxed values are instances of constructors */+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype);+    if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) {+        if (!JS_IsException(obj_proto))+            JS_ThrowTypeError(ctx, "operand 'prototype' property is not an object");+        ret = -1;+        goto done;+    }+    proto = JS_VALUE_GET_OBJ(obj_proto);+    p = JS_VALUE_GET_OBJ(val);+    for(;;) {+        proto1 = p->shape->proto;+        if (!proto1) {+            /* slow case if proxy in the prototype chain */+            if (unlikely(p->class_id == JS_CLASS_PROXY)) {+                JSValue obj1;+                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p));+                for(;;) {+                    obj1 = JS_GetPrototypeFree(ctx, obj1);+                    if (JS_IsException(obj1)) {+                        ret = -1;+                        break;+                    }+                    if (JS_IsNull(obj1)) {+                        ret = FALSE;+                        break;+                    }+                    if (proto == JS_VALUE_GET_OBJ(obj1)) {+                        JS_FreeValue(ctx, obj1);+                        ret = TRUE;+                        break;+                    }+                    /* must check for timeout to avoid infinite loop */+                    if (js_poll_interrupts(ctx)) {+                        JS_FreeValue(ctx, obj1);+                        ret = -1;+                        break;+                    }+                }+            } else {+                ret = FALSE;+            }+            break;+        }+        p = proto1;+        if (proto == p) {+            ret = TRUE;+            break;+        }+    }+done:+    JS_FreeValue(ctx, obj_proto);+    return ret;+}++/* return TRUE, FALSE or (-1) in case of exception */+int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj)+{+    JSValue method;++    if (!JS_IsObject(obj))+        goto fail;+    method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_hasInstance);+    if (JS_IsException(method))+        return -1;+    if (!JS_IsNull(method) && !JS_IsUndefined(method)) {+        JSValue ret;+        ret = JS_CallFree(ctx, method, obj, 1, &val);+        return JS_ToBoolFree(ctx, ret);+    }++    /* legacy case */+    if (!JS_IsFunction(ctx, obj)) {+    fail:+        JS_ThrowTypeError(ctx, "invalid 'instanceof' right operand");+        return -1;+    }+    return JS_OrdinaryIsInstanceOf(ctx, val, obj);+}++/* return the value associated to the autoinit property or an exception */+typedef JSValue JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);++static JSAutoInitFunc *js_autoinit_func_table[] = {+    js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */+    js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */+    JS_InstantiateFunctionListItem2, /* JS_AUTOINIT_ID_PROP */+};++/* warning: 'prs' is reallocated after it */+static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,+                               JSProperty *pr, JSShapeProperty *prs)+{+    JSValue val;+    JSContext *realm;+    JSAutoInitFunc *func;++    if (js_shape_prepare_update(ctx, p, &prs))+        return -1;++    realm = js_autoinit_get_realm(pr);+    func = js_autoinit_func_table[js_autoinit_get_id(pr)];+    /* 'func' shall not modify the object properties 'pr' */+    val = func(realm, p, prop, pr->u.init.opaque);+    js_autoinit_free(ctx->rt, pr);+    prs->flags &= ~JS_PROP_TMASK;+    pr->u.value = JS_UNDEFINED;+    if (JS_IsException(val))+        return -1;+    pr->u.value = val;+    return 0;+}++JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,+                               JSAtom prop, JSValueConst this_obj,+                               BOOL throw_ref_error)+{+    JSObject *p;+    JSProperty *pr;+    JSShapeProperty *prs;+    uint32_t tag;++    tag = JS_VALUE_GET_TAG(obj);+    if (unlikely(tag != JS_TAG_OBJECT)) {+        switch(tag) {+        case JS_TAG_NULL:+            return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop);+        case JS_TAG_UNDEFINED:+            return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", prop);+        case JS_TAG_EXCEPTION:+            return JS_EXCEPTION;+        case JS_TAG_STRING:+            {+                JSString *p1 = JS_VALUE_GET_STRING(obj);+                if (__JS_AtomIsTaggedInt(prop)) {+                    uint32_t idx, ch;+                    idx = __JS_AtomToUInt32(prop);+                    if (idx < p1->len) {+                        if (p1->is_wide_char)+                            ch = p1->u.str16[idx];+                        else+                            ch = p1->u.str8[idx];+                        return js_new_string_char(ctx, ch);+                    }+                } else if (prop == JS_ATOM_length) {+                    return JS_NewInt32(ctx, p1->len);+                }+            }+            break;+        default:+            break;+        }+        /* cannot raise an exception */+        p = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj));+        if (!p)+            return JS_UNDEFINED;+    } else {+        p = JS_VALUE_GET_OBJ(obj);+    }++    for(;;) {+        prs = find_own_property(&pr, p, prop);+        if (prs) {+            /* found */+            if (unlikely(prs->flags & JS_PROP_TMASK)) {+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                    if (unlikely(!pr->u.getset.getter)) {+                        return JS_UNDEFINED;+                    } else {+                        JSValue func = JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter);+                        /* Note: the field could be removed in the getter */+                        func = JS_DupValue(ctx, func);+                        return JS_CallFree(ctx, func, this_obj, 0, NULL);+                    }+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                    JSValue val = *pr->u.var_ref->pvalue;+                    if (unlikely(JS_IsUninitialized(val)))+                        return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+                    return JS_DupValue(ctx, val);+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                    /* Instantiate property and retry */+                    if (JS_AutoInitProperty(ctx, p, prop, pr, prs))+                        return JS_EXCEPTION;+                    continue;+                }+            } else {+                return JS_DupValue(ctx, pr->u.value);+            }+        }+        if (unlikely(p->is_exotic)) {+            /* exotic behaviors */+            if (p->fast_array) {+                if (__JS_AtomIsTaggedInt(prop)) {+                    uint32_t idx = __JS_AtomToUInt32(prop);+                    if (idx < p->u.array.count) {+                        /* we avoid duplicating the code */+                        return JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);+                    } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+                               p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+                        return JS_UNDEFINED;+                    }+                } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+                           p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+                    int ret;+                    ret = JS_AtomIsNumericIndex(ctx, prop);+                    if (ret != 0) {+                        if (ret < 0)+                            return JS_EXCEPTION;+                        return JS_UNDEFINED;+                    }+                }+            } else {+                const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+                if (em) {+                    if (em->get_property) {+                        JSValue obj1, retval;+                        /* XXX: should pass throw_ref_error */+                        /* Note: if 'p' is a prototype, it can be+                           freed in the called function */+                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+                        retval = em->get_property(ctx, obj1, prop, this_obj);+                        JS_FreeValue(ctx, obj1);+                        return retval;+                    }+                    if (em->get_own_property) {+                        JSPropertyDescriptor desc;+                        int ret;+                        JSValue obj1;++                        /* Note: if 'p' is a prototype, it can be+                           freed in the called function */+                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+                        ret = em->get_own_property(ctx, &desc, obj1, prop);+                        JS_FreeValue(ctx, obj1);+                        if (ret < 0)+                            return JS_EXCEPTION;+                        if (ret) {+                            if (desc.flags & JS_PROP_GETSET) {+                                JS_FreeValue(ctx, desc.setter);+                                return JS_CallFree(ctx, desc.getter, this_obj, 0, NULL);+                            } else {+                                return desc.value;+                            }+                        }+                    }+                }+            }+        }+        p = p->shape->proto;+        if (!p)+            break;+    }+    if (unlikely(throw_ref_error)) {+        return JS_ThrowReferenceErrorNotDefined(ctx, prop);+    } else {+        return JS_UNDEFINED;+    }+}++static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)+{+    return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist",+                                 atom);+}++/* Private fields can be added even on non extensible objects or+   Proxies */+static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj,+                                 JSValueConst name, JSValue val)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSAtom prop;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        goto fail;+    }+    /* safety check */+    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) {+        JS_ThrowTypeErrorNotASymbol(ctx);+        goto fail;+    }+    prop = js_symbol_to_atom(ctx, (JSValue)name);+    p = JS_VALUE_GET_OBJ(obj);+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists",+                              prop);+        goto fail;+    }+    pr = add_property(ctx, p, prop, JS_PROP_C_W_E);+    if (unlikely(!pr)) {+    fail:+        JS_FreeValue(ctx, val);+        return -1;+    }+    pr->u.value = val;+    return 0;+}++static JSValue JS_GetPrivateField(JSContext *ctx, JSValueConst obj,+                                  JSValueConst name)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSAtom prop;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    /* safety check */+    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL))+        return JS_ThrowTypeErrorNotASymbol(ctx);+    prop = js_symbol_to_atom(ctx, (JSValue)name);+    p = JS_VALUE_GET_OBJ(obj);+    prs = find_own_property(&pr, p, prop);+    if (!prs) {+        JS_ThrowTypeErrorPrivateNotFound(ctx, prop);+        return JS_EXCEPTION;+    }+    return JS_DupValue(ctx, pr->u.value);+}++static int JS_SetPrivateField(JSContext *ctx, JSValueConst obj,+                              JSValueConst name, JSValue val)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSAtom prop;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        goto fail;+    }+    /* safety check */+    if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL)) {+        JS_ThrowTypeErrorNotASymbol(ctx);+        goto fail;+    }+    prop = js_symbol_to_atom(ctx, (JSValue)name);+    p = JS_VALUE_GET_OBJ(obj);+    prs = find_own_property(&pr, p, prop);+    if (!prs) {+        JS_ThrowTypeErrorPrivateNotFound(ctx, prop);+    fail:+        JS_FreeValue(ctx, val);+        return -1;+    }+    set_value(ctx, &pr->u.value, val);+    return 0;+}++static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj)+{+    JSObject *p, *p1;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSValue brand;+    JSAtom brand_atom;+    +    if (unlikely(JS_VALUE_GET_TAG(home_obj) != JS_TAG_OBJECT)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    p = JS_VALUE_GET_OBJ(home_obj);+    prs = find_own_property(&pr, p, JS_ATOM_Private_brand);+    if (!prs) {+        brand = JS_NewSymbolFromAtom(ctx, JS_ATOM_brand, JS_ATOM_TYPE_PRIVATE);+        if (JS_IsException(brand))+            return -1;+        /* if the brand is not present, add it */+        pr = add_property(ctx, p, JS_ATOM_Private_brand, JS_PROP_C_W_E);+        if (!pr) {+            JS_FreeValue(ctx, brand);+            return -1;+        }+        pr->u.value = JS_DupValue(ctx, brand);+    } else {+        brand = JS_DupValue(ctx, pr->u.value);+    }+    brand_atom = js_symbol_to_atom(ctx, brand);+    +    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        JS_FreeAtom(ctx, brand_atom);+        return -1;+    }+    p1 = JS_VALUE_GET_OBJ(obj);+    pr = add_property(ctx, p1, brand_atom, JS_PROP_C_W_E);+    JS_FreeAtom(ctx, brand_atom);+    if (!pr)+        return -1;+    pr->u.value = JS_UNDEFINED;+    return 0;+}++static int JS_CheckBrand(JSContext *ctx, JSValueConst obj, JSValueConst func)+{+    JSObject *p, *p1, *home_obj;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSValueConst brand;+    +    /* get the home object of 'func' */+    if (unlikely(JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)) {+    not_obj:+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    p1 = JS_VALUE_GET_OBJ(func);+    if (!js_class_has_bytecode(p1->class_id))+        goto not_obj;+    home_obj = p1->u.func.home_object;+    if (!home_obj)+        goto not_obj;+    prs = find_own_property(&pr, home_obj, JS_ATOM_Private_brand);+    if (!prs) {+        JS_ThrowTypeError(ctx, "expecting <brand> private field");+        return -1;+    }+    brand = pr->u.value;+    /* safety check */+    if (unlikely(JS_VALUE_GET_TAG(brand) != JS_TAG_SYMBOL))+        goto not_obj;+    +    /* get the brand array of 'obj' */+    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))+        goto not_obj;+    p = JS_VALUE_GET_OBJ(obj);+    prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));+    if (!prs) {+        JS_ThrowTypeError(ctx, "invalid brand on object");+        return -1;+    }+    return 0;+}++static uint32_t js_string_obj_get_length(JSContext *ctx,+                                         JSValueConst obj)+{+    JSObject *p;+    JSString *p1;+    uint32_t len = 0;++    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */+    p = JS_VALUE_GET_OBJ(obj);+    if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {+        p1 = JS_VALUE_GET_STRING(p->u.object_data);+        len = p1->len;+    }+    return len;+}++static int num_keys_cmp(const void *p1, const void *p2, void *opaque)+{+    JSContext *ctx = opaque;+    JSAtom atom1 = ((const JSPropertyEnum *)p1)->atom;+    JSAtom atom2 = ((const JSPropertyEnum *)p2)->atom;+    uint32_t v1, v2;+    BOOL atom1_is_integer, atom2_is_integer;++    atom1_is_integer = JS_AtomIsArrayIndex(ctx, &v1, atom1);+    atom2_is_integer = JS_AtomIsArrayIndex(ctx, &v2, atom2);+    assert(atom1_is_integer && atom2_is_integer);+    if (v1 < v2)+        return -1;+    else if (v1 == v2)+        return 0;+    else+        return 1;+}++static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)+{+    uint32_t i;+    if (tab) {+        for(i = 0; i < len; i++)+            JS_FreeAtom(ctx, tab[i].atom);+        js_free(ctx, tab);+    }+}++/* return < 0 in case if exception, 0 if OK. ptab and its atoms must+   be freed by the user. */+static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,+                                                      JSPropertyEnum **ptab,+                                                      uint32_t *plen,+                                                      JSObject *p, int flags)+{+    int i, j;+    JSShape *sh;+    JSShapeProperty *prs;+    JSPropertyEnum *tab_atom, *tab_exotic;+    JSAtom atom;+    uint32_t num_keys_count, str_keys_count, sym_keys_count, atom_count;+    uint32_t num_index, str_index, sym_index, exotic_count, exotic_keys_count;+    BOOL is_enumerable, num_sorted;+    uint32_t num_key;+    JSAtomKindEnum kind;+    +    /* clear pointer for consistency in case of failure */+    *ptab = NULL;+    *plen = 0;++    /* compute the number of returned properties */+    num_keys_count = 0;+    str_keys_count = 0;+    sym_keys_count = 0;+    exotic_keys_count = 0;+    exotic_count = 0;+    tab_exotic = NULL;+    sh = p->shape;+    for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {+        atom = prs->atom;+        if (atom != JS_ATOM_NULL) {+            is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0);+            kind = JS_AtomGetKind(ctx, atom);+            if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&+                ((flags >> kind) & 1) != 0) {+                /* need to raise an exception in case of the module+                   name space (implicit GetOwnProperty) */+                if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) &&+                    (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY))) {+                    JSVarRef *var_ref = p->prop[i].u.var_ref;+                    if (unlikely(JS_IsUninitialized(*var_ref->pvalue))) {+                        JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+                        return -1;+                    }+                }+                if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {+                    num_keys_count++;+                } else if (kind == JS_ATOM_KIND_STRING) {+                    str_keys_count++;+                } else {+                    sym_keys_count++;+                }+            }+        }+    }++    if (p->is_exotic) {+        if (p->fast_array) {+            if (flags & JS_GPN_STRING_MASK) {+                num_keys_count += p->u.array.count;+            }+        } else if (p->class_id == JS_CLASS_STRING) {+            if (flags & JS_GPN_STRING_MASK) {+                num_keys_count += js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+            }+        } else {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em && em->get_own_property_names) {+                if (em->get_own_property_names(ctx, &tab_exotic, &exotic_count,+                                               JS_MKPTR(JS_TAG_OBJECT, p)))+                    return -1;+                for(i = 0; i < exotic_count; i++) {+                    atom = tab_exotic[i].atom;+                    kind = JS_AtomGetKind(ctx, atom);+                    if (((flags >> kind) & 1) != 0) {+                        is_enumerable = FALSE;+                        if (flags & (JS_GPN_SET_ENUM | JS_GPN_ENUM_ONLY)) {+                            JSPropertyDescriptor desc;+                            int res;+                            /* set the "is_enumerable" field if necessary */+                            res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);+                            if (res < 0) {+                                js_free_prop_enum(ctx, tab_exotic, exotic_count);+                                return -1;+                            }+                            if (res) {+                                is_enumerable =+                                    ((desc.flags & JS_PROP_ENUMERABLE) != 0);+                                js_free_desc(ctx, &desc);+                            }+                            tab_exotic[i].is_enumerable = is_enumerable;+                        }+                        if (!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) {+                            exotic_keys_count++;+                        }+                    }+                }+            }+        }+    }++    /* fill them */++    atom_count = num_keys_count + str_keys_count + sym_keys_count + exotic_keys_count;+    /* avoid allocating 0 bytes */+    tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1));+    if (!tab_atom) {+        js_free_prop_enum(ctx, tab_exotic, exotic_count);+        return -1;+    }++    num_index = 0;+    str_index = num_keys_count;+    sym_index = str_index + str_keys_count;++    num_sorted = TRUE;+    sh = p->shape;+    for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {+        atom = prs->atom;+        if (atom != JS_ATOM_NULL) {+            is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0);+            kind = JS_AtomGetKind(ctx, atom);+            if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&+                ((flags >> kind) & 1) != 0) {+                if (JS_AtomIsArrayIndex(ctx, &num_key, atom)) {+                    j = num_index++;+                    num_sorted = FALSE;+                } else if (kind == JS_ATOM_KIND_STRING) {+                    j = str_index++;+                } else {+                    j = sym_index++;+                }+                tab_atom[j].atom = JS_DupAtom(ctx, atom);+                tab_atom[j].is_enumerable = is_enumerable;+            }+        }+    }++    if (p->is_exotic) {+        int len;+        if (p->fast_array) {+            if (flags & JS_GPN_STRING_MASK) {+                len = p->u.array.count;+                goto add_array_keys;+            }+        } else if (p->class_id == JS_CLASS_STRING) {+            if (flags & JS_GPN_STRING_MASK) {+                len = js_string_obj_get_length(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+            add_array_keys:+                for(i = 0; i < len; i++) {+                    tab_atom[num_index].atom = __JS_AtomFromUInt32(i);+                    if (tab_atom[num_index].atom == JS_ATOM_NULL) {+                        js_free_prop_enum(ctx, tab_atom, num_index);+                        return -1;+                    }+                    tab_atom[num_index].is_enumerable = TRUE;+                    num_index++;+                }+            }+        } else {+            /* Note: exotic keys are not reordered and comes after the object own properties. */+            for(i = 0; i < exotic_count; i++) {+                atom = tab_exotic[i].atom;+                is_enumerable = tab_exotic[i].is_enumerable;+                kind = JS_AtomGetKind(ctx, atom);+                if ((!(flags & JS_GPN_ENUM_ONLY) || is_enumerable) &&+                    ((flags >> kind) & 1) != 0) {+                    tab_atom[sym_index].atom = atom;+                    tab_atom[sym_index].is_enumerable = is_enumerable;+                    sym_index++;+                } else {+                    JS_FreeAtom(ctx, atom);+                }+            }+            js_free(ctx, tab_exotic);+        }+    }++    assert(num_index == num_keys_count);+    assert(str_index == num_keys_count + str_keys_count);+    assert(sym_index == atom_count);++    if (num_keys_count != 0 && !num_sorted) {+        rqsort(tab_atom, num_keys_count, sizeof(tab_atom[0]), num_keys_cmp,+               ctx);+    }+    *ptab = tab_atom;+    *plen = atom_count;+    return 0;+}++int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,+                           uint32_t *plen, JSValueConst obj, int flags)+{+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen,+                                          JS_VALUE_GET_OBJ(obj), flags);+}++/* Return -1 if exception,+   FALSE if the property does not exist, TRUE if it exists. If TRUE is+   returned, the property descriptor 'desc' is filled present. */+static int JS_GetOwnPropertyInternal(JSContext *ctx, JSPropertyDescriptor *desc,+                                     JSObject *p, JSAtom prop)+{+    JSShapeProperty *prs;+    JSProperty *pr;++retry:+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        if (desc) {+            desc->flags = prs->flags & JS_PROP_C_W_E;+            desc->getter = JS_UNDEFINED;+            desc->setter = JS_UNDEFINED;+            desc->value = JS_UNDEFINED;+            if (unlikely(prs->flags & JS_PROP_TMASK)) {+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                    desc->flags |= JS_PROP_GETSET;+                    if (pr->u.getset.getter)+                        desc->getter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));+                    if (pr->u.getset.setter)+                        desc->setter = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                    JSValue val = *pr->u.var_ref->pvalue;+                    if (unlikely(JS_IsUninitialized(val))) {+                        JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+                        return -1;+                    }+                    desc->value = JS_DupValue(ctx, val);+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                    /* Instantiate property and retry */+                    if (JS_AutoInitProperty(ctx, p, prop, pr, prs))+                        return -1;+                    goto retry;+                }+            } else {+                desc->value = JS_DupValue(ctx, pr->u.value);+            }+        } else {+            /* for consistency, send the exception even if desc is NULL */+            if (unlikely((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF)) {+                if (unlikely(JS_IsUninitialized(*pr->u.var_ref->pvalue))) {+                    JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+                    return -1;+                }+            } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                /* nothing to do: delay instantiation until actual value and/or attributes are read */+            }+        }+        return TRUE;+    }+    if (p->is_exotic) {+        if (p->fast_array) {+            /* specific case for fast arrays */+            if (__JS_AtomIsTaggedInt(prop)) {+                uint32_t idx;+                idx = __JS_AtomToUInt32(prop);+                if (idx < p->u.array.count) {+                    if (desc) {+                        desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE |+                            JS_PROP_CONFIGURABLE;+                        desc->getter = JS_UNDEFINED;+                        desc->setter = JS_UNDEFINED;+                        desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx);+                    }+                    return TRUE;+                }+            }+        } else {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em && em->get_own_property) {+                return em->get_own_property(ctx, desc,+                                            JS_MKPTR(JS_TAG_OBJECT, p), prop);+            }+        }+    }+    return FALSE;+}++int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,+                      JSValueConst obj, JSAtom prop)+{+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    return JS_GetOwnPropertyInternal(ctx, desc, JS_VALUE_GET_OBJ(obj), prop);+}++/* return -1 if exception (Proxy object only) or TRUE/FALSE */+int JS_IsExtensible(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    if (unlikely(p->class_id == JS_CLASS_PROXY))+        return js_proxy_isExtensible(ctx, obj);+    else+        return p->extensible;+}++/* return -1 if exception (Proxy object only) or TRUE/FALSE */+int JS_PreventExtensions(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    if (unlikely(p->class_id == JS_CLASS_PROXY))+        return js_proxy_preventExtensions(ctx, obj);+    p->extensible = FALSE;+    return TRUE;+}++/* return -1 if exception otherwise TRUE or FALSE */+int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop)+{+    JSObject *p;+    int ret;+    JSValue obj1;++    if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    for(;;) {+        if (p->is_exotic) {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em && em->has_property) {+                /* has_property can free the prototype */+                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+                ret = em->has_property(ctx, obj1, prop);+                JS_FreeValue(ctx, obj1);+                return ret;+            }+        }+        /* JS_GetOwnPropertyInternal can free the prototype */+        JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+        ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop);+        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+        if (ret != 0)+            return ret;+        if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+            p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+            ret = JS_AtomIsNumericIndex(ctx, prop);+            if (ret != 0) {+                if (ret < 0)+                    return -1;+                return FALSE;+            }+        }+        p = p->shape->proto;+        if (!p)+            break;+    }+    return FALSE;+}++/* val must be a symbol */+static JSAtom js_symbol_to_atom(JSContext *ctx, JSValue val)+{+    JSAtomStruct *p = JS_VALUE_GET_PTR(val);+    return js_get_atom_index(ctx->rt, p);+}++/* return JS_ATOM_NULL in case of exception */+JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val)+{+    JSAtom atom;+    uint32_t tag;+    tag = JS_VALUE_GET_TAG(val);+    if (tag == JS_TAG_INT &&+        (uint32_t)JS_VALUE_GET_INT(val) <= JS_ATOM_MAX_INT) {+        /* fast path for integer values */+        atom = __JS_AtomFromUInt32(JS_VALUE_GET_INT(val));+    } else if (tag == JS_TAG_SYMBOL) {+        JSAtomStruct *p = JS_VALUE_GET_PTR(val);+        atom = JS_DupAtom(ctx, js_get_atom_index(ctx->rt, p));+    } else {+        JSValue str;+        str = JS_ToPropertyKey(ctx, val);+        if (JS_IsException(str))+            return JS_ATOM_NULL;+        if (JS_VALUE_GET_TAG(str) == JS_TAG_SYMBOL) {+            atom = js_symbol_to_atom(ctx, str);+        } else {+            atom = JS_NewAtomStr(ctx, JS_VALUE_GET_STRING(str));+        }+    }+    return atom;+}++static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,+                                   JSValue prop)+{+    JSAtom atom;+    JSValue ret;++    if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&+               JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {+        JSObject *p;+        uint32_t idx, len;+        /* fast path for array access */+        p = JS_VALUE_GET_OBJ(this_obj);+        idx = JS_VALUE_GET_INT(prop);+        len = (uint32_t)p->u.array.count;+        if (unlikely(idx >= len))+            goto slow_path;+        switch(p->class_id) {+        case JS_CLASS_ARRAY:+        case JS_CLASS_ARGUMENTS:+            return JS_DupValue(ctx, p->u.array.u.values[idx]);+        case JS_CLASS_INT8_ARRAY:+            return JS_NewInt32(ctx, p->u.array.u.int8_ptr[idx]);+        case JS_CLASS_UINT8C_ARRAY:+        case JS_CLASS_UINT8_ARRAY:+            return JS_NewInt32(ctx, p->u.array.u.uint8_ptr[idx]);+        case JS_CLASS_INT16_ARRAY:+            return JS_NewInt32(ctx, p->u.array.u.int16_ptr[idx]);+        case JS_CLASS_UINT16_ARRAY:+            return JS_NewInt32(ctx, p->u.array.u.uint16_ptr[idx]);+        case JS_CLASS_INT32_ARRAY:+            return JS_NewInt32(ctx, p->u.array.u.int32_ptr[idx]);+        case JS_CLASS_UINT32_ARRAY:+            return JS_NewUint32(ctx, p->u.array.u.uint32_ptr[idx]);+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT64_ARRAY:+            return JS_NewBigInt64(ctx, p->u.array.u.int64_ptr[idx]);+        case JS_CLASS_BIG_UINT64_ARRAY:+            return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);+#endif+        case JS_CLASS_FLOAT32_ARRAY:+            return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);+        case JS_CLASS_FLOAT64_ARRAY:+            return __JS_NewFloat64(ctx, p->u.array.u.double_ptr[idx]);+        default:+            goto slow_path;+        }+    } else {+    slow_path:+        atom = JS_ValueToAtom(ctx, prop);+        JS_FreeValue(ctx, prop);+        if (unlikely(atom == JS_ATOM_NULL))+            return JS_EXCEPTION;+        ret = JS_GetProperty(ctx, this_obj, atom);+        JS_FreeAtom(ctx, atom);+        return ret;+    }+}++JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,+                             uint32_t idx)+{+    return JS_GetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx));+}++/* Check if an object has a generalized numeric property. Return value:+   -1 for exception,+   TRUE if property exists, stored into *pval,+   FALSE if proprty does not exist.+ */+static int JS_TryGetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, JSValue *pval)+{+    JSValue val = JS_UNDEFINED;+    JSAtom prop;+    int present;++    if (likely((uint64_t)idx <= JS_ATOM_MAX_INT)) {+        /* fast path */+        present = JS_HasProperty(ctx, obj, __JS_AtomFromUInt32(idx));+        if (present > 0) {+            val = JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));+            if (unlikely(JS_IsException(val)))+                present = -1;+        }+    } else {+        prop = JS_NewAtomInt64(ctx, idx);+        present = -1;+        if (likely(prop != JS_ATOM_NULL)) {+            present = JS_HasProperty(ctx, obj, prop);+            if (present > 0) {+                val = JS_GetProperty(ctx, obj, prop);+                if (unlikely(JS_IsException(val)))+                    present = -1;+            }+            JS_FreeAtom(ctx, prop);+        }+    }+    *pval = val;+    return present;+}++static JSValue JS_GetPropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx)+{+    JSAtom prop;+    JSValue val;++    if ((uint64_t)idx <= INT32_MAX) {+        /* fast path for fast arrays */+        return JS_GetPropertyValue(ctx, obj, JS_NewInt32(ctx, idx));+    }+    prop = JS_NewAtomInt64(ctx, idx);+    if (prop == JS_ATOM_NULL)+        return JS_EXCEPTION;++    val = JS_GetProperty(ctx, obj, prop);+    JS_FreeAtom(ctx, prop);+    return val;+}++JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,+                          const char *prop)+{+    JSAtom atom;+    JSValue ret;+    atom = JS_NewAtom(ctx, prop);+    ret = JS_GetProperty(ctx, this_obj, atom);+    JS_FreeAtom(ctx, atom);+    return ret;+}++/* Note: the property value is not initialized. Return NULL if memory+   error. */+static JSProperty *add_property(JSContext *ctx,+                                JSObject *p, JSAtom prop, int prop_flags)+{+    JSShape *sh, *new_sh;++    sh = p->shape;+    if (sh->is_hashed) {+        /* try to find an existing shape */+        new_sh = find_hashed_shape_prop(ctx->rt, sh, prop, prop_flags);+        if (new_sh) {+            /* matching shape found: use it */+            /*  the property array may need to be resized */+            if (new_sh->prop_size != sh->prop_size) {+                JSProperty *new_prop;+                new_prop = js_realloc(ctx, p->prop, sizeof(p->prop[0]) *+                                      new_sh->prop_size);+                if (!new_prop)+                    return NULL;+                p->prop = new_prop;+            }+            p->shape = js_dup_shape(new_sh);+            js_free_shape(ctx->rt, sh);+            return &p->prop[new_sh->prop_count - 1];+        } else if (sh->header.ref_count != 1) {+            /* if the shape is shared, clone it */+            new_sh = js_clone_shape(ctx, sh);+            if (!new_sh)+                return NULL;+            /* hash the cloned shape */+            new_sh->is_hashed = TRUE;+            js_shape_hash_link(ctx->rt, new_sh);+            js_free_shape(ctx->rt, p->shape);+            p->shape = new_sh;+        }+    }+    assert(p->shape->header.ref_count == 1);+    if (add_shape_property(ctx, &p->shape, p, prop, prop_flags))+        return NULL;+    return &p->prop[p->shape->prop_count - 1];+}++/* can be called on Array or Arguments objects. return < 0 if+   memory alloc error. */+static no_inline __exception int convert_fast_array_to_array(JSContext *ctx,+                                                             JSObject *p)+{+    JSProperty *pr;+    JSShape *sh;+    JSValue *tab;+    uint32_t i, len, new_count;++    if (js_shape_prepare_update(ctx, p, NULL))+        return -1;+    len = p->u.array.count;+    /* resize the properties once to simplify the error handling */+    sh = p->shape;+    new_count = sh->prop_count + len;+    if (new_count > sh->prop_size) {+        if (resize_properties(ctx, &p->shape, p, new_count))+            return -1;+    }++    tab = p->u.array.u.values;+    for(i = 0; i < len; i++) {+        /* add_property cannot fail here but+           __JS_AtomFromUInt32(i) fails for i > INT32_MAX */+        pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E);+        pr->u.value = *tab++;+    }+    js_free(ctx, p->u.array.u.values);+    p->u.array.count = 0;+    p->u.array.u.values = NULL; /* fail safe */+    p->u.array.u1.size = 0;+    p->fast_array = 0;+    return 0;+}++static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom)+{+    JSShape *sh;+    JSShapeProperty *pr, *lpr, *prop;+    JSProperty *pr1;+    uint32_t lpr_idx;+    intptr_t h, h1;++ redo:+    sh = p->shape;+    h1 = atom & sh->prop_hash_mask;+    h = prop_hash_end(sh)[-h1 - 1];+    prop = get_shape_prop(sh);+    lpr = NULL;+    lpr_idx = 0;   /* prevent warning */+    while (h != 0) {+        pr = &prop[h - 1];+        if (likely(pr->atom == atom)) {+            /* found ! */+            if (!(pr->flags & JS_PROP_CONFIGURABLE))+                return FALSE;+            /* realloc the shape if needed */+            if (lpr)+                lpr_idx = lpr - get_shape_prop(sh);+            if (js_shape_prepare_update(ctx, p, &pr))+                return -1;+            sh = p->shape;+            /* remove property */+            if (lpr) {+                lpr = get_shape_prop(sh) + lpr_idx;+                lpr->hash_next = pr->hash_next;+            } else {+                prop_hash_end(sh)[-h1 - 1] = pr->hash_next;+            }+            sh->deleted_prop_count++;+            /* free the entry */+            pr1 = &p->prop[h - 1];+            free_property(ctx->rt, pr1, pr->flags);+            JS_FreeAtom(ctx, pr->atom);+            /* put default values */+            pr->flags = 0;+            pr->atom = JS_ATOM_NULL;+            pr1->u.value = JS_UNDEFINED;++            /* compact the properties if too many deleted properties */+            if (sh->deleted_prop_count >= 8 &&+                sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) {+                compact_properties(ctx, p);+            }+            return TRUE;+        }+        lpr = pr;+        h = pr->hash_next;+    }++    if (p->is_exotic) {+        if (p->fast_array) {+            uint32_t idx;+            if (JS_AtomIsArrayIndex(ctx, &idx, atom) &&+                idx < p->u.array.count) {+                if (p->class_id == JS_CLASS_ARRAY ||+                    p->class_id == JS_CLASS_ARGUMENTS) {+                    /* Special case deleting the last element of a fast Array */+                    if (idx == p->u.array.count - 1) {+                        JS_FreeValue(ctx, p->u.array.u.values[idx]);+                        p->u.array.count = idx;+                        return TRUE;+                    }+                    if (convert_fast_array_to_array(ctx, p))+                        return -1;+                    goto redo;+                } else {+                    return FALSE;+                }+            }+        } else {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em && em->delete_property) {+                return em->delete_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), atom);+            }+        }+    }+    /* not found */+    return TRUE;+}++static int call_setter(JSContext *ctx, JSObject *setter,+                       JSValueConst this_obj, JSValue val, int flags)+{+    JSValue ret, func;+    if (likely(setter)) {+        func = JS_MKPTR(JS_TAG_OBJECT, setter);+        /* Note: the field could be removed in the setter */+        func = JS_DupValue(ctx, func);+        ret = JS_CallFree(ctx, func, this_obj, 1, (JSValueConst *)&val);+        JS_FreeValue(ctx, val);+        if (JS_IsException(ret))+            return -1;+        JS_FreeValue(ctx, ret);+        return TRUE;+    } else {+        JS_FreeValue(ctx, val);+        if ((flags & JS_PROP_THROW) ||+            ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {+            JS_ThrowTypeError(ctx, "no setter for property");+            return -1;+        }+        return FALSE;+    }+}++/* set the array length and remove the array elements if necessary. */+static int set_array_length(JSContext *ctx, JSObject *p, JSValue val,+                            int flags)+{+    uint32_t len, idx, cur_len;+    int i, ret;++    /* Note: this call can reallocate the properties of 'p' */+    ret = JS_ToArrayLengthFree(ctx, &len, val, FALSE);+    if (ret)+        return -1;+    /* JS_ToArrayLengthFree() must be done before the read-only test */+    if (unlikely(!(p->shape->prop[0].flags & JS_PROP_WRITABLE)))+        return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);++    if (likely(p->fast_array)) {+        uint32_t old_len = p->u.array.count;+        if (len < old_len) {+            for(i = len; i < old_len; i++) {+                JS_FreeValue(ctx, p->u.array.u.values[i]);+            }+            p->u.array.count = len;+        }+        p->prop[0].u.value = JS_NewUint32(ctx, len);+    } else {+        /* Note: length is always a uint32 because the object is an+           array */+        JS_ToUint32(ctx, &cur_len, p->prop[0].u.value);+        if (len < cur_len) {+            uint32_t d;+            JSShape *sh;+            JSShapeProperty *pr;++            d = cur_len - len;+            sh = p->shape;+            if (d <= sh->prop_count) {+                JSAtom atom;++                /* faster to iterate */+                while (cur_len > len) {+                    atom = JS_NewAtomUInt32(ctx, cur_len - 1);+                    ret = delete_property(ctx, p, atom);+                    JS_FreeAtom(ctx, atom);+                    if (unlikely(!ret)) {+                        /* unlikely case: property is not+                           configurable */+                        break;+                    }+                    cur_len--;+                }+            } else {+                /* faster to iterate thru all the properties. Need two+                   passes in case one of the property is not+                   configurable */+                cur_len = len;+                for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count;+                    i++, pr++) {+                    if (pr->atom != JS_ATOM_NULL &&+                        JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) {+                        if (idx >= cur_len &&+                            !(pr->flags & JS_PROP_CONFIGURABLE)) {+                            cur_len = idx + 1;+                        }+                    }+                }++                for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count;+                    i++, pr++) {+                    if (pr->atom != JS_ATOM_NULL &&+                        JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) {+                        if (idx >= cur_len) {+                            /* remove the property */+                            delete_property(ctx, p, pr->atom);+                            /* WARNING: the shape may have been modified */+                            sh = p->shape;+                            pr = get_shape_prop(sh) + i;+                        }+                    }+                }+            }+        } else {+            cur_len = len;+        }+        set_value(ctx, &p->prop[0].u.value, JS_NewUint32(ctx, cur_len));+        if (unlikely(cur_len > len)) {+            return JS_ThrowTypeErrorOrFalse(ctx, flags, "not configurable");+        }+    }+    return TRUE;+}++/* Preconditions: 'p' must be of class JS_CLASS_ARRAY, p->fast_array =+   TRUE and p->extensible = TRUE */+static int add_fast_array_element(JSContext *ctx, JSObject *p,+                                  JSValue val, int flags)+{+    uint32_t new_len, array_len;+    /* extend the array by one */+    /* XXX: convert to slow array if new_len > 2^31-1 elements */+    new_len = p->u.array.count + 1;+    /* update the length if necessary. We assume that if the length is+       not an integer, then if it >= 2^31.  */+    if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) {+        array_len = JS_VALUE_GET_INT(p->prop[0].u.value);+        if (new_len > array_len) {+            if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) {+                JS_FreeValue(ctx, val);+                return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);+            }+            p->prop[0].u.value = JS_NewInt32(ctx, new_len);+        }+    }+    if (unlikely(new_len > p->u.array.u1.size)) {+        uint32_t new_size;+        size_t slack;+        JSValue *new_array_prop;+        /* XXX: potential arithmetic overflow */+        new_size = max_int(new_len, p->u.array.u1.size * 3 / 2);+        new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack);+        if (!new_array_prop) {+            JS_FreeValue(ctx, val);+            return -1;+        }+        new_size += slack / sizeof(*new_array_prop);+        p->u.array.u.values = new_array_prop;+        p->u.array.u1.size = new_size;+    }+    p->u.array.u.values[new_len - 1] = val;+    p->u.array.count = new_len;+    return TRUE;+}++static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)+{+    JS_FreeValue(ctx, desc->getter);+    JS_FreeValue(ctx, desc->setter);+    JS_FreeValue(ctx, desc->value);+}++/* generic (and slower) version of JS_SetProperty() for Reflect.set() */+static int JS_SetPropertyGeneric(JSContext *ctx,+                                 JSObject *p, JSAtom prop,+                                 JSValue val, JSValueConst this_obj,+                                 int flags)+{+    int ret;+    JSPropertyDescriptor desc;++    while (p != NULL) {+        if (p->is_exotic) {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em && em->set_property) {+                JSValue obj1;+                /* set_property can free the prototype */+                obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+                ret = em->set_property(ctx, obj1, prop,+                                       val, this_obj, flags);+                JS_FreeValue(ctx, obj1);+                JS_FreeValue(ctx, val);+                return ret;+            }+        }++        ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);+        if (ret < 0)+            return ret;+        if (ret) {+            if (desc.flags & JS_PROP_GETSET) {+                JSObject *setter;+                if (JS_IsUndefined(desc.setter))+                    setter = NULL;+                else+                    setter = JS_VALUE_GET_OBJ(desc.setter);+                ret = call_setter(ctx, setter, this_obj, val, flags);+                JS_FreeValue(ctx, desc.getter);+                JS_FreeValue(ctx, desc.setter);+                return ret;+            } else {+                JS_FreeValue(ctx, desc.value);+                if (!(desc.flags & JS_PROP_WRITABLE)) {+                    goto read_only_error;+                }+            }+            break;+        }+        p = p->shape->proto;+    }++    if (!JS_IsObject(this_obj))+        return JS_ThrowTypeErrorOrFalse(ctx, flags, "receiver is not an object");++    p = JS_VALUE_GET_OBJ(this_obj);++    /* modify the property in this_obj if it already exists */+    ret = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);+    if (ret < 0)+        return ret;+    if (ret) {+        if (desc.flags & JS_PROP_GETSET) {+            JS_FreeValue(ctx, desc.getter);+            JS_FreeValue(ctx, desc.setter);+            JS_FreeValue(ctx, val);+            return JS_ThrowTypeErrorOrFalse(ctx, flags, "setter is forbidden");+        } else {+            JS_FreeValue(ctx, desc.value);+            if (!(desc.flags & JS_PROP_WRITABLE) ||+                p->class_id == JS_CLASS_MODULE_NS) {+            read_only_error:+                JS_FreeValue(ctx, val);+                return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);+            }+        }+        ret = JS_DefineProperty(ctx, this_obj, prop, val,+                                JS_UNDEFINED, JS_UNDEFINED,+                                JS_PROP_HAS_VALUE);+        JS_FreeValue(ctx, val);+        return ret;+    }++    ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,+                            flags |+                            JS_PROP_HAS_VALUE |+                            JS_PROP_HAS_ENUMERABLE |+                            JS_PROP_HAS_WRITABLE |+                            JS_PROP_HAS_CONFIGURABLE |+                            JS_PROP_C_W_E);+    JS_FreeValue(ctx, val);+    return ret;+}++/* return -1 in case of exception or TRUE or FALSE. Warning: 'val' is+   freed by the function. 'flags' is a bitmask of JS_PROP_NO_ADD,+   JS_PROP_THROW or JS_PROP_THROW_STRICT. If JS_PROP_NO_ADD is set,+   the new property is not added and an error is raised. */+int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,+                           JSAtom prop, JSValue val, int flags)+{+    JSObject *p, *p1;+    JSShapeProperty *prs;+    JSProperty *pr;+    uint32_t tag;+    JSPropertyDescriptor desc;+    int ret;+#if 0+    printf("JS_SetPropertyInternal: "); print_atom(ctx, prop); printf("\n");+#endif+    tag = JS_VALUE_GET_TAG(this_obj);+    if (unlikely(tag != JS_TAG_OBJECT)) {+        switch(tag) {+        case JS_TAG_NULL:+            JS_FreeValue(ctx, val);+            JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop);+            return -1;+        case JS_TAG_UNDEFINED:+            JS_FreeValue(ctx, val);+            JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop);+            return -1;+        default:+            /* even on a primitive type we can have setters on the prototype */+            p = NULL;+            p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj));+            goto prototype_lookup;+        }+    }+    p = JS_VALUE_GET_OBJ(this_obj);+retry:+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |+                                  JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {+            /* fast case */+            set_value(ctx, &pr->u.value, val);+            return TRUE;+        } else if (prs->flags & JS_PROP_LENGTH) {+            assert(p->class_id == JS_CLASS_ARRAY);+            assert(prop == JS_ATOM_length);+            return set_array_length(ctx, p, val, flags);+        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+            return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);+        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+            /* JS_PROP_WRITABLE is always true for variable+               references, but they are write protected in module name+               spaces. */+            if (p->class_id == JS_CLASS_MODULE_NS)+                goto read_only_prop;+            set_value(ctx, pr->u.var_ref->pvalue, val);+            return TRUE;+        } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+            /* Instantiate property and retry (potentially useless) */+            if (JS_AutoInitProperty(ctx, p, prop, pr, prs)) {+                JS_FreeValue(ctx, val);+                return -1;+            }+            goto retry;+        } else {+            goto read_only_prop;+        }+    }++    p1 = p;+    for(;;) {+        if (p1->is_exotic) {+            if (p1->fast_array) {+                if (__JS_AtomIsTaggedInt(prop)) {+                    uint32_t idx = __JS_AtomToUInt32(prop);+                    if (idx < p1->u.array.count) {+                        if (unlikely(p == p1))+                            return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val, flags);+                        else+                            break;+                    } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&+                               p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {+                        goto typed_array_oob;+                    }+                } else if (p1->class_id >= JS_CLASS_UINT8C_ARRAY &&+                           p1->class_id <= JS_CLASS_FLOAT64_ARRAY) {+                    ret = JS_AtomIsNumericIndex(ctx, prop);+                    if (ret != 0) {+                        if (ret < 0) {+                            JS_FreeValue(ctx, val);+                            return -1;+                        }+                    typed_array_oob:+                        val = JS_ToNumberFree(ctx, val);+                        JS_FreeValue(ctx, val);+                        if (JS_IsException(val))+                            return -1;+                        return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");+                    }+                }+            } else {+                const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic;+                if (em) {+                    JSValue obj1;+                    if (em->set_property) {+                        /* set_property can free the prototype */+                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));+                        ret = em->set_property(ctx, obj1, prop,+                                               val, this_obj, flags);+                        JS_FreeValue(ctx, obj1);+                        JS_FreeValue(ctx, val);+                        return ret;+                    }+                    if (em->get_own_property) {+                        /* get_own_property can free the prototype */+                        obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));+                        ret = em->get_own_property(ctx, &desc,+                                                   obj1, prop);+                        JS_FreeValue(ctx, obj1);+                        if (ret < 0) {+                            JS_FreeValue(ctx, val);+                            return ret;+                        }+                        if (ret) {+                            if (desc.flags & JS_PROP_GETSET) {+                                JSObject *setter;+                                if (JS_IsUndefined(desc.setter))+                                    setter = NULL;+                                else+                                    setter = JS_VALUE_GET_OBJ(desc.setter);+                                ret = call_setter(ctx, setter, this_obj, val, flags);+                                JS_FreeValue(ctx, desc.getter);+                                JS_FreeValue(ctx, desc.setter);+                                return ret;+                            } else {+                                JS_FreeValue(ctx, desc.value);+                                if (!(desc.flags & JS_PROP_WRITABLE))+                                    goto read_only_prop;+                                if (likely(p == p1)) {+                                    ret = JS_DefineProperty(ctx, this_obj, prop, val,+                                                            JS_UNDEFINED, JS_UNDEFINED,+                                                            JS_PROP_HAS_VALUE);+                                    JS_FreeValue(ctx, val);+                                    return ret;+                                } else {+                                    break;+                                }+                            }+                        }+                    }+                }+            }+        }+        p1 = p1->shape->proto;+    prototype_lookup:+        if (!p1)+            break;++    retry2:+        prs = find_own_property(&pr, p1, prop);+        if (prs) {+            if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                return call_setter(ctx, pr->u.getset.setter, this_obj, val, flags);+            } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                /* Instantiate property and retry (potentially useless) */+                if (JS_AutoInitProperty(ctx, p1, prop, pr, prs))+                    return -1;+                goto retry2;+            } else if (!(prs->flags & JS_PROP_WRITABLE)) {+            read_only_prop:+                JS_FreeValue(ctx, val);+                return JS_ThrowTypeErrorReadOnly(ctx, flags, prop);+            }+        }+    }++    if (unlikely(flags & JS_PROP_NO_ADD)) {+        JS_FreeValue(ctx, val);+        JS_ThrowReferenceErrorNotDefined(ctx, prop);+        return -1;+    }++    if (unlikely(!p)) {+        JS_FreeValue(ctx, val);+        return JS_ThrowTypeErrorOrFalse(ctx, flags, "not an object");+    }++    if (unlikely(!p->extensible)) {+        JS_FreeValue(ctx, val);+        return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");+    }++    if (p->is_exotic) {+        if (p->class_id == JS_CLASS_ARRAY && p->fast_array &&+            __JS_AtomIsTaggedInt(prop)) {+            uint32_t idx = __JS_AtomToUInt32(prop);+            if (idx == p->u.array.count) {+                /* fast case */+                return add_fast_array_element(ctx, p, val, flags);+            } else {+                goto generic_create_prop;+            }+        } else {+        generic_create_prop:+            ret = JS_CreateProperty(ctx, p, prop, val, JS_UNDEFINED, JS_UNDEFINED,+                                    flags |+                                    JS_PROP_HAS_VALUE |+                                    JS_PROP_HAS_ENUMERABLE |+                                    JS_PROP_HAS_WRITABLE |+                                    JS_PROP_HAS_CONFIGURABLE |+                                    JS_PROP_C_W_E);+            JS_FreeValue(ctx, val);+            return ret;+        }+    }++    pr = add_property(ctx, p, prop, JS_PROP_C_W_E);+    if (unlikely(!pr)) {+        JS_FreeValue(ctx, val);+        return -1;+    }+    pr->u.value = val;+    return TRUE;+}++/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */+static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,+                               JSValue prop, JSValue val, int flags)+{+    if (likely(JS_VALUE_GET_TAG(this_obj) == JS_TAG_OBJECT &&+               JS_VALUE_GET_TAG(prop) == JS_TAG_INT)) {+        JSObject *p;+        uint32_t idx;+        double d;+        int32_t v;++        /* fast path for array access */+        p = JS_VALUE_GET_OBJ(this_obj);+        idx = JS_VALUE_GET_INT(prop);+        switch(p->class_id) {+        case JS_CLASS_ARRAY:+            if (unlikely(idx >= (uint32_t)p->u.array.count)) {+                JSObject *p1;+                JSShape *sh1;++                /* fast path to add an element to the array */+                if (idx != (uint32_t)p->u.array.count ||+                    !p->fast_array || !p->extensible)+                    goto slow_path;+                /* check if prototype chain has a numeric property */+                p1 = p->shape->proto;+                while (p1 != NULL) {+                    sh1 = p1->shape;+                    if (p1->class_id == JS_CLASS_ARRAY) {+                        if (unlikely(!p1->fast_array))+                            goto slow_path;+                    } else if (p1->class_id == JS_CLASS_OBJECT) {+                        if (unlikely(sh1->has_small_array_index))+                            goto slow_path;+                    } else {+                        goto slow_path;+                    }+                    p1 = sh1->proto;+                }+                /* add element */+                return add_fast_array_element(ctx, p, val, flags);+            }+            set_value(ctx, &p->u.array.u.values[idx], val);+            break;+        case JS_CLASS_ARGUMENTS:+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto slow_path;+            set_value(ctx, &p->u.array.u.values[idx], val);+            break;+        case JS_CLASS_UINT8C_ARRAY:+            if (JS_ToUint8ClampFree(ctx, &v, val))+                return -1;+            /* Note: the conversion can detach the typed array, so the+               array bound check must be done after */+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto ta_out_of_bound;+            p->u.array.u.uint8_ptr[idx] = v;+            break;+        case JS_CLASS_INT8_ARRAY:+        case JS_CLASS_UINT8_ARRAY:+            if (JS_ToInt32Free(ctx, &v, val))+                return -1;+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto ta_out_of_bound;+            p->u.array.u.uint8_ptr[idx] = v;+            break;+        case JS_CLASS_INT16_ARRAY:+        case JS_CLASS_UINT16_ARRAY:+            if (JS_ToInt32Free(ctx, &v, val))+                return -1;+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto ta_out_of_bound;+            p->u.array.u.uint16_ptr[idx] = v;+            break;+        case JS_CLASS_INT32_ARRAY:+        case JS_CLASS_UINT32_ARRAY:+            if (JS_ToInt32Free(ctx, &v, val))+                return -1;+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto ta_out_of_bound;+            p->u.array.u.uint32_ptr[idx] = v;+            break;+#ifdef CONFIG_BIGNUM+        case JS_CLASS_BIG_INT64_ARRAY:+        case JS_CLASS_BIG_UINT64_ARRAY:+            /* XXX: need specific conversion function */+            {+                int64_t v;+                if (JS_ToBigInt64Free(ctx, &v, val))+                    return -1;+                if (unlikely(idx >= (uint32_t)p->u.array.count))+                    goto ta_out_of_bound;+                p->u.array.u.uint64_ptr[idx] = v;+            }+            break;+#endif+        case JS_CLASS_FLOAT32_ARRAY:+            if (JS_ToFloat64Free(ctx, &d, val))+                return -1;+            if (unlikely(idx >= (uint32_t)p->u.array.count))+                goto ta_out_of_bound;+            p->u.array.u.float_ptr[idx] = d;+            break;+        case JS_CLASS_FLOAT64_ARRAY:+            if (JS_ToFloat64Free(ctx, &d, val))+                return -1;+            if (unlikely(idx >= (uint32_t)p->u.array.count)) {+            ta_out_of_bound:+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound numeric index");+            }+            p->u.array.u.double_ptr[idx] = d;+            break;+        default:+            goto slow_path;+        }+        return TRUE;+    } else {+        JSAtom atom;+        int ret;+    slow_path:+        atom = JS_ValueToAtom(ctx, prop);+        JS_FreeValue(ctx, prop);+        if (unlikely(atom == JS_ATOM_NULL)) {+            JS_FreeValue(ctx, val);+            return -1;+        }+        ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, flags);+        JS_FreeAtom(ctx, atom);+        return ret;+    }+}++int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,+                         uint32_t idx, JSValue val)+{+    return JS_SetPropertyValue(ctx, this_obj, JS_NewUint32(ctx, idx), val,+                               JS_PROP_THROW);+}++int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,+                        int64_t idx, JSValue val)+{+    JSAtom prop;+    int res;++    if ((uint64_t)idx <= INT32_MAX) {+        /* fast path for fast arrays */+        return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), val,+                                   JS_PROP_THROW);+    }+    prop = JS_NewAtomInt64(ctx, idx);+    if (prop == JS_ATOM_NULL) {+        JS_FreeValue(ctx, val);+        return -1;+    }+    res = JS_SetProperty(ctx, this_obj, prop, val);+    JS_FreeAtom(ctx, prop);+    return res;+}++int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,+                      const char *prop, JSValue val)+{+    JSAtom atom;+    int ret;+    atom = JS_NewAtom(ctx, prop);+    ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, JS_PROP_THROW);+    JS_FreeAtom(ctx, atom);+    return ret;+}++/* compute the property flags. For each flag: (JS_PROP_HAS_x forces+   it, otherwise def_flags is used)+   Note: makes assumption about the bit pattern of the flags+*/+static int get_prop_flags(int flags, int def_flags)+{+    int mask;+    mask = (flags >> JS_PROP_HAS_SHIFT) & JS_PROP_C_W_E;+    return (flags & mask) | (def_flags & ~mask);+}++static int JS_CreateProperty(JSContext *ctx, JSObject *p,+                             JSAtom prop, JSValueConst val,+                             JSValueConst getter, JSValueConst setter,+                             int flags)+{+    JSProperty *pr;+    int ret, prop_flags;++    /* add a new property or modify an existing exotic one */+    if (p->is_exotic) {+        if (p->class_id == JS_CLASS_ARRAY) {+            uint32_t idx, len;++            if (p->fast_array) {+                if (__JS_AtomIsTaggedInt(prop)) {+                    idx = __JS_AtomToUInt32(prop);+                    if (idx == p->u.array.count) {+                        if (!p->extensible)+                            goto not_extensible;+                        if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET))+                            goto convert_to_array;+                        prop_flags = get_prop_flags(flags, 0);+                        if (prop_flags != JS_PROP_C_W_E)+                            goto convert_to_array;+                        return add_fast_array_element(ctx, p,+                                                      JS_DupValue(ctx, val), flags);+                    } else {+                        goto convert_to_array;+                    }+                } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) {+                    /* convert the fast array to normal array */+                convert_to_array:+                    if (convert_fast_array_to_array(ctx, p))+                        return -1;+                    goto generic_array;+                }+            } else if (JS_AtomIsArrayIndex(ctx, &idx, prop)) {+                JSProperty *plen;+                JSShapeProperty *pslen;+            generic_array:+                /* update the length field */+                plen = &p->prop[0];+                JS_ToUint32(ctx, &len, plen->u.value);+                if ((idx + 1) > len) {+                    pslen = get_shape_prop(p->shape);+                    if (unlikely(!(pslen->flags & JS_PROP_WRITABLE)))+                        return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length);+                    /* XXX: should update the length after defining+                       the property */+                    len = idx + 1;+                    set_value(ctx, &plen->u.value, JS_NewUint32(ctx, len));+                }+            }+        } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+                   p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+            ret = JS_AtomIsNumericIndex(ctx, prop);+            if (ret != 0) {+                if (ret < 0)+                    return -1;+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "cannot create numeric index in typed array");+            }+        } else if (!(flags & JS_PROP_NO_EXOTIC)) {+            const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic;+            if (em) {+                if (em->define_own_property) {+                    return em->define_own_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p),+                                                   prop, val, getter, setter, flags);+                }+                ret = JS_IsExtensible(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+                if (ret < 0)+                    return -1;+                if (!ret)+                    goto not_extensible;+            }+        }+    }++    if (!p->extensible) {+    not_extensible:+        return JS_ThrowTypeErrorOrFalse(ctx, flags, "object is not extensible");+    }++    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+        prop_flags = (flags & (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) |+            JS_PROP_GETSET;+    } else {+        prop_flags = flags & JS_PROP_C_W_E;+    }+    pr = add_property(ctx, p, prop, prop_flags);+    if (unlikely(!pr))+        return -1;+    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+        pr->u.getset.getter = NULL;+        if ((flags & JS_PROP_HAS_GET) && JS_IsFunction(ctx, getter)) {+            pr->u.getset.getter =+                JS_VALUE_GET_OBJ(JS_DupValue(ctx, getter));+        }+        pr->u.getset.setter = NULL;+        if ((flags & JS_PROP_HAS_SET) && JS_IsFunction(ctx, setter)) {+            pr->u.getset.setter =+                JS_VALUE_GET_OBJ(JS_DupValue(ctx, setter));+        }+    } else {+        if (flags & JS_PROP_HAS_VALUE) {+            pr->u.value = JS_DupValue(ctx, val);+        } else {+            pr->u.value = JS_UNDEFINED;+        }+    }+    return TRUE;+}++/* return FALSE if not OK */+static BOOL check_define_prop_flags(int prop_flags, int flags)+{+    BOOL has_accessor, is_getset;++    if (!(prop_flags & JS_PROP_CONFIGURABLE)) {+        if ((flags & (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) ==+            (JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE)) {+            return FALSE;+        }+        if ((flags & JS_PROP_HAS_ENUMERABLE) &&+            (flags & JS_PROP_ENUMERABLE) != (prop_flags & JS_PROP_ENUMERABLE))+            return FALSE;+    }+    if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |+                 JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+        if (!(prop_flags & JS_PROP_CONFIGURABLE)) {+            has_accessor = ((flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) != 0);+            is_getset = ((prop_flags & JS_PROP_TMASK) == JS_PROP_GETSET);+            if (has_accessor != is_getset)+                return FALSE;+            if (!has_accessor && !is_getset && !(prop_flags & JS_PROP_WRITABLE)) {+                /* not writable: cannot set the writable bit */+                if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==+                    (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE))+                    return FALSE;+            }+        }+    }+    return TRUE;+}++/* ensure that the shape can be safely modified */+static int js_shape_prepare_update(JSContext *ctx, JSObject *p,+                                   JSShapeProperty **pprs)+{+    JSShape *sh;+    uint32_t idx = 0;    /* prevent warning */++    sh = p->shape;+    if (sh->is_hashed) {+        if (sh->header.ref_count != 1) {+            if (pprs)+                idx = *pprs - get_shape_prop(sh);+            /* clone the shape (the resulting one is no longer hashed) */+            sh = js_clone_shape(ctx, sh);+            if (!sh)+                return -1;+            js_free_shape(ctx->rt, p->shape);+            p->shape = sh;+            if (pprs)+                *pprs = get_shape_prop(sh) + idx;+        } else {+            js_shape_hash_unlink(ctx->rt, sh);+            sh->is_hashed = FALSE;+        }+    }+    return 0;+}++static int js_update_property_flags(JSContext *ctx, JSObject *p,+                                    JSShapeProperty **pprs, int flags)+{+    if (flags != (*pprs)->flags) {+        if (js_shape_prepare_update(ctx, p, pprs))+            return -1;+        (*pprs)->flags = flags;+    }+    return 0;+}++/* allowed flags:+   JS_PROP_CONFIGURABLE, JS_PROP_WRITABLE, JS_PROP_ENUMERABLE+   JS_PROP_HAS_GET, JS_PROP_HAS_SET, JS_PROP_HAS_VALUE,+   JS_PROP_HAS_CONFIGURABLE, JS_PROP_HAS_WRITABLE, JS_PROP_HAS_ENUMERABLE,+   JS_PROP_THROW, JS_PROP_NO_EXOTIC.+   If JS_PROP_THROW is set, return an exception instead of FALSE.+   if JS_PROP_NO_EXOTIC is set, do not call the exotic+   define_own_property callback.+   return -1 (exception), FALSE or TRUE.+*/+int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,+                      JSAtom prop, JSValueConst val,+                      JSValueConst getter, JSValueConst setter, int flags)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    int mask, res;++    if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    p = JS_VALUE_GET_OBJ(this_obj);++ redo_prop_update:+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        /* the range of the Array length property is always tested before */+        if ((prs->flags & JS_PROP_LENGTH) && (flags & JS_PROP_HAS_VALUE)) {+            uint32_t array_length;+            if (JS_ToArrayLengthFree(ctx, &array_length,+                                     JS_DupValue(ctx, val), FALSE)) {+                return -1;+            }+            /* this code relies on the fact that Uint32 are never allocated */+            val = (JSValueConst)JS_NewUint32(ctx, array_length);+            /* prs may have been modified */+            prs = find_own_property(&pr, p, prop);+            assert(prs != NULL);+        }+        /* property already exists */+        if (!check_define_prop_flags(prs->flags, flags)) {+        not_configurable:+            return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");+        }++        if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+            /* Instantiate property and retry */+            if (JS_AutoInitProperty(ctx, p, prop, pr, prs))+                return -1;+            goto redo_prop_update;+        }++        if (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE |+                     JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+            if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+                JSObject *new_getter, *new_setter;++                if (JS_IsFunction(ctx, getter)) {+                    new_getter = JS_VALUE_GET_OBJ(getter);+                } else {+                    new_getter = NULL;+                }+                if (JS_IsFunction(ctx, setter)) {+                    new_setter = JS_VALUE_GET_OBJ(setter);+                } else {+                    new_setter = NULL;+                }++                if ((prs->flags & JS_PROP_TMASK) != JS_PROP_GETSET) {+                    if (js_shape_prepare_update(ctx, p, &prs))+                        return -1;+                    /* convert to getset */+                    if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                        free_var_ref(ctx->rt, pr->u.var_ref);+                    } else {+                        JS_FreeValue(ctx, pr->u.value);+                    }+                    prs->flags = (prs->flags &+                                  (JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE)) |+                        JS_PROP_GETSET;+                    pr->u.getset.getter = NULL;+                    pr->u.getset.setter = NULL;+                } else {+                    if (!(prs->flags & JS_PROP_CONFIGURABLE)) {+                        if ((flags & JS_PROP_HAS_GET) &&+                            new_getter != pr->u.getset.getter) {+                            goto not_configurable;+                        }+                        if ((flags & JS_PROP_HAS_SET) &&+                            new_setter != pr->u.getset.setter) {+                            goto not_configurable;+                        }+                    }+                }+                if (flags & JS_PROP_HAS_GET) {+                    if (pr->u.getset.getter)+                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));+                    if (new_getter)+                        JS_DupValue(ctx, getter);+                    pr->u.getset.getter = new_getter;+                }+                if (flags & JS_PROP_HAS_SET) {+                    if (pr->u.getset.setter)+                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));+                    if (new_setter)+                        JS_DupValue(ctx, setter);+                    pr->u.getset.setter = new_setter;+                }+            } else {+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                    /* convert to data descriptor */+                    if (js_shape_prepare_update(ctx, p, &prs))+                        return -1;+                    if (pr->u.getset.getter)+                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.getter));+                    if (pr->u.getset.setter)+                        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, pr->u.getset.setter));+                    prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);+                    pr->u.value = JS_UNDEFINED;+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                    /* Note: JS_PROP_VARREF is always writable */+                } else {+                    if ((prs->flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 &&+                        (flags & JS_PROP_HAS_VALUE)) {+                        if (!js_same_value(ctx, val, pr->u.value)) {+                            goto not_configurable;+                        } else {+                            return TRUE;+                        }+                    }+                }+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                    if (flags & JS_PROP_HAS_VALUE) {+                        if (p->class_id == JS_CLASS_MODULE_NS) {+                            /* JS_PROP_WRITABLE is always true for variable+                               references, but they are write protected in module name+                               spaces. */+                            if (!js_same_value(ctx, val, *pr->u.var_ref->pvalue))+                                goto not_configurable;+                        }+                        /* update the reference */+                        set_value(ctx, pr->u.var_ref->pvalue,+                                  JS_DupValue(ctx, val));+                    }+                    /* if writable is set to false, no longer a+                       reference (for mapped arguments) */+                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) {+                        JSValue val1;+                        if (js_shape_prepare_update(ctx, p, &prs))+                            return -1;+                        val1 = JS_DupValue(ctx, *pr->u.var_ref->pvalue);+                        free_var_ref(ctx->rt, pr->u.var_ref);+                        pr->u.value = val1;+                        prs->flags &= ~(JS_PROP_TMASK | JS_PROP_WRITABLE);+                    }+                } else if (prs->flags & JS_PROP_LENGTH) {+                    if (flags & JS_PROP_HAS_VALUE) {+                        /* Note: no JS code is executable because+                           'val' is guaranted to be a Uint32 */+                        res = set_array_length(ctx, p, JS_DupValue(ctx, val),+                                               flags);+                    } else {+                        res = TRUE;+                    }+                    /* still need to reset the writable flag if+                       needed.  The JS_PROP_LENGTH is kept because the+                       Uint32 test is still done if the length+                       property is read-only. */+                    if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) ==+                        JS_PROP_HAS_WRITABLE) {+                        prs = get_shape_prop(p->shape);+                        if (js_update_property_flags(ctx, p, &prs,+                                                     prs->flags & ~JS_PROP_WRITABLE))+                            return -1;+                    }+                    return res;+                } else {+                    if (flags & JS_PROP_HAS_VALUE) {+                        JS_FreeValue(ctx, pr->u.value);+                        pr->u.value = JS_DupValue(ctx, val);+                    }+                    if (flags & JS_PROP_HAS_WRITABLE) {+                        if (js_update_property_flags(ctx, p, &prs,+                                                     (prs->flags & ~JS_PROP_WRITABLE) |+                                                     (flags & JS_PROP_WRITABLE)))+                            return -1;+                    }+                }+            }+        }+        mask = 0;+        if (flags & JS_PROP_HAS_CONFIGURABLE)+            mask |= JS_PROP_CONFIGURABLE;+        if (flags & JS_PROP_HAS_ENUMERABLE)+            mask |= JS_PROP_ENUMERABLE;+        if (js_update_property_flags(ctx, p, &prs,+                                     (prs->flags & ~mask) | (flags & mask)))+            return -1;+        return TRUE;+    }++    /* handle modification of fast array elements */+    if (p->fast_array) {+        uint32_t idx;+        uint32_t prop_flags;+        if (p->class_id == JS_CLASS_ARRAY) {+            if (__JS_AtomIsTaggedInt(prop)) {+                idx = __JS_AtomToUInt32(prop);+                if (idx < p->u.array.count) {+                    prop_flags = get_prop_flags(flags, JS_PROP_C_W_E);+                    if (prop_flags != JS_PROP_C_W_E)+                        goto convert_to_slow_array;+                    if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+                    convert_to_slow_array:+                        if (convert_fast_array_to_array(ctx, p))+                            return -1;+                        else+                            goto redo_prop_update;+                    }+                    if (flags & JS_PROP_HAS_VALUE) {+                        set_value(ctx, &p->u.array.u.values[idx], JS_DupValue(ctx, val));+                    }+                    return TRUE;+                }+            }+        } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+                   p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+            JSValue num;+            int ret;++            if (!__JS_AtomIsTaggedInt(prop)) {+                /* slow path with to handle all numeric indexes */+                num = JS_AtomIsNumericIndex1(ctx, prop);+                if (JS_IsUndefined(num))+                    goto typed_array_done;+                if (JS_IsException(num))+                    return -1;+                ret = JS_NumberIsInteger(ctx, num);+                if (ret < 0) {+                    JS_FreeValue(ctx, num);+                    return -1;+                }+                if (!ret) {+                    JS_FreeValue(ctx, num);+                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "non integer index in typed array");+                }+                ret = JS_NumberIsNegativeOrMinusZero(ctx, num);+                JS_FreeValue(ctx, num);+                if (ret) {+                    return JS_ThrowTypeErrorOrFalse(ctx, flags, "negative index in typed array");+                }+                if (!__JS_AtomIsTaggedInt(prop))+                    goto typed_array_oob;+            }+            idx = __JS_AtomToUInt32(prop);+            /* if the typed array is detached, p->u.array.count = 0 */+            if (idx >= typed_array_get_length(ctx, p)) {+            typed_array_oob:+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "out-of-bound index in typed array");+            }+            prop_flags = get_prop_flags(flags, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+            if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET) ||+                prop_flags != (JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE)) {+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "invalid descriptor flags");+            }+            if (flags & JS_PROP_HAS_VALUE) {+                return JS_SetPropertyValue(ctx, this_obj, JS_NewInt32(ctx, idx), JS_DupValue(ctx, val), flags);+            }+            return TRUE;+        typed_array_done: ;+        }+    }++    return JS_CreateProperty(ctx, p, prop, val, getter, setter, flags);+}++static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,+                                     JSAtom prop, JSAutoInitIDEnum id,+                                     void *opaque, int flags)+{+    JSObject *p;+    JSProperty *pr;++    if (JS_VALUE_GET_TAG(this_obj) != JS_TAG_OBJECT)+        return FALSE;++    p = JS_VALUE_GET_OBJ(this_obj);++    if (find_own_property(&pr, p, prop)) {+        /* property already exists */+        abort();+        return FALSE;+    }++    /* Specialized CreateProperty */+    pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);+    if (unlikely(!pr))+        return -1;+    pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx);+    assert((pr->u.init.realm_and_id & 3) == 0);+    assert(id <= 3);+    pr->u.init.realm_and_id |= id;+    pr->u.init.opaque = opaque;+    return TRUE;+}++/* shortcut to add or redefine a new property value */+int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,+                           JSAtom prop, JSValue val, int flags)+{+    int ret;+    ret = JS_DefineProperty(ctx, this_obj, prop, val, JS_UNDEFINED, JS_UNDEFINED,+                            flags | JS_PROP_HAS_VALUE | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE);+    JS_FreeValue(ctx, val);+    return ret;+}++int JS_DefinePropertyValueValue(JSContext *ctx, JSValueConst this_obj,+                                JSValue prop, JSValue val, int flags)+{+    JSAtom atom;+    int ret;+    atom = JS_ValueToAtom(ctx, prop);+    JS_FreeValue(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL)) {+        JS_FreeValue(ctx, val);+        return -1;+    }+    ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);+    JS_FreeAtom(ctx, atom);+    return ret;+}++int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,+                                 uint32_t idx, JSValue val, int flags)+{+    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewUint32(ctx, idx),+                                       val, flags);+}++int JS_DefinePropertyValueInt64(JSContext *ctx, JSValueConst this_obj,+                                int64_t idx, JSValue val, int flags)+{+    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),+                                       val, flags);+}++int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,+                              const char *prop, JSValue val, int flags)+{+    JSAtom atom;+    int ret;+    atom = JS_NewAtom(ctx, prop);+    ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);+    JS_FreeAtom(ctx, atom);+    return ret;+}++/* shortcut to add getter & setter */+int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,+                            JSAtom prop, JSValue getter, JSValue setter,+                            int flags)+{+    int ret;+    ret = JS_DefineProperty(ctx, this_obj, prop, JS_UNDEFINED, getter, setter,+                            flags | JS_PROP_HAS_GET | JS_PROP_HAS_SET |+                            JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE);+    JS_FreeValue(ctx, getter);+    JS_FreeValue(ctx, setter);+    return ret;+}++static int JS_CreateDataPropertyUint32(JSContext *ctx, JSValueConst this_obj,+                                       int64_t idx, JSValue val, int flags)+{+    return JS_DefinePropertyValueValue(ctx, this_obj, JS_NewInt64(ctx, idx),+                                       val, flags | JS_PROP_CONFIGURABLE |+                                       JS_PROP_ENUMERABLE | JS_PROP_WRITABLE);+}+++/* return TRUE if 'obj' has a non empty 'name' string */+static BOOL js_object_has_name(JSContext *ctx, JSValueConst obj)+{+    JSProperty *pr;+    JSShapeProperty *prs;+    JSValueConst val;+    JSString *p;+    +    prs = find_own_property(&pr, JS_VALUE_GET_OBJ(obj), JS_ATOM_name);+    if (!prs)+        return FALSE;+    if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)+        return TRUE;+    val = pr->u.value;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)+        return TRUE;+    p = JS_VALUE_GET_STRING(val);+    return (p->len != 0);+}++static int JS_DefineObjectName(JSContext *ctx, JSValueConst obj,+                               JSAtom name, int flags)+{+    if (name != JS_ATOM_NULL+    &&  JS_IsObject(obj)+    &&  !js_object_has_name(ctx, obj)+    &&  JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, JS_AtomToString(ctx, name), flags) < 0) {+        return -1;+    }+    return 0;+}++static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj,+                                       JSValueConst str, int flags)+{+    if (JS_IsObject(obj) &&+        !js_object_has_name(ctx, obj)) {+        JSAtom prop;+        JSValue name_str;+        prop = JS_ValueToAtom(ctx, str);+        if (prop == JS_ATOM_NULL)+            return -1;+        name_str = js_get_function_name(ctx, prop);+        JS_FreeAtom(ctx, prop);+        if (JS_IsException(name_str))+            return -1;+        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_name, name_str, flags) < 0)+            return -1;+    }+    return 0;+}++#define DEFINE_GLOBAL_LEX_VAR (1 << 7)+#define DEFINE_GLOBAL_FUNC_VAR (1 << 6)++static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop)+{+    return JS_ThrowSyntaxErrorAtom(ctx, "redeclaration of '%s'", prop);+}++/* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */+/* XXX: could support exotic global object. */+static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags)+{+    JSObject *p;+    JSShapeProperty *prs;++    p = JS_VALUE_GET_OBJ(ctx->global_obj);+    prs = find_own_property1(p, prop);+    /* XXX: should handle JS_PROP_AUTOINIT */+    if (flags & DEFINE_GLOBAL_LEX_VAR) {+        if (prs && !(prs->flags & JS_PROP_CONFIGURABLE))+            goto fail_redeclaration;+    } else {+        if (!prs && !p->extensible)+            goto define_error;+        if (flags & DEFINE_GLOBAL_FUNC_VAR) {+            if (prs) {+                if (!(prs->flags & JS_PROP_CONFIGURABLE) &&+                    ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET ||+                     ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) !=+                      (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) {+                define_error:+                    JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'",+                                          prop);+                    return -1;+                }+            }+        }+    }+    /* check if there already is a lexical declaration */+    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+    prs = find_own_property1(p, prop);+    if (prs) {+    fail_redeclaration:+        JS_ThrowSyntaxErrorVarRedeclaration(ctx, prop);+        return -1;+    }+    return 0;+}++/* def_flags is (0, DEFINE_GLOBAL_LEX_VAR) |+   JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE */+/* XXX: could support exotic global object. */+static int JS_DefineGlobalVar(JSContext *ctx, JSAtom prop, int def_flags)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    JSValue val;+    int flags;++    if (def_flags & DEFINE_GLOBAL_LEX_VAR) {+        p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+        flags = JS_PROP_ENUMERABLE | (def_flags & JS_PROP_WRITABLE) |+            JS_PROP_CONFIGURABLE;+        val = JS_UNINITIALIZED;+    } else {+        p = JS_VALUE_GET_OBJ(ctx->global_obj);+        flags = JS_PROP_ENUMERABLE | JS_PROP_WRITABLE |+            (def_flags & JS_PROP_CONFIGURABLE);+        val = JS_UNDEFINED;+    }+    prs = find_own_property1(p, prop);+    if (prs)+        return 0;+    if (!p->extensible)+        return 0;+    pr = add_property(ctx, p, prop, flags);+    if (unlikely(!pr))+        return -1;+    pr->u.value = val;+    return 0;+}++/* 'def_flags' is 0 or JS_PROP_CONFIGURABLE. */+/* XXX: could support exotic global object. */+static int JS_DefineGlobalFunction(JSContext *ctx, JSAtom prop,+                                   JSValueConst func, int def_flags)+{++    JSObject *p;+    JSShapeProperty *prs;+    int flags;++    p = JS_VALUE_GET_OBJ(ctx->global_obj);+    prs = find_own_property1(p, prop);+    flags = JS_PROP_HAS_VALUE | JS_PROP_THROW;+    if (!prs || (prs->flags & JS_PROP_CONFIGURABLE)) {+        flags |= JS_PROP_ENUMERABLE | JS_PROP_WRITABLE | def_flags |+            JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_WRITABLE | JS_PROP_HAS_ENUMERABLE;+    }+    if (JS_DefineProperty(ctx, ctx->global_obj, prop, func,+                          JS_UNDEFINED, JS_UNDEFINED, flags) < 0)+        return -1;+    return 0;+}++static JSValue JS_GetGlobalVar(JSContext *ctx, JSAtom prop,+                               BOOL throw_ref_error)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;++    /* no exotic behavior is possible in global_var_obj */+    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        /* XXX: should handle JS_PROP_TMASK properties */+        if (unlikely(JS_IsUninitialized(pr->u.value)))+            return JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+        return JS_DupValue(ctx, pr->u.value);+    }+    return JS_GetPropertyInternal(ctx, ctx->global_obj, prop,+                                 ctx->global_obj, throw_ref_error);+}++/* construct a reference to a global variable */+static int JS_GetGlobalVarRef(JSContext *ctx, JSAtom prop, JSValue *sp)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;++    /* no exotic behavior is possible in global_var_obj */+    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        /* XXX: should handle JS_PROP_AUTOINIT properties? */+        /* XXX: conformance: do these tests in+           OP_put_var_ref/OP_get_var_ref ? */+        if (unlikely(JS_IsUninitialized(pr->u.value))) {+            JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+            return -1;+        }+        if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) {+            return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop);+        }+        sp[0] = JS_DupValue(ctx, ctx->global_var_obj);+    } else {+        int ret;+        ret = JS_HasProperty(ctx, ctx->global_obj, prop);+        if (ret < 0)+            return -1;+        if (ret) {+            sp[0] = JS_DupValue(ctx, ctx->global_obj);+        } else {+            sp[0] = JS_UNDEFINED;+        }+    }+    sp[1] = JS_AtomToValue(ctx, prop);+    return 0;+}++/* use for strict variable access: test if the variable exists */+static int JS_CheckGlobalVar(JSContext *ctx, JSAtom prop)+{+    JSObject *p;+    JSShapeProperty *prs;+    int ret;++    /* no exotic behavior is possible in global_var_obj */+    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+    prs = find_own_property1(p, prop);+    if (prs) {+        ret = TRUE;+    } else {+        ret = JS_HasProperty(ctx, ctx->global_obj, prop);+        if (ret < 0)+            return -1;+    }+    return ret;+}++/* flag = 0: normal variable write+   flag = 1: initialize lexical variable+   flag = 2: normal variable write, strict check was done before+*/+static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,+                           int flag)+{+    JSObject *p;+    JSShapeProperty *prs;+    JSProperty *pr;+    int flags;++    /* no exotic behavior is possible in global_var_obj */+    p = JS_VALUE_GET_OBJ(ctx->global_var_obj);+    prs = find_own_property(&pr, p, prop);+    if (prs) {+        /* XXX: should handle JS_PROP_AUTOINIT properties? */+        if (flag != 1) {+            if (unlikely(JS_IsUninitialized(pr->u.value))) {+                JS_FreeValue(ctx, val);+                JS_ThrowReferenceErrorUninitialized(ctx, prs->atom);+                return -1;+            }+            if (unlikely(!(prs->flags & JS_PROP_WRITABLE))) {+                JS_FreeValue(ctx, val);+                return JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, prop);+            }+        }+        set_value(ctx, &pr->u.value, val);+        return 0;+    }+    flags = JS_PROP_THROW_STRICT;+    if (is_strict_mode(ctx)) +        flags |= JS_PROP_NO_ADD;+    return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, flags);+}++/* return -1, FALSE or TRUE. return FALSE if not configurable or+   invalid object. return -1 in case of exception.+   flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */+int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags)+{+    JSValue obj1;+    JSObject *p;+    int res;+    +    obj1 = JS_ToObject(ctx, obj);+    if (JS_IsException(obj1))+        return -1;+    p = JS_VALUE_GET_OBJ(obj1);+    res = delete_property(ctx, p, prop);+    JS_FreeValue(ctx, obj1);+    if (res != FALSE)+        return res;+    if ((flags & JS_PROP_THROW) ||+        ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {+        JS_ThrowTypeError(ctx, "could not delete property");+        return -1;+    }+    return FALSE;+}++int JS_DeletePropertyInt64(JSContext *ctx, JSValueConst obj, int64_t idx, int flags)+{+    JSAtom prop;+    int res;++    if ((uint64_t)idx <= JS_ATOM_MAX_INT) {+        /* fast path for fast arrays */+        return JS_DeleteProperty(ctx, obj, __JS_AtomFromUInt32(idx), flags);+    }+    prop = JS_NewAtomInt64(ctx, idx);+    if (prop == JS_ATOM_NULL)+        return -1;+    res = JS_DeleteProperty(ctx, obj, prop, flags);+    JS_FreeAtom(ctx, prop);+    return res;+}++BOOL JS_IsFunction(JSContext *ctx, JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(val);+    switch(p->class_id) {+    case JS_CLASS_BYTECODE_FUNCTION:+        return TRUE;+    case JS_CLASS_PROXY:+        return p->u.proxy_data->is_func;+    default:+        return (ctx->rt->class_array[p->class_id].call != NULL);+    }+}++BOOL JS_IsCFunction(JSContext *ctx, JSValueConst val, JSCFunction *func, int magic)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(val);+    if (p->class_id == JS_CLASS_C_FUNCTION)+        return (p->u.cfunc.c_function.generic == func && p->u.cfunc.magic == magic);+    else+        return FALSE;+}++BOOL JS_IsConstructor(JSContext *ctx, JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(val);+    return p->is_constructor;+}++BOOL JS_SetConstructorBit(JSContext *ctx, JSValueConst func_obj, BOOL val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(func_obj);+    p->is_constructor = val;+    return TRUE;+}++BOOL JS_IsError(JSContext *ctx, JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(val);+    return (p->class_id == JS_CLASS_ERROR);+}++/* used to avoid catching interrupt exceptions */+BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(val);+    return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error;+}++void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return;+    p = JS_VALUE_GET_OBJ(val);+    if (p->class_id == JS_CLASS_ERROR)+        p->is_uncatchable_error = flag;+}++void JS_ResetUncatchableError(JSContext *ctx)+{+    JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE);+}++void JS_SetOpaque(JSValue obj, void *opaque)+{+   JSObject *p;+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(obj);+        p->u.opaque = opaque;+    }+}++/* return NULL if not an object of class class_id */+void *JS_GetOpaque(JSValueConst obj, JSClassID class_id)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return NULL;+    p = JS_VALUE_GET_OBJ(obj);+    if (p->class_id != class_id)+        return NULL;+    return p->u.opaque;+}++void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)+{+    void *p = JS_GetOpaque(obj, class_id);+    if (unlikely(!p)) {+        JS_ThrowTypeErrorInvalidClass(ctx, class_id);+    }+    return p;+}++#define HINT_STRING  0+#define HINT_NUMBER  1+#define HINT_NONE    2+/* don't try Symbol.toPrimitive */+#define HINT_FORCE_ORDINARY (1 << 4)++static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)+{+    int i;+    BOOL force_ordinary;++    JSAtom method_name;+    JSValue method, ret;+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)+        return val;+    force_ordinary = hint & HINT_FORCE_ORDINARY;+    hint &= ~HINT_FORCE_ORDINARY;+    if (!force_ordinary) {+        method = JS_GetProperty(ctx, val, JS_ATOM_Symbol_toPrimitive);+        if (JS_IsException(method))+            goto exception;+        /* ECMA says *If exoticToPrim is not undefined* but tests in+           test262 use null as a non callable converter */+        if (!JS_IsUndefined(method) && !JS_IsNull(method)) {+            JSAtom atom;+            JSValue arg;+            switch(hint) {+            case HINT_STRING:+                atom = JS_ATOM_string;+                break;+            case HINT_NUMBER:+                atom = JS_ATOM_number;+                break;+            default:+            case HINT_NONE:+                atom = JS_ATOM_default;+                break;+            }+            arg = JS_AtomToString(ctx, atom);+            ret = JS_CallFree(ctx, method, val, 1, (JSValueConst *)&arg);+            JS_FreeValue(ctx, arg);+            if (JS_IsException(ret))+                goto exception;+            JS_FreeValue(ctx, val);+            if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT)+                return ret;+            JS_FreeValue(ctx, ret);+            return JS_ThrowTypeError(ctx, "toPrimitive");+        }+    }+    if (hint != HINT_STRING)+        hint = HINT_NUMBER;+    for(i = 0; i < 2; i++) {+        if ((i ^ hint) == 0) {+            method_name = JS_ATOM_toString;+        } else {+            method_name = JS_ATOM_valueOf;+        }+        method = JS_GetProperty(ctx, val, method_name);+        if (JS_IsException(method))+            goto exception;+        if (JS_IsFunction(ctx, method)) {+            ret = JS_CallFree(ctx, method, val, 0, NULL);+            if (JS_IsException(ret))+                goto exception;+            if (JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {+                JS_FreeValue(ctx, val);+                return ret;+            }+            JS_FreeValue(ctx, ret);+        } else {+            JS_FreeValue(ctx, method);+        }+    }+    JS_ThrowTypeError(ctx, "toPrimitive");+exception:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue JS_ToPrimitive(JSContext *ctx, JSValueConst val, int hint)+{+    return JS_ToPrimitiveFree(ctx, JS_DupValue(ctx, val), hint);+}++void JS_SetIsHTMLDDA(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return;+    p = JS_VALUE_GET_OBJ(obj);+    p->is_HTMLDDA = TRUE;+}++static inline BOOL JS_IsHTMLDDA(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return FALSE;+    p = JS_VALUE_GET_OBJ(obj);+    return p->is_HTMLDDA;+}+                         +static int JS_ToBoolFree(JSContext *ctx, JSValue val)+{+    uint32_t tag = JS_VALUE_GET_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+        return JS_VALUE_GET_INT(val) != 0;+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        return JS_VALUE_GET_INT(val);+    case JS_TAG_EXCEPTION:+        return -1;+    case JS_TAG_STRING:+        {+            BOOL ret = JS_VALUE_GET_STRING(val)->len != 0;+            JS_FreeValue(ctx, val);+            return ret;+        }+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            BOOL ret;+            ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;+            JS_FreeValue(ctx, val);+            return ret;+        }+    case JS_TAG_BIG_DECIMAL:+        {+            JSBigDecimal *p = JS_VALUE_GET_PTR(val);+            BOOL ret;+            ret = p->num.expn != BF_EXP_ZERO && p->num.expn != BF_EXP_NAN;+            JS_FreeValue(ctx, val);+            return ret;+        }+#endif+    case JS_TAG_OBJECT:+        {+            JSObject *p = JS_VALUE_GET_OBJ(val);+            BOOL ret;+            ret = !p->is_HTMLDDA;+            JS_FreeValue(ctx, val);+            return ret;+        }+        break;+    default:+        if (JS_TAG_IS_FLOAT64(tag)) {+            double d = JS_VALUE_GET_FLOAT64(val);+            return !isnan(d) && d != 0;+        } else {+            JS_FreeValue(ctx, val);+            return TRUE;+        }+    }+}++int JS_ToBool(JSContext *ctx, JSValueConst val)+{+    return JS_ToBoolFree(ctx, JS_DupValue(ctx, val));+}++static int skip_spaces(const char *pc)+{+    const uint8_t *p, *p_next, *p_start;+    uint32_t c;++    p = p_start = (const uint8_t *)pc;+    for (;;) {+        c = *p;+        if (c < 128) {+            if (!((c >= 0x09 && c <= 0x0d) || (c == 0x20)))+                break;+            p++;+        } else {+            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);+            if (!lre_is_space(c))+                break;+            p = p_next;+        }+    }+    return p - p_start;+}++static inline int to_digit(int c)+{+    if (c >= '0' && c <= '9')+        return c - '0';+    else if (c >= 'A' && c <= 'Z')+        return c - 'A' + 10;+    else if (c >= 'a' && c <= 'z')+        return c - 'a' + 10;+    else+        return 36;+}++/* XXX: remove */+static double js_strtod(const char *p, int radix, BOOL is_float)+{+    double d;+    int c;+    +    if (!is_float || radix != 10) {+        uint64_t n_max, n;+        int int_exp, is_neg;+        +        is_neg = 0;+        if (*p == '-') {+            is_neg = 1;+            p++;+        }++        /* skip leading zeros */+        while (*p == '0')+            p++;+        n = 0;+        if (radix == 10)+            n_max = ((uint64_t)-1 - 9) / 10; /* most common case */+        else+            n_max = ((uint64_t)-1 - (radix - 1)) / radix;+        /* XXX: could be more precise */+        int_exp = 0;+        while (*p != '\0') {+            c = to_digit((uint8_t)*p);+            if (c >= radix)+                break;+            if (n <= n_max) {+                n = n * radix + c;+            } else {+                int_exp++;+            }+            p++;+        }+        d = n;+        if (int_exp != 0) {+            d *= pow(radix, int_exp);+        }+        if (is_neg)+            d = -d;+    } else {+        d = strtod(p, NULL);+    }+    return d;+}++#define ATOD_INT_ONLY        (1 << 0)+/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */+#define ATOD_ACCEPT_BIN_OCT  (1 << 2)+/* accept O prefix as octal if radix == 0 and properly formed (Annex B) */+#define ATOD_ACCEPT_LEGACY_OCTAL  (1 << 4)+/* accept _ between digits as a digit separator */+#define ATOD_ACCEPT_UNDERSCORES  (1 << 5)+/* allow a suffix to override the type */+#define ATOD_ACCEPT_SUFFIX    (1 << 6) +/* default type */+#define ATOD_TYPE_MASK        (3 << 7)+#define ATOD_TYPE_FLOAT64     (0 << 7)+#define ATOD_TYPE_BIG_INT     (1 << 7)+#define ATOD_TYPE_BIG_FLOAT   (2 << 7)+#define ATOD_TYPE_BIG_DECIMAL (3 << 7)+/* assume bigint mode: floats are parsed as integers if no decimal+   point nor exponent */+#define ATOD_MODE_BIGINT      (1 << 9) +/* accept -0x1 */+#define ATOD_ACCEPT_PREFIX_AFTER_SIGN (1 << 10)++#ifdef CONFIG_BIGNUM+static JSValue js_string_to_bigint(JSContext *ctx, const char *buf,+                                   int radix, int flags, slimb_t *pexponent)+{+    bf_t a_s, *a = &a_s;+    int ret;+    JSValue val;+    val = JS_NewBigInt(ctx);+    if (JS_IsException(val))+        return val;+    a = JS_GetBigInt(val);+    ret = bf_atof(a, buf, NULL, radix, BF_PREC_INF, BF_RNDZ);+    if (ret & BF_ST_MEM_ERROR) {+        JS_FreeValue(ctx, val);+        return JS_ThrowOutOfMemory(ctx);+    }+    val = JS_CompactBigInt1(ctx, val, (flags & ATOD_MODE_BIGINT) != 0);+    return val;+}++static JSValue js_string_to_bigfloat(JSContext *ctx, const char *buf,+                                     int radix, int flags, slimb_t *pexponent)+{+    bf_t *a;+    int ret;+    JSValue val;+    +    val = JS_NewBigFloat(ctx);+    if (JS_IsException(val))+        return val;+    a = JS_GetBigFloat(val);+    if (flags & ATOD_ACCEPT_SUFFIX) {+        /* return the exponent to get infinite precision */+        ret = bf_atof2(a, pexponent, buf, NULL, radix, BF_PREC_INF,+                       BF_RNDZ | BF_ATOF_EXPONENT);+    } else {+        ret = bf_atof(a, buf, NULL, radix, ctx->fp_env.prec,+                      ctx->fp_env.flags);+    }+    if (ret & BF_ST_MEM_ERROR) {+        JS_FreeValue(ctx, val);+        return JS_ThrowOutOfMemory(ctx);+    }+    return val;+}++static JSValue js_string_to_bigdecimal(JSContext *ctx, const char *buf,+                                       int radix, int flags, slimb_t *pexponent)+{+    bfdec_t *a;+    int ret;+    JSValue val;+    +    val = JS_NewBigDecimal(ctx);+    if (JS_IsException(val))+        return val;+    a = JS_GetBigDecimal(val);+    ret = bfdec_atof(a, buf, NULL, BF_PREC_INF,+                     BF_RNDZ | BF_ATOF_NO_NAN_INF);+    if (ret & BF_ST_MEM_ERROR) {+        JS_FreeValue(ctx, val);+        return JS_ThrowOutOfMemory(ctx);+    }+    return val;+}++#endif++/* return an exception in case of memory error. Return JS_NAN if+   invalid syntax */+#ifdef CONFIG_BIGNUM+static JSValue js_atof2(JSContext *ctx, const char *str, const char **pp,+                        int radix, int flags, slimb_t *pexponent)+#else+static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,+                       int radix, int flags)+#endif+{+    const char *p, *p_start;+    int sep, is_neg;+    BOOL is_float, has_legacy_octal;+    int atod_type = flags & ATOD_TYPE_MASK;+    char buf1[64], *buf;+    int i, j, len;+    BOOL buf_allocated = FALSE;+    JSValue val;+    +    /* optional separator between digits */+    sep = (flags & ATOD_ACCEPT_UNDERSCORES) ? '_' : 256;+    has_legacy_octal = FALSE;+    +    p = str;+    p_start = p;+    is_neg = 0;+    if (p[0] == '+') {+        p++;+        p_start++;+        if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))+            goto no_radix_prefix;+    } else if (p[0] == '-') {+        p++;+        p_start++;+        is_neg = 1;+        if (!(flags & ATOD_ACCEPT_PREFIX_AFTER_SIGN))+            goto no_radix_prefix;+    }+    if (p[0] == '0') {+        if ((p[1] == 'x' || p[1] == 'X') &&+            (radix == 0 || radix == 16)) {+            p += 2;+            radix = 16;+        } else if ((p[1] == 'o' || p[1] == 'O') &&+                   radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {+            p += 2;+            radix = 8;+        } else if ((p[1] == 'b' || p[1] == 'B') &&+                   radix == 0 && (flags & ATOD_ACCEPT_BIN_OCT)) {+            p += 2;+            radix = 2;+        } else if ((p[1] >= '0' && p[1] <= '9') &&+                   radix == 0 && (flags & ATOD_ACCEPT_LEGACY_OCTAL)) {+            int i;+            has_legacy_octal = TRUE;+            sep = 256;+            for (i = 1; (p[i] >= '0' && p[i] <= '7'); i++)+                continue;+            if (p[i] == '8' || p[i] == '9')+                goto no_prefix;+            p += 1;+            radix = 8;+        } else {+            goto no_prefix;+        }+        /* there must be a digit after the prefix */+        if (to_digit((uint8_t)*p) >= radix)+            goto fail;+    no_prefix: ;+    } else {+ no_radix_prefix:+        if (!(flags & ATOD_INT_ONLY) &&+            (atod_type == ATOD_TYPE_FLOAT64 ||+             atod_type == ATOD_TYPE_BIG_FLOAT) &&+            strstart(p, "Infinity", &p)) {+#ifdef CONFIG_BIGNUM+            if (atod_type == ATOD_TYPE_BIG_FLOAT) {+                bf_t *a;+                val = JS_NewBigFloat(ctx);+                if (JS_IsException(val))+                    goto done;+                a = JS_GetBigFloat(val);+                bf_set_inf(a, is_neg);+            } else+#endif+            {+                double d = 1.0 / 0.0;+                if (is_neg)+                    d = -d;+                val = JS_NewFloat64(ctx, d);+            }+            goto done;+        }+    }+    if (radix == 0)+        radix = 10;+    is_float = FALSE;+    p_start = p;+    while (to_digit((uint8_t)*p) < radix+           ||  (*p == sep && (radix != 10 ||+                              p != p_start + 1 || p[-1] != '0') &&+                to_digit((uint8_t)p[1]) < radix)) {+        p++;+    }+    if (!(flags & ATOD_INT_ONLY)) {+        if (*p == '.' && (p > p_start || to_digit((uint8_t)p[1]) < radix)) {+            is_float = TRUE;+            p++;+            if (*p == sep)+                goto fail;+            while (to_digit((uint8_t)*p) < radix ||+                   (*p == sep && to_digit((uint8_t)p[1]) < radix))+                p++;+        }+        if (p > p_start &&+            (((*p == 'e' || *p == 'E') && radix == 10) ||+             ((*p == 'p' || *p == 'P') && (radix == 2 || radix == 8 || radix == 16)))) {+            const char *p1 = p + 1;+            is_float = TRUE;+            if (*p1 == '+') {+                p1++;+            } else if (*p1 == '-') {+                p1++;+            }+            if (is_digit((uint8_t)*p1)) {+                p = p1 + 1;+                while (is_digit((uint8_t)*p) || (*p == sep && is_digit((uint8_t)p[1])))+                    p++;+            }+        }+    }+    if (p == p_start)+        goto fail;++    buf = buf1;+    buf_allocated = FALSE;+    len = p - p_start;+    if (unlikely((len + 2) > sizeof(buf1))) {+        buf = js_malloc_rt(ctx->rt, len + 2); /* no exception raised */+        if (!buf)+            goto mem_error;+        buf_allocated = TRUE;+    }+    /* remove the separators and the radix prefixes */+    j = 0;+    if (is_neg)+        buf[j++] = '-';+    for (i = 0; i < len; i++) {+        if (p_start[i] != '_')+            buf[j++] = p_start[i];+    }+    buf[j] = '\0';++#ifdef CONFIG_BIGNUM+    if (flags & ATOD_ACCEPT_SUFFIX) {+        if (*p == 'n') {+            p++;+            atod_type = ATOD_TYPE_BIG_INT;+        } else if (*p == 'l') {+            p++;+            atod_type = ATOD_TYPE_BIG_FLOAT;+        } else if (*p == 'm') {+            p++;+            atod_type = ATOD_TYPE_BIG_DECIMAL;+        } else {+            if (flags & ATOD_MODE_BIGINT) {+                if (!is_float)+                    atod_type = ATOD_TYPE_BIG_INT;+                if (has_legacy_octal)+                    goto fail;+            } else {+                if (is_float && radix != 10)+                    goto fail;+            }+        }+    } else {+        if (atod_type == ATOD_TYPE_FLOAT64) {+            if (flags & ATOD_MODE_BIGINT) {+                if (!is_float)+                    atod_type = ATOD_TYPE_BIG_INT;+                if (has_legacy_octal)+                    goto fail;+            } else {+                if (is_float && radix != 10)+                    goto fail;+            }+        }+    }++    switch(atod_type) {+    case ATOD_TYPE_FLOAT64:+        {+            double d;+            d = js_strtod(buf, radix, is_float);+            /* return int or float64 */+            val = JS_NewFloat64(ctx, d);+        }+        break;+    case ATOD_TYPE_BIG_INT:+        if (has_legacy_octal || is_float)+            goto fail;+        val = ctx->rt->bigint_ops.from_string(ctx, buf, radix, flags, NULL);+        break;+    case ATOD_TYPE_BIG_FLOAT:+        if (has_legacy_octal)+            goto fail;+        val = ctx->rt->bigfloat_ops.from_string(ctx, buf, radix, flags,+                                                pexponent);+        break;+    case ATOD_TYPE_BIG_DECIMAL:+        if (radix != 10)+            goto fail;+        val = ctx->rt->bigdecimal_ops.from_string(ctx, buf, radix, flags, NULL);+        break;+    default:+        abort();+    }+#else+    {+        double d;+        (void)has_legacy_octal;+        if (is_float && radix != 10)+            goto fail;+        d = js_strtod(buf, radix, is_float);+        val = JS_NewFloat64(ctx, d);+    }+#endif+    +done:+    if (buf_allocated)+        js_free_rt(ctx->rt, buf);+    if (pp)+        *pp = p;+    return val;+ fail:+    val = JS_NAN;+    goto done;+ mem_error:+    val = JS_ThrowOutOfMemory(ctx);+    goto done;+}++#ifdef CONFIG_BIGNUM+static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,+                       int radix, int flags)+{+    return js_atof2(ctx, str, pp, radix, flags, NULL);+}+#endif++typedef enum JSToNumberHintEnum {+    TON_FLAG_NUMBER,+    TON_FLAG_NUMERIC,+} JSToNumberHintEnum;++static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,+                                   JSToNumberHintEnum flag)+{+    uint32_t tag;+    JSValue ret;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_DECIMAL:+        if (flag != TON_FLAG_NUMERIC) {+            JS_FreeValue(ctx, val);+            return JS_ThrowTypeError(ctx, "cannot convert bigdecimal to number");+        }+        ret = val;+        break;+    case JS_TAG_BIG_INT:+        if (flag != TON_FLAG_NUMERIC) {+            JS_FreeValue(ctx, val);+            return JS_ThrowTypeError(ctx, "cannot convert bigint to number");+        }+        ret = val;+        break;+    case JS_TAG_BIG_FLOAT:+        if (flag != TON_FLAG_NUMERIC) {+            JS_FreeValue(ctx, val);+            return JS_ThrowTypeError(ctx, "cannot convert bigfloat to number");+        }+        ret = val;+        break;+#endif+    case JS_TAG_FLOAT64:+    case JS_TAG_INT:+    case JS_TAG_EXCEPTION:+        ret = val;+        break;+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+        ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));+        break;+    case JS_TAG_UNDEFINED:+        ret = JS_NAN;+        break;+    case JS_TAG_OBJECT:+        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);+        if (JS_IsException(val))+            return JS_EXCEPTION;+        goto redo;+    case JS_TAG_STRING:+        {+            const char *str;+            const char *p;+            size_t len;+            +            str = JS_ToCStringLen(ctx, &len, val);+            JS_FreeValue(ctx, val);+            if (!str)+                return JS_EXCEPTION;+            p = str;+            p += skip_spaces(p);+            if ((p - str) == len) {+                ret = JS_NewInt32(ctx, 0);+            } else {+                int flags = ATOD_ACCEPT_BIN_OCT;+                ret = js_atof(ctx, p, &p, 0, flags);+                if (!JS_IsException(ret)) {+                    p += skip_spaces(p);+                    if ((p - str) != len) {+                        JS_FreeValue(ctx, ret);+                        ret = JS_NAN;+                    }+                }+            }+            JS_FreeCString(ctx, str);+        }+        break;+    case JS_TAG_SYMBOL:+        JS_FreeValue(ctx, val);+        return JS_ThrowTypeError(ctx, "cannot convert symbol to number");+    default:+        JS_FreeValue(ctx, val);+        ret = JS_NAN;+        break;+    }+    return ret;+}++static JSValue JS_ToNumberFree(JSContext *ctx, JSValue val)+{+    return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMBER);+}++static JSValue JS_ToNumericFree(JSContext *ctx, JSValue val)+{+    return JS_ToNumberHintFree(ctx, val, TON_FLAG_NUMERIC);+}++static JSValue JS_ToNumeric(JSContext *ctx, JSValueConst val)+{+    return JS_ToNumericFree(ctx, JS_DupValue(ctx, val));+}++static __exception int __JS_ToFloat64Free(JSContext *ctx, double *pres,+                                          JSValue val)+{+    double d;+    uint32_t tag;++    val = JS_ToNumberFree(ctx, val);+    if (JS_IsException(val)) {+        *pres = JS_FLOAT64_NAN;+        return -1;+    }+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+        d = JS_VALUE_GET_INT(val);+        break;+    case JS_TAG_FLOAT64:+        d = JS_VALUE_GET_FLOAT64(val);+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            /* XXX: there can be a double rounding issue with some+               primitives (such as JS_ToUint8ClampFree()), but it is+               not critical to fix it. */+            bf_get_float64(&p->num, &d, BF_RNDN);+            JS_FreeValue(ctx, val);+        }+        break;+#endif+    default:+        abort();+    }+    *pres = d;+    return 0;+}++static inline int JS_ToFloat64Free(JSContext *ctx, double *pres, JSValue val)+{+    uint32_t tag;++    tag = JS_VALUE_GET_TAG(val);+    if (tag <= JS_TAG_NULL) {+        *pres = JS_VALUE_GET_INT(val);+        return 0;+    } else if (JS_TAG_IS_FLOAT64(tag)) {+        *pres = JS_VALUE_GET_FLOAT64(val);+        return 0;+    } else {+        return __JS_ToFloat64Free(ctx, pres, val);+    }+}++int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val)+{+    return JS_ToFloat64Free(ctx, pres, JS_DupValue(ctx, val));+}++static JSValue JS_ToNumber(JSContext *ctx, JSValueConst val)+{+    return JS_ToNumberFree(ctx, JS_DupValue(ctx, val));+}++/* same as JS_ToNumber() but return 0 in case of NaN/Undefined */+static __maybe_unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)+{+    uint32_t tag;+    JSValue ret;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));+        break;+    case JS_TAG_FLOAT64:+        {+            double d = JS_VALUE_GET_FLOAT64(val);+            if (isnan(d)) {+                ret = JS_NewInt32(ctx, 0);+            } else {+                /* convert -0 to +0 */+                d = trunc(d) + 0.0;+                ret = JS_NewFloat64(ctx, d);+            }+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            bf_t a_s, *a, r_s, *r = &r_s;+            BOOL is_nan;++            a = JS_ToBigFloat(ctx, &a_s, val);+            if (!bf_is_finite(a)) {+                is_nan = bf_is_nan(a);+                if (is_nan)+                    ret = JS_NewInt32(ctx, 0);+                else+                    ret = JS_DupValue(ctx, val);+            } else {+                ret = JS_NewBigInt(ctx);+                if (!JS_IsException(ret)) {+                    r = JS_GetBigInt(ret);+                    bf_set(r, a);+                    bf_rint(r, BF_RNDZ);+                    ret = JS_CompactBigInt(ctx, ret);+                }+            }+            if (a == &a_s)+                bf_delete(a);+            JS_FreeValue(ctx, val);+        }+        break;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val))+            return val;+        goto redo;+    }+    return ret;+}++/* Note: the integer value is satured to 32 bits */+static int JS_ToInt32SatFree(JSContext *ctx, int *pres, JSValue val)+{+    uint32_t tag;+    int ret;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        ret = JS_VALUE_GET_INT(val);+        break;+    case JS_TAG_EXCEPTION:+        *pres = 0;+        return -1;+    case JS_TAG_FLOAT64:+        {+            double d = JS_VALUE_GET_FLOAT64(val);+            if (isnan(d)) {+                ret = 0;+            } else {+                if (d < INT32_MIN)+                    ret = INT32_MIN;+                else if (d > INT32_MAX)+                    ret = INT32_MAX;+                else+                    ret = (int)d;+            }+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_get_int32(&ret, &p->num, 0);+            JS_FreeValue(ctx, val);+        }+        break;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val)) {+            *pres = 0;+            return -1;+        }+        goto redo;+    }+    *pres = ret;+    return 0;+}++int JS_ToInt32Sat(JSContext *ctx, int *pres, JSValueConst val)+{+    return JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));+}++int JS_ToInt32Clamp(JSContext *ctx, int *pres, JSValueConst val,+                    int min, int max, int min_offset)+{+    int res = JS_ToInt32SatFree(ctx, pres, JS_DupValue(ctx, val));+    if (res == 0) {+        if (*pres < min) {+            *pres += min_offset;+            if (*pres < min)+                *pres = min;+        } else {+            if (*pres > max)+                *pres = max;+        }+    }+    return res;+}++static int JS_ToInt64SatFree(JSContext *ctx, int64_t *pres, JSValue val)+{+    uint32_t tag;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        *pres = JS_VALUE_GET_INT(val);+        return 0;+    case JS_TAG_EXCEPTION:+        *pres = 0;+        return -1;+    case JS_TAG_FLOAT64:+        {+            double d = JS_VALUE_GET_FLOAT64(val);+            if (isnan(d)) {+                *pres = 0;+            } else {+                if (d < INT64_MIN)+                    *pres = INT64_MIN;+                else if (d > INT64_MAX)+                    *pres = INT64_MAX;+                else+                    *pres = (int64_t)d;+            }+        }+        return 0;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_get_int64(pres, &p->num, 0);+            JS_FreeValue(ctx, val);+        }+        return 0;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val)) {+            *pres = 0;+            return -1;+        }+        goto redo;+    }+}++int JS_ToInt64Sat(JSContext *ctx, int64_t *pres, JSValueConst val)+{+    return JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));+}++int JS_ToInt64Clamp(JSContext *ctx, int64_t *pres, JSValueConst val,+                    int64_t min, int64_t max, int64_t neg_offset)+{+    int res = JS_ToInt64SatFree(ctx, pres, JS_DupValue(ctx, val));+    if (res == 0) {+        if (*pres < 0)+            *pres += neg_offset;+        if (*pres < min)+            *pres = min;+        else if (*pres > max)+            *pres = max;+    }+    return res;+}++/* Same as JS_ToInt32Free() but with a 64 bit result. Return (<0, 0)+   in case of exception */+static int JS_ToInt64Free(JSContext *ctx, int64_t *pres, JSValue val)+{+    uint32_t tag;+    int64_t ret;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        ret = JS_VALUE_GET_INT(val);+        break;+    case JS_TAG_FLOAT64:+        {+            JSFloat64Union u;+            double d;+            int e;+            d = JS_VALUE_GET_FLOAT64(val);+            u.d = d;+            /* we avoid doing fmod(x, 2^64) */+            e = (u.u64 >> 52) & 0x7ff;+            if (likely(e <= (1023 + 62))) {+                /* fast case */+                ret = (int64_t)d;+            } else if (e <= (1023 + 62 + 53)) {+                uint64_t v;+                /* remainder modulo 2^64 */+                v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52);+                ret = v << ((e - 1023) - 52);+                /* take the sign into account */+                if (u.u64 >> 63)+                    ret = -ret;+            } else {+                ret = 0; /* also handles NaN and +inf */+            }+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_get_int64(&ret, &p->num, BF_GET_INT_MOD);+            JS_FreeValue(ctx, val);+        }+        break;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val)) {+            *pres = 0;+            return -1;+        }+        goto redo;+    }+    *pres = ret;+    return 0;+}++int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val)+{+    return JS_ToInt64Free(ctx, pres, JS_DupValue(ctx, val));+}++int JS_ToInt64Ext(JSContext *ctx, int64_t *pres, JSValueConst val)+{+    if (JS_IsBigInt(ctx, val))+        return JS_ToBigInt64(ctx, pres, val);+    else+        return JS_ToInt64(ctx, pres, val);+}++/* return (<0, 0) in case of exception */+static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val)+{+    uint32_t tag;+    int32_t ret;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        ret = JS_VALUE_GET_INT(val);+        break;+    case JS_TAG_FLOAT64:+        {+            JSFloat64Union u;+            double d;+            int e;+            d = JS_VALUE_GET_FLOAT64(val);+            u.d = d;+            /* we avoid doing fmod(x, 2^32) */+            e = (u.u64 >> 52) & 0x7ff;+            if (likely(e <= (1023 + 30))) {+                /* fast case */+                ret = (int32_t)d;+            } else if (e <= (1023 + 30 + 53)) {+                uint64_t v;+                /* remainder modulo 2^32 */+                v = (u.u64 & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52);+                v = v << ((e - 1023) - 52 + 32);+                ret = v >> 32;+                /* take the sign into account */+                if (u.u64 >> 63)+                    ret = -ret;+            } else {+                ret = 0; /* also handles NaN and +inf */+            }+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_get_int32(&ret, &p->num, BF_GET_INT_MOD);+            JS_FreeValue(ctx, val);+        }+        break;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val)) {+            *pres = 0;+            return -1;+        }+        goto redo;+    }+    *pres = ret;+    return 0;+}++int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val)+{+    return JS_ToInt32Free(ctx, pres, JS_DupValue(ctx, val));+}++static inline int JS_ToUint32Free(JSContext *ctx, uint32_t *pres, JSValue val)+{+    return JS_ToInt32Free(ctx, (int32_t *)pres, val);+}++static int JS_ToUint8ClampFree(JSContext *ctx, int32_t *pres, JSValue val)+{+    uint32_t tag;+    int res;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        res = JS_VALUE_GET_INT(val);+#ifdef CONFIG_BIGNUM+    int_clamp:+#endif+        res = max_int(0, min_int(255, res));+        break;+    case JS_TAG_FLOAT64:+        {+            double d = JS_VALUE_GET_FLOAT64(val);+            if (isnan(d)) {+                res = 0;+            } else {+                if (d < 0)+                    res = 0;+                else if (d > 255)+                    res = 255;+                else+                    res = lrint(d);+            }+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_t r_s, *r = &r_s;+            bf_init(ctx->bf_ctx, r);+            bf_set(r, &p->num);+            bf_rint(r, BF_RNDN);+            bf_get_int32(&res, r, 0);+            bf_delete(r);+            JS_FreeValue(ctx, val);+        }+        goto int_clamp;+#endif+    default:+        val = JS_ToNumberFree(ctx, val);+        if (JS_IsException(val)) {+            *pres = 0;+            return -1;+        }+        goto redo;+    }+    *pres = res;+    return 0;+}++static __exception int JS_ToArrayLengthFree(JSContext *ctx, uint32_t *plen,+                                            JSValue val, BOOL is_array_ctor)+{+    uint32_t tag, len;++    tag = JS_VALUE_GET_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+        {+            int v;+            v = JS_VALUE_GET_INT(val);+            if (v < 0)+                goto fail;+            len = v;+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            bf_t a;+            BOOL res;+            bf_get_int32((int32_t *)&len, &p->num, BF_GET_INT_MOD);+            bf_init(ctx->bf_ctx, &a);+            bf_set_ui(&a, len);+            res = bf_cmp_eq(&a, &p->num);+            bf_delete(&a);+            JS_FreeValue(ctx, val);+            if (!res)+                goto fail;+        }+        break;+#endif+    default:+        if (JS_TAG_IS_FLOAT64(tag)) {+            double d;+            d = JS_VALUE_GET_FLOAT64(val);+            len = (uint32_t)d;+            if (len != d)+                goto fail;+        } else {+            uint32_t len1;++            if (is_array_ctor) {+                val = JS_ToNumberFree(ctx, val);+                if (JS_IsException(val))+                    return -1;+                /* cannot recurse because val is a number */+                if (JS_ToArrayLengthFree(ctx, &len, val, TRUE))+                    return -1;+            } else {+                /* legacy behavior: must do the conversion twice and compare */+                if (JS_ToUint32(ctx, &len, val)) {+                    JS_FreeValue(ctx, val);+                    return -1;+                }+                val = JS_ToNumberFree(ctx, val);+                if (JS_IsException(val))+                    return -1;+                /* cannot recurse because val is a number */+                if (JS_ToArrayLengthFree(ctx, &len1, val, FALSE))+                    return -1;+                if (len1 != len) {+                fail:+                    JS_ThrowRangeError(ctx, "invalid array length");+                    return -1;+                }+            }+        }+        break;+    }+    *plen = len;+    return 0;+}++#define MAX_SAFE_INTEGER (((int64_t)1 << 53) - 1)++static BOOL is_safe_integer(double d)+{+    return isfinite(d) && floor(d) == d &&+        fabs(d) <= (double)MAX_SAFE_INTEGER;+}++int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val)+{+    int64_t v;+    if (JS_ToInt64Sat(ctx, &v, val))+        return -1;+    if (v < 0 || v > MAX_SAFE_INTEGER) {+        JS_ThrowRangeError(ctx, "invalid array index");+        *plen = 0;+        return -1;+    }+    *plen = v;+    return 0;+}++/* convert a value to a length between 0 and MAX_SAFE_INTEGER.+   return -1 for exception */+static __exception int JS_ToLengthFree(JSContext *ctx, int64_t *plen,+                                       JSValue val)+{+    int res = JS_ToInt64Clamp(ctx, plen, val, 0, MAX_SAFE_INTEGER, 0);+    JS_FreeValue(ctx, val);+    return res;+}++/* Note: can return an exception */+static int JS_NumberIsInteger(JSContext *ctx, JSValueConst val)+{+    double d;+    if (!JS_IsNumber(val))+        return FALSE;+    if (unlikely(JS_ToFloat64(ctx, &d, val)))+        return -1;+    return isfinite(d) && floor(d) == d;+}++static BOOL JS_NumberIsNegativeOrMinusZero(JSContext *ctx, JSValueConst val)+{+    uint32_t tag;++    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+        {+            int v;+            v = JS_VALUE_GET_INT(val);+            return (v < 0);+        }+    case JS_TAG_FLOAT64:+        {+            JSFloat64Union u;+            u.d = JS_VALUE_GET_FLOAT64(val);+            return (u.u64 >> 63);+        }+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            /* Note: integer zeros are not necessarily positive */+            return p->num.sign && !bf_is_zero(&p->num);+        }+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            return p->num.sign;+        }+        break;+    case JS_TAG_BIG_DECIMAL:+        {+            JSBigDecimal *p = JS_VALUE_GET_PTR(val);+            return p->num.sign;+        }+        break;+#endif+    default:+        return FALSE;+    }+}++#ifdef CONFIG_BIGNUM++static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)+{+    JSValue ret;+    bf_t a_s, *a;+    char *str;+    int saved_sign;++    a = JS_ToBigInt(ctx, &a_s, val);+    if (!a)+        return JS_EXCEPTION;+    saved_sign = a->sign;+    if (a->expn == BF_EXP_ZERO)+        a->sign = 0;+    str = bf_ftoa(NULL, a, radix, 0, BF_RNDZ | BF_FTOA_FORMAT_FRAC |+                  BF_FTOA_JS_QUIRKS);+    a->sign = saved_sign;+    JS_FreeBigInt(ctx, a, &a_s);+    if (!str)+        return JS_ThrowOutOfMemory(ctx);+    ret = JS_NewString(ctx, str);+    bf_free(ctx->bf_ctx, str);+    return ret;+}++static JSValue js_bigint_to_string(JSContext *ctx, JSValueConst val)+{+    return js_bigint_to_string1(ctx, val, 10);+}++static JSValue js_ftoa(JSContext *ctx, JSValueConst val1, int radix,+                       limb_t prec, bf_flags_t flags)+{+    JSValue val, ret;+    bf_t a_s, *a;+    char *str;+    int saved_sign;++    val = JS_ToNumeric(ctx, val1);+    if (JS_IsException(val))+        return val;+    a = JS_ToBigFloat(ctx, &a_s, val);+    saved_sign = a->sign;+    if (a->expn == BF_EXP_ZERO)+        a->sign = 0;+    flags |= BF_FTOA_JS_QUIRKS;+    if ((flags & BF_FTOA_FORMAT_MASK) == BF_FTOA_FORMAT_FREE_MIN) {+        /* Note: for floating point numbers with a radix which is not+           a power of two, the current precision is used to compute+           the number of digits. */+        if ((radix & (radix - 1)) != 0) {+            bf_t r_s, *r = &r_s;+            int prec, flags1;+            /* must round first */+            if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {+                prec = ctx->fp_env.prec;+                flags1 = ctx->fp_env.flags &+                    (BF_FLAG_SUBNORMAL | (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT));+            } else {+                prec = 53;+                flags1 = bf_set_exp_bits(11) | BF_FLAG_SUBNORMAL;+            }+            bf_init(ctx->bf_ctx, r);+            bf_set(r, a);+            bf_round(r, prec, flags1 | BF_RNDN);+            str = bf_ftoa(NULL, r, radix, prec, flags1 | flags);+            bf_delete(r);+        } else {+            str = bf_ftoa(NULL, a, radix, BF_PREC_INF, flags);+        }+    } else {+        str = bf_ftoa(NULL, a, radix, prec, flags);+    }+    a->sign = saved_sign;+    if (a == &a_s)+        bf_delete(a);+    JS_FreeValue(ctx, val);+    if (!str)+        return JS_ThrowOutOfMemory(ctx);+    ret = JS_NewString(ctx, str);+    bf_free(ctx->bf_ctx, str);+    return ret;+}++static JSValue js_bigfloat_to_string(JSContext *ctx, JSValueConst val)+{+    return js_ftoa(ctx, val, 10, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);+}++static JSValue js_bigdecimal_to_string1(JSContext *ctx, JSValueConst val,+                                        limb_t prec, int flags)+{+    JSValue ret;+    bfdec_t *a;+    char *str;+    int saved_sign;++    a = JS_ToBigDecimal(ctx, val);+    saved_sign = a->sign;+    if (a->expn == BF_EXP_ZERO)+        a->sign = 0;+    str = bfdec_ftoa(NULL, a, prec, flags | BF_FTOA_JS_QUIRKS);+    a->sign = saved_sign;+    if (!str)+        return JS_ThrowOutOfMemory(ctx);+    ret = JS_NewString(ctx, str);+    bf_free(ctx->bf_ctx, str);+    return ret;+}++static JSValue js_bigdecimal_to_string(JSContext *ctx, JSValueConst val)+{+    return js_bigdecimal_to_string1(ctx, val, 0,+                                    BF_RNDZ | BF_FTOA_FORMAT_FREE);+}++#endif /* CONFIG_BIGNUM */++/* 2 <= base <= 36 */+static char *i64toa(char *buf_end, int64_t n, unsigned int base)+{+    char *q = buf_end;+    int digit, is_neg;++    is_neg = 0;+    if (n < 0) {+        is_neg = 1;+        n = -n;+    }+    *--q = '\0';+    do {+        digit = (uint64_t)n % base;+        n = (uint64_t)n / base;+        if (digit < 10)+            digit += '0';+        else+            digit += 'a' - 10;+        *--q = digit;+    } while (n != 0);+    if (is_neg)+        *--q = '-';+    return q;+}++/* buf1 contains the printf result */+static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf,+                     int rounding_mode, char *buf1, int buf1_size)+{+    if (rounding_mode != FE_TONEAREST)+        fesetround(rounding_mode);+    snprintf(buf1, buf1_size, "%+.*e", n_digits - 1, d);+    if (rounding_mode != FE_TONEAREST)+        fesetround(FE_TONEAREST);+    *sign = (buf1[0] == '-');+    /* mantissa */+    buf[0] = buf1[1];+    if (n_digits > 1)+        memcpy(buf + 1, buf1 + 3, n_digits - 1);+    buf[n_digits] = '\0';+    /* exponent */+    *decpt = atoi(buf1 + n_digits + 2 + (n_digits > 1)) + 1;+}++/* maximum buffer size for js_dtoa */+#define JS_DTOA_BUF_SIZE 128++/* needed because ecvt usually limits the number of digits to+   17. Return the number of digits. */+static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf,+                   BOOL is_fixed)+{+    int rounding_mode;+    char buf_tmp[JS_DTOA_BUF_SIZE];++    if (!is_fixed) {+        unsigned int n_digits_min, n_digits_max;+        /* find the minimum amount of digits (XXX: inefficient but simple) */+        n_digits_min = 1;+        n_digits_max = 17;+        while (n_digits_min < n_digits_max) {+            n_digits = (n_digits_min + n_digits_max) / 2;+            js_ecvt1(d, n_digits, decpt, sign, buf, FE_TONEAREST,+                     buf_tmp, sizeof(buf_tmp));+            if (strtod(buf_tmp, NULL) == d) {+                /* no need to keep the trailing zeros */+                while (n_digits >= 2 && buf[n_digits - 1] == '0')+                    n_digits--;+                n_digits_max = n_digits;+            } else {+                n_digits_min = n_digits + 1;+            }+        }+        n_digits = n_digits_max;+        rounding_mode = FE_TONEAREST;+    } else {+        rounding_mode = FE_TONEAREST;+#ifdef CONFIG_PRINTF_RNDN+        {+            char buf1[JS_DTOA_BUF_SIZE], buf2[JS_DTOA_BUF_SIZE];+            int decpt1, sign1, decpt2, sign2;+            /* The JS rounding is specified as round to nearest ties away+               from zero (RNDNA), but in printf the "ties" case is not+               specified (for example it is RNDN for glibc, RNDNA for+               Windows), so we must round manually. */+            js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_TONEAREST,+                     buf_tmp, sizeof(buf_tmp));+            /* XXX: could use 2 digits to reduce the average running time */+            if (buf1[n_digits] == '5') {+                js_ecvt1(d, n_digits + 1, &decpt1, &sign1, buf1, FE_DOWNWARD,+                         buf_tmp, sizeof(buf_tmp));+                js_ecvt1(d, n_digits + 1, &decpt2, &sign2, buf2, FE_UPWARD,+                         buf_tmp, sizeof(buf_tmp));+                if (memcmp(buf1, buf2, n_digits + 1) == 0 && decpt1 == decpt2) {+                    /* exact result: round away from zero */+                    if (sign1)+                        rounding_mode = FE_DOWNWARD;+                    else+                        rounding_mode = FE_UPWARD;+                }+            }+        }+#endif /* CONFIG_PRINTF_RNDN */+    }+    js_ecvt1(d, n_digits, decpt, sign, buf, rounding_mode,+             buf_tmp, sizeof(buf_tmp));+    return n_digits;+}++static int js_fcvt1(char *buf, int buf_size, double d, int n_digits,+                    int rounding_mode)+{+    int n;+    if (rounding_mode != FE_TONEAREST)+        fesetround(rounding_mode);+    n = snprintf(buf, buf_size, "%.*f", n_digits, d);+    if (rounding_mode != FE_TONEAREST)+        fesetround(FE_TONEAREST);+    assert(n < buf_size);+    return n;+}++static void js_fcvt(char *buf, int buf_size, double d, int n_digits)+{+    int rounding_mode;+    rounding_mode = FE_TONEAREST;+#ifdef CONFIG_PRINTF_RNDN+    {+        int n1, n2;+        char buf1[JS_DTOA_BUF_SIZE];+        char buf2[JS_DTOA_BUF_SIZE];++        /* The JS rounding is specified as round to nearest ties away from+           zero (RNDNA), but in printf the "ties" case is not specified+           (for example it is RNDN for glibc, RNDNA for Windows), so we+           must round manually. */+        n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_TONEAREST);+        rounding_mode = FE_TONEAREST;+        /* XXX: could use 2 digits to reduce the average running time */+        if (buf1[n1 - 1] == '5') {+            n1 = js_fcvt1(buf1, sizeof(buf1), d, n_digits + 1, FE_DOWNWARD);+            n2 = js_fcvt1(buf2, sizeof(buf2), d, n_digits + 1, FE_UPWARD);+            if (n1 == n2 && memcmp(buf1, buf2, n1) == 0) {+                /* exact result: round away from zero */+                if (buf1[0] == '-')+                    rounding_mode = FE_DOWNWARD;+                else+                    rounding_mode = FE_UPWARD;+            }+        }+    }+#endif /* CONFIG_PRINTF_RNDN */+    js_fcvt1(buf, buf_size, d, n_digits, rounding_mode);+}++/* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */+/* use as many digits as necessary */+#define JS_DTOA_VAR_FORMAT   (0 << 0)+/* use n_digits significant digits (1 <= n_digits <= 101) */+#define JS_DTOA_FIXED_FORMAT (1 << 0)+/* force fractional format: [-]dd.dd with n_digits fractional digits */+#define JS_DTOA_FRAC_FORMAT  (2 << 0)+/* force exponential notation either in fixed or variable format */+#define JS_DTOA_FORCE_EXP    (1 << 2)++/* XXX: slow and maybe not fully correct. Use libbf when it is fast enough.+   XXX: radix != 10 is only supported for small integers+*/+static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags)+{+    char *q;++    if (!isfinite(d)) {+        if (isnan(d)) {+            strcpy(buf, "NaN");+        } else {+            q = buf;+            if (d < 0)+                *q++ = '-';+            strcpy(q, "Infinity");+        }+    } else if (flags == JS_DTOA_VAR_FORMAT) {+        int64_t i64;+        char buf1[70], *ptr;+        i64 = (int64_t)d;+        if (d != i64 || i64 > MAX_SAFE_INTEGER || i64 < -MAX_SAFE_INTEGER)+            goto generic_conv;+        /* fast path for integers */+        ptr = i64toa(buf1 + sizeof(buf1), i64, radix);+        strcpy(buf, ptr);+    } else {+        if (d == 0.0)+            d = 0.0; /* convert -0 to 0 */+        if (flags == JS_DTOA_FRAC_FORMAT) {+            js_fcvt(buf, JS_DTOA_BUF_SIZE, d, n_digits);+        } else {+            char buf1[JS_DTOA_BUF_SIZE];+            int sign, decpt, k, n, i, p, n_max;+            BOOL is_fixed;+        generic_conv:+            is_fixed = ((flags & 3) == JS_DTOA_FIXED_FORMAT);+            if (is_fixed) {+                n_max = n_digits;+            } else {+                n_max = 21;+            }+            /* the number has k digits (k >= 1) */+            k = js_ecvt(d, n_digits, &decpt, &sign, buf1, is_fixed);+            n = decpt; /* d=10^(n-k)*(buf1) i.e. d= < x.yyyy 10^(n-1) */+            q = buf;+            if (sign)+                *q++ = '-';+            if (flags & JS_DTOA_FORCE_EXP)+                goto force_exp;+            if (n >= 1 && n <= n_max) {+                if (k <= n) {+                    memcpy(q, buf1, k);+                    q += k;+                    for(i = 0; i < (n - k); i++)+                        *q++ = '0';+                    *q = '\0';+                } else {+                    /* k > n */+                    memcpy(q, buf1, n);+                    q += n;+                    *q++ = '.';+                    for(i = 0; i < (k - n); i++)+                        *q++ = buf1[n + i];+                    *q = '\0';+                }+            } else if (n >= -5 && n <= 0) {+                *q++ = '0';+                *q++ = '.';+                for(i = 0; i < -n; i++)+                    *q++ = '0';+                memcpy(q, buf1, k);+                q += k;+                *q = '\0';+            } else {+            force_exp:+                /* exponential notation */+                *q++ = buf1[0];+                if (k > 1) {+                    *q++ = '.';+                    for(i = 1; i < k; i++)+                        *q++ = buf1[i];+                }+                *q++ = 'e';+                p = n - 1;+                if (p >= 0)+                    *q++ = '+';+                sprintf(q, "%d", p);+            }+        }+    }+}++static JSValue js_dtoa(JSContext *ctx,+                       double d, int radix, int n_digits, int flags)+{+    char buf[JS_DTOA_BUF_SIZE];+    js_dtoa1(buf, d, radix, n_digits, flags);+    return JS_NewString(ctx, buf);+}++JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToPropertyKey)+{+    uint32_t tag;+    const char *str;+    char buf[32];++    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_STRING:+        return JS_DupValue(ctx, val);+    case JS_TAG_INT:+        snprintf(buf, sizeof(buf), "%d", JS_VALUE_GET_INT(val));+        str = buf;+        goto new_string;+    case JS_TAG_BOOL:+        return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ?+                          JS_ATOM_true : JS_ATOM_false);+    case JS_TAG_NULL:+        return JS_AtomToString(ctx, JS_ATOM_null);+    case JS_TAG_UNDEFINED:+        return JS_AtomToString(ctx, JS_ATOM_undefined);+    case JS_TAG_EXCEPTION:+        return JS_EXCEPTION;+    case JS_TAG_OBJECT:+        {+            JSValue val1, ret;+            val1 = JS_ToPrimitive(ctx, val, HINT_STRING);+            if (JS_IsException(val1))+                return val1;+            ret = JS_ToStringInternal(ctx, val1, is_ToPropertyKey);+            JS_FreeValue(ctx, val1);+            return ret;+        }+        break;+    case JS_TAG_FUNCTION_BYTECODE:+        str = "[function bytecode]";+        goto new_string;+    case JS_TAG_SYMBOL:+        if (is_ToPropertyKey) {+            return JS_DupValue(ctx, val);+        } else {+            return JS_ThrowTypeError(ctx, "cannot convert symbol to string");+        }+    case JS_TAG_FLOAT64:+        return js_dtoa(ctx, JS_VALUE_GET_FLOAT64(val), 10, 0,+                       JS_DTOA_VAR_FORMAT);+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        return ctx->rt->bigint_ops.to_string(ctx, val);+    case JS_TAG_BIG_FLOAT:+        return ctx->rt->bigfloat_ops.to_string(ctx, val);+    case JS_TAG_BIG_DECIMAL:+        return ctx->rt->bigdecimal_ops.to_string(ctx, val);+#endif+    default:+        str = "[unsupported type]";+    new_string:+        return JS_NewString(ctx, str);+    }+}++JSValue JS_ToString(JSContext *ctx, JSValueConst val)+{+    return JS_ToStringInternal(ctx, val, FALSE);+}++static JSValue JS_ToStringFree(JSContext *ctx, JSValue val)+{+    JSValue ret;+    ret = JS_ToString(ctx, val);+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue JS_ToLocaleStringFree(JSContext *ctx, JSValue val)+{+    if (JS_IsUndefined(val) || JS_IsNull(val))+        return JS_ToStringFree(ctx, val);+    return JS_InvokeFree(ctx, val, JS_ATOM_toLocaleString, 0, NULL);+}++JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val)+{+    return JS_ToStringInternal(ctx, val, TRUE);+}++static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)+{+    uint32_t tag = JS_VALUE_GET_TAG(val);+    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)+        return JS_ThrowTypeError(ctx, "null or undefined are forbidden");+    return JS_ToString(ctx, val);+}++static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)+{+    JSValue val;+    JSString *p;+    int i;+    uint32_t c;+    StringBuffer b_s, *b = &b_s;+    char buf[16];++    val = JS_ToStringCheckObject(ctx, val1);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_STRING(val);++    if (string_buffer_init(ctx, b, p->len + 2))+        goto fail;++    if (string_buffer_putc8(b, '\"'))+        goto fail;+    for(i = 0; i < p->len; ) {+        c = string_getc(p, &i);+        switch(c) {+        case '\t':+            c = 't';+            goto quote;+        case '\r':+            c = 'r';+            goto quote;+        case '\n':+            c = 'n';+            goto quote;+        case '\b':+            c = 'b';+            goto quote;+        case '\f':+            c = 'f';+            goto quote;+        case '\"':+        case '\\':+        quote:+            if (string_buffer_putc8(b, '\\'))+                goto fail;+            if (string_buffer_putc8(b, c))+                goto fail;+            break;+        default:+            if (c < 32 || (c >= 0xd800 && c < 0xe000)) {+                snprintf(buf, sizeof(buf), "\\u%04x", c);+                if (string_buffer_puts8(b, buf))+                    goto fail;+            } else {+                if (string_buffer_putc(b, c))+                    goto fail;+            }+            break;+        }+    }+    if (string_buffer_putc8(b, '\"'))+        goto fail;+    JS_FreeValue(ctx, val);+    return string_buffer_end(b);+ fail:+    JS_FreeValue(ctx, val);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)+{+    printf("%14s %4s %4s %14s %10s %s\n",+           "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");+}++/* for debug only: dump an object without side effect */+static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)+{+    uint32_t i;+    char atom_buf[ATOM_GET_STR_BUF_SIZE];+    JSShape *sh;+    JSShapeProperty *prs;+    JSProperty *pr;+    BOOL is_first = TRUE;++    /* XXX: should encode atoms with special characters */+    sh = p->shape; /* the shape can be NULL while freeing an object */+    printf("%14p %4d ",+           (void *)p,+           p->header.ref_count);+    if (sh) {+        printf("%3d%c %14p ",+               sh->header.ref_count,+               " *"[sh->is_hashed],+               (void *)sh->proto);+    } else {+        printf("%3s  %14s ", "-", "-");+    }+    printf("%10s ",+           JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name));+    if (p->is_exotic && p->fast_array) {+        printf("[ ");+        for(i = 0; i < p->u.array.count; i++) {+            if (i != 0)+                printf(", ");+            switch (p->class_id) {+            case JS_CLASS_ARRAY:+            case JS_CLASS_ARGUMENTS:+                JS_DumpValueShort(rt, p->u.array.u.values[i]);+                break;+            case JS_CLASS_UINT8C_ARRAY:+            case JS_CLASS_INT8_ARRAY:+            case JS_CLASS_UINT8_ARRAY:+            case JS_CLASS_INT16_ARRAY:+            case JS_CLASS_UINT16_ARRAY:+            case JS_CLASS_INT32_ARRAY:+            case JS_CLASS_UINT32_ARRAY:+#ifdef CONFIG_BIGNUM+            case JS_CLASS_BIG_INT64_ARRAY:+            case JS_CLASS_BIG_UINT64_ARRAY:+#endif+            case JS_CLASS_FLOAT32_ARRAY:+            case JS_CLASS_FLOAT64_ARRAY:+                {+                    int size = 1 << typed_array_size_log2(p->class_id);+                    const uint8_t *b = p->u.array.u.uint8_ptr + i * size;+                    while (size-- > 0)+                        printf("%02X", *b++);+                }+                break;+            }+        }+        printf(" ] ");+    }++    if (sh) {+        printf("{ ");+        for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {+            if (prs->atom != JS_ATOM_NULL) {+                pr = &p->prop[i];+                if (!is_first)+                    printf(", ");+                printf("%s: ",+                       JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom));+                if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {+                    printf("[getset %p %p]", (void *)pr->u.getset.getter,+                           (void *)pr->u.getset.setter);+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {+                    printf("[varref %p]", (void *)pr->u.var_ref);+                } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {+                    printf("[autoinit %p %d %p]",+                           (void *)js_autoinit_get_realm(pr),+                           js_autoinit_get_id(pr),+                           (void *)pr->u.init.opaque);+                } else {+                    JS_DumpValueShort(rt, pr->u.value);+                }+                is_first = FALSE;+            }+        }+        printf(" }");+    }+    +    if (js_class_has_bytecode(p->class_id)) {+        JSFunctionBytecode *b = p->u.func.function_bytecode;+        JSVarRef **var_refs;+        if (b->closure_var_count) {+            var_refs = p->u.func.var_refs;+            printf(" Closure:");+            for(i = 0; i < b->closure_var_count; i++) {+                printf(" ");+                JS_DumpValueShort(rt, var_refs[i]->value);+            }+            if (p->u.func.home_object) {+                printf(" HomeObject: ");+                JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));+            }+        }+    }+    printf("\n");+}++static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)+{+    if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {+        JS_DumpObject(rt, (JSObject *)p);+    } else {+        printf("%14p %4d ",+               (void *)p,+               p->ref_count);+        switch(p->gc_obj_type) {+        case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:+            printf("[function bytecode]");+            break;+        case JS_GC_OBJ_TYPE_SHAPE:+            printf("[shape]");+            break;+        case JS_GC_OBJ_TYPE_VAR_REF:+            printf("[var_ref]");+            break;+        case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:+            printf("[async_function]");+            break;+        case JS_GC_OBJ_TYPE_JS_CONTEXT:+            printf("[js_context]");+            break;+        default:+            printf("[unknown %d]", p->gc_obj_type);+            break;+        }+        printf("\n");+    }+}++static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,+                                                      JSValueConst val)+{+    uint32_t tag = JS_VALUE_GET_NORM_TAG(val);+    const char *str;++    switch(tag) {+    case JS_TAG_INT:+        printf("%d", JS_VALUE_GET_INT(val));+        break;+    case JS_TAG_BOOL:+        if (JS_VALUE_GET_BOOL(val))+            str = "true";+        else+            str = "false";+        goto print_str;+    case JS_TAG_NULL:+        str = "null";+        goto print_str;+    case JS_TAG_EXCEPTION:+        str = "exception";+        goto print_str;+    case JS_TAG_UNINITIALIZED:+        str = "uninitialized";+        goto print_str;+    case JS_TAG_UNDEFINED:+        str = "undefined";+    print_str:+        printf("%s", str);+        break;+    case JS_TAG_FLOAT64:+        printf("%.14g", JS_VALUE_GET_FLOAT64(val));+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            char *str;+            str = bf_ftoa(NULL, &p->num, 10, 0,+                          BF_RNDZ | BF_FTOA_FORMAT_FRAC);+            printf("%sn", str);+            bf_realloc(&rt->bf_ctx, str, 0);+        }+        break;+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            char *str;+            str = bf_ftoa(NULL, &p->num, 16, BF_PREC_INF,+                          BF_RNDZ | BF_FTOA_FORMAT_FREE | BF_FTOA_ADD_PREFIX);+            printf("%sl", str);+            bf_free(&rt->bf_ctx, str);+        }+        break;+    case JS_TAG_BIG_DECIMAL:+        {+            JSBigDecimal *p = JS_VALUE_GET_PTR(val);+            char *str;+            str = bfdec_ftoa(NULL, &p->num, BF_PREC_INF,+                             BF_RNDZ | BF_FTOA_FORMAT_FREE);+            printf("%sm", str);+            bf_free(&rt->bf_ctx, str);+        }+        break;+#endif+    case JS_TAG_STRING:+        {+            JSString *p;+            p = JS_VALUE_GET_STRING(val);+            JS_DumpString(rt, p);+        }+        break;+    case JS_TAG_FUNCTION_BYTECODE:+        {+            JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);+            char buf[ATOM_GET_STR_BUF_SIZE];+            printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));+        }+        break;+    case JS_TAG_OBJECT:+        {+            JSObject *p = JS_VALUE_GET_OBJ(val);+            JSAtom atom = rt->class_array[p->class_id].class_name;+            char atom_buf[ATOM_GET_STR_BUF_SIZE];+            printf("[%s %p]",+                   JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p);+        }+        break;+    case JS_TAG_SYMBOL:+        {+            JSAtomStruct *p = JS_VALUE_GET_PTR(val);+            char atom_buf[ATOM_GET_STR_BUF_SIZE];+            printf("Symbol(%s)",+                   JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p)));+        }+        break;+    case JS_TAG_MODULE:+        printf("[module]");+        break;+    default:+        printf("[unknown tag %d]", tag);+        break;+    }+}++static __maybe_unused void JS_DumpValue(JSContext *ctx,+                                                 JSValueConst val)+{+    JS_DumpValueShort(ctx->rt, val);+}++static __maybe_unused void JS_PrintValue(JSContext *ctx,+                                                  const char *str,+                                                  JSValueConst val)+{+    printf("%s=", str);+    JS_DumpValueShort(ctx->rt, val);+    printf("\n");+}++/* return -1 if exception (proxy case) or TRUE/FALSE */+int JS_IsArray(JSContext *ctx, JSValueConst val)+{+    JSObject *p;+    if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(val);+        if (unlikely(p->class_id == JS_CLASS_PROXY))+            return js_proxy_isArray(ctx, val);+        else+            return p->class_id == JS_CLASS_ARRAY;+    } else {+        return FALSE;+    }+}++static double js_pow(double a, double b)+{+    if (unlikely(!isfinite(b)) && fabs(a) == 1) {+        /* not compatible with IEEE 754 */+        return JS_FLOAT64_NAN;+    } else {+        return pow(a, b);+    }+}++#ifdef CONFIG_BIGNUM++JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v)+{+    JSValue val;+    bf_t *a;+    val = JS_NewBigInt(ctx);+    if (JS_IsException(val))+        return val;+    a = JS_GetBigInt(val);+    if (bf_set_si(a, v)) {+        JS_FreeValue(ctx, val);+        return JS_ThrowOutOfMemory(ctx);+    }+    return val;+}++JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)+{+    if (is_math_mode(ctx) &&+        v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {+        return JS_NewInt64(ctx, v);+    } else {+        return JS_NewBigInt64_1(ctx, v);+    }+}++JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)+{+    JSValue val;+    if (is_math_mode(ctx) && v <= MAX_SAFE_INTEGER) {+        val = JS_NewInt64(ctx, v);+    } else {+        bf_t *a;+        val = JS_NewBigInt(ctx);+        if (JS_IsException(val))+            return val;+        a = JS_GetBigInt(val);+        if (bf_set_ui(a, v)) {+            JS_FreeValue(ctx, val);+            return JS_ThrowOutOfMemory(ctx);+        }+    }+    return val;+}++/* if the returned bigfloat is allocated it is equal to+   'buf'. Otherwise it is a pointer to the bigfloat in 'val'. Return+   NULL in case of error. */+static bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val)+{+    uint32_t tag;+    bf_t *r;+    JSBigFloat *p;++    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+        r = buf;+        bf_init(ctx->bf_ctx, r);+        if (bf_set_si(r, JS_VALUE_GET_INT(val)))+            goto fail;+        break;+    case JS_TAG_FLOAT64:+        r = buf;+        bf_init(ctx->bf_ctx, r);+        if (bf_set_float64(r, JS_VALUE_GET_FLOAT64(val))) {+        fail:+            bf_delete(r);+            return NULL;+        }+        break;+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        p = JS_VALUE_GET_PTR(val);+        r = &p->num;+        break;+    case JS_TAG_UNDEFINED:+    default:+        r = buf;+        bf_init(ctx->bf_ctx, r);+        bf_set_nan(r);+        break;+    }+    return r;+}++/* return NULL if invalid type */+static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val)+{+    uint32_t tag;+    JSBigDecimal *p;+    bfdec_t *r;+    +    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_BIG_DECIMAL:+        p = JS_VALUE_GET_PTR(val);+        r = &p->num;+        break;+    default:+        JS_ThrowTypeError(ctx, "bigdecimal expected");+        r = NULL;+        break;+    }+    return r;+}++/* return NaN if bad bigint literal */+static JSValue JS_StringToBigInt(JSContext *ctx, JSValue val)+{+    const char *str, *p;+    size_t len;+    int flags;+    +    str = JS_ToCStringLen(ctx, &len, val);+    JS_FreeValue(ctx, val);+    if (!str)+        return JS_EXCEPTION;+    p = str;+    p += skip_spaces(p);+    if ((p - str) == len) {+        val = JS_NewBigInt64(ctx, 0);+    } else {+        flags = ATOD_INT_ONLY | ATOD_ACCEPT_BIN_OCT | ATOD_TYPE_BIG_INT;+        if (is_math_mode(ctx))+            flags |= ATOD_MODE_BIGINT;+        val = js_atof(ctx, p, &p, 0, flags);+        p += skip_spaces(p);+        if (!JS_IsException(val)) {+            if ((p - str) != len) {+                JS_FreeValue(ctx, val);+                val = JS_NAN;+            }+        }+    }+    JS_FreeCString(ctx, str);+    return val;+}++static JSValue JS_StringToBigIntErr(JSContext *ctx, JSValue val)+{+    val = JS_StringToBigInt(ctx, val);+    if (JS_VALUE_IS_NAN(val))+        return JS_ThrowSyntaxError(ctx, "invalid bigint literal");+    return val;+}++/* if the returned bigfloat is allocated it is equal to+   'buf'. Otherwise it is a pointer to the bigfloat in 'val'. */+static bf_t *JS_ToBigIntFree(JSContext *ctx, bf_t *buf, JSValue val)+{+    uint32_t tag;+    bf_t *r;+    JSBigFloat *p;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        if (!is_math_mode(ctx))+            goto fail;+        /* fall tru */+    case JS_TAG_BOOL:+        r = buf;+        bf_init(ctx->bf_ctx, r);+        bf_set_si(r, JS_VALUE_GET_INT(val));+        break;+    case JS_TAG_FLOAT64:+        {+            double d = JS_VALUE_GET_FLOAT64(val);+            if (!is_math_mode(ctx))+                goto fail;+            if (!isfinite(d))+                goto fail;+            r = buf;+            bf_init(ctx->bf_ctx, r);+            d = trunc(d);+            bf_set_float64(r, d);+        }+        break;+    case JS_TAG_BIG_INT:+        p = JS_VALUE_GET_PTR(val);+        r = &p->num;+        break;+    case JS_TAG_BIG_FLOAT:+        if (!is_math_mode(ctx))+            goto fail;+        p = JS_VALUE_GET_PTR(val);+        if (!bf_is_finite(&p->num))+            goto fail;+        r = buf;+        bf_init(ctx->bf_ctx, r);+        bf_set(r, &p->num);+        bf_rint(r, BF_RNDZ);+        JS_FreeValue(ctx, val);+        break;+    case JS_TAG_STRING:+        val = JS_StringToBigIntErr(ctx, val);+        if (JS_IsException(val))+            return NULL;+        goto redo;+    case JS_TAG_OBJECT:+        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);+        if (JS_IsException(val))+            return NULL;+        goto redo;+    default:+    fail:+        JS_FreeValue(ctx, val);+        JS_ThrowTypeError(ctx, "cannot convert to bigint");+        return NULL;+    }+    return r;+}++static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val)+{+    return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val));+}++static __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val)+{+    if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) {+        return val;+    } else {+        bf_t a_s, *a, *r;+        int ret;+        JSValue res; ++        res = JS_NewBigInt(ctx);+        if (JS_IsException(res))+            return JS_EXCEPTION;+        a = JS_ToBigIntFree(ctx, &a_s, val);+        if (!a) {+            JS_FreeValue(ctx, res);+            return JS_EXCEPTION;+        }+        r = JS_GetBigInt(res);+        ret = bf_set(r, a);+        JS_FreeBigInt(ctx, a, &a_s);+        if (ret) {+            JS_FreeValue(ctx, res);+            return JS_ThrowOutOfMemory(ctx);+        }+        return JS_CompactBigInt(ctx, res);+    }+}++/* free the bf_t allocated by JS_ToBigInt */+static void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf)+{+    if (a == buf) {+        bf_delete(a);+    } else {+        JSBigFloat *p = (JSBigFloat *)((uint8_t *)a -+                                       offsetof(JSBigFloat, num));+        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_BIG_FLOAT, p));+    }+}++/* XXX: merge with JS_ToInt64Free with a specific flag */+static int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val)+{+    bf_t a_s, *a;++    a = JS_ToBigIntFree(ctx, &a_s, val);+    if (!a) {+        *pres = 0;+        return -1;+    }+    bf_get_int64(pres, a, BF_GET_INT_MOD);+    JS_FreeBigInt(ctx, a, &a_s);+    return 0;+}++int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)+{+    return JS_ToBigInt64Free(ctx, pres, JS_DupValue(ctx, val));+}++static JSBigFloat *js_new_bf(JSContext *ctx)+{+    JSBigFloat *p;+    p = js_malloc(ctx, sizeof(*p));+    if (!p)+        return NULL;+    p->header.ref_count = 1;+    bf_init(ctx->bf_ctx, &p->num);+    return p;+}++static JSValue JS_NewBigFloat(JSContext *ctx)+{+    JSBigFloat *p;+    p = js_malloc(ctx, sizeof(*p));+    if (!p)+        return JS_EXCEPTION;+    p->header.ref_count = 1;+    bf_init(ctx->bf_ctx, &p->num);+    return JS_MKPTR(JS_TAG_BIG_FLOAT, p);+}++static JSValue JS_NewBigDecimal(JSContext *ctx)+{+    JSBigDecimal *p;+    p = js_malloc(ctx, sizeof(*p));+    if (!p)+        return JS_EXCEPTION;+    p->header.ref_count = 1;+    bfdec_init(ctx->bf_ctx, &p->num);+    return JS_MKPTR(JS_TAG_BIG_DECIMAL, p);+}++static JSValue JS_NewBigInt(JSContext *ctx)+{+    JSBigFloat *p;+    p = js_malloc(ctx, sizeof(*p));+    if (!p)+        return JS_EXCEPTION;+    p->header.ref_count = 1;+    bf_init(ctx->bf_ctx, &p->num);+    return JS_MKPTR(JS_TAG_BIG_INT, p);+}++static JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val,+                                 BOOL convert_to_safe_integer)+{+    int64_t v;+    bf_t *a;+    +    if (JS_VALUE_GET_TAG(val) != JS_TAG_BIG_INT)+        return val; /* fail safe */+    a = JS_GetBigInt(val);+    if (convert_to_safe_integer && bf_get_int64(&v, a, 0) == 0 &&+        v >= -MAX_SAFE_INTEGER && v <= MAX_SAFE_INTEGER) {+        JS_FreeValue(ctx, val);+        return JS_NewInt64(ctx, v);+    } else if (a->expn == BF_EXP_ZERO && a->sign) {+        JSBigFloat *p = JS_VALUE_GET_PTR(val);+        assert(p->header.ref_count == 1);+        a->sign = 0;+    }+    return val;+}++/* Convert the big int to a safe integer if in math mode. normalize+   the zero representation. Could also be used to convert the bigint+   to a short bigint value. The reference count of the value must be+   1. Cannot fail */+static JSValue JS_CompactBigInt(JSContext *ctx, JSValue val)+{+    return JS_CompactBigInt1(ctx, val, is_math_mode(ctx));+}++/* must be kept in sync with JSOverloadableOperatorEnum */+/* XXX: use atoms ? */+static const char js_overloadable_operator_names[JS_OVOP_COUNT][4] = {+    "+",+    "-",+    "*",+    "/",+    "%",+    "**",+    "|",+    "&",+    "^",+    "<<",+    ">>",+    ">>>",+    "==",+    "<",+    "pos",+    "neg",+    "++",+    "--",+    "~",+};++static int get_ovop_from_opcode(OPCodeEnum op)+{+    switch(op) {+    case OP_add:+        return JS_OVOP_ADD;+    case OP_sub:+        return JS_OVOP_SUB;+    case OP_mul:+        return JS_OVOP_MUL;+    case OP_div:+        return JS_OVOP_DIV;+    case OP_mod:+    case OP_math_mod:+        return JS_OVOP_MOD;+    case OP_pow:+        return JS_OVOP_POW;+    case OP_or:+        return JS_OVOP_OR;+    case OP_and:+        return JS_OVOP_AND;+    case OP_xor:+        return JS_OVOP_XOR;+    case OP_shl:+        return JS_OVOP_SHL;+    case OP_sar:+        return JS_OVOP_SAR;+    case OP_shr:+        return JS_OVOP_SHR;+    case OP_eq:+    case OP_neq:+        return JS_OVOP_EQ;+    case OP_lt:+    case OP_lte:+    case OP_gt:+    case OP_gte:+        return JS_OVOP_LESS;+    case OP_plus:+        return JS_OVOP_POS;+    case OP_neg:+        return JS_OVOP_NEG;+    case OP_inc:+        return JS_OVOP_INC;+    case OP_dec:+        return JS_OVOP_DEC;+    default:+        abort();+    }+}++/* return NULL if not present */+static JSObject *find_binary_op(JSBinaryOperatorDef *def,+                                uint32_t operator_index,+                                JSOverloadableOperatorEnum op)+{+    JSBinaryOperatorDefEntry *ent;+    int i;+    for(i = 0; i < def->count; i++) {+        ent = &def->tab[i];+        if (ent->operator_index == operator_index)+            return ent->ops[op];+    }+    return NULL;+}++/* return -1 if exception, 0 if no operator overloading, 1 if+   overloaded operator called */+static __exception int js_call_binary_op_fallback(JSContext *ctx,+                                                  JSValue *pret,+                                                  JSValueConst op1,+                                                  JSValueConst op2,+                                                  OPCodeEnum op,+                                                  BOOL is_numeric,+                                                  int hint)+{+    JSValue opset1_obj, opset2_obj, method, ret, new_op1, new_op2;+    JSOperatorSetData *opset1, *opset2;+    JSOverloadableOperatorEnum ovop;+    JSObject *p;+    JSValueConst args[2];+    +    if (!ctx->allow_operator_overloading)+        return 0;+    +    opset2_obj = JS_UNDEFINED;+    opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);+    if (JS_IsException(opset1_obj))+        goto exception;+    if (JS_IsUndefined(opset1_obj))+        return 0;+    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);+    if (!opset1)+        goto exception;++    opset2_obj = JS_GetProperty(ctx, op2, JS_ATOM_Symbol_operatorSet);+    if (JS_IsException(opset2_obj))+        goto exception;+    if (JS_IsUndefined(opset2_obj)) {+        JS_FreeValue(ctx, opset1_obj);+        return 0;+    }+    opset2 = JS_GetOpaque2(ctx, opset2_obj, JS_CLASS_OPERATOR_SET);+    if (!opset2)+        goto exception;++    if (opset1->is_primitive && opset2->is_primitive) {+        JS_FreeValue(ctx, opset1_obj);+        JS_FreeValue(ctx, opset2_obj);+        return 0;+    }++    ovop = get_ovop_from_opcode(op);+    +    if (opset1->operator_counter == opset2->operator_counter) {+        p = opset1->self_ops[ovop];+    } else if (opset1->operator_counter > opset2->operator_counter) {+        p = find_binary_op(&opset1->left, opset2->operator_counter, ovop);+    } else {+        p = find_binary_op(&opset2->right, opset1->operator_counter, ovop);+    }+    if (!p) {+        JS_ThrowTypeError(ctx, "operator %s: no function defined",+                          js_overloadable_operator_names[ovop]);+        goto exception;+    }++    if (opset1->is_primitive) {+        if (is_numeric) {+            new_op1 = JS_ToNumeric(ctx, op1);+        } else {+            new_op1 = JS_ToPrimitive(ctx, op1, hint);+        }+        if (JS_IsException(new_op1))+            goto exception;+    } else {+        new_op1 = JS_DupValue(ctx, op1);+    }+    +    if (opset2->is_primitive) {+        if (is_numeric) {+            new_op2 = JS_ToNumeric(ctx, op2);+        } else {+            new_op2 = JS_ToPrimitive(ctx, op2, hint);+        }+        if (JS_IsException(new_op2)) {+            JS_FreeValue(ctx, new_op1);+            goto exception;+        }+    } else {+        new_op2 = JS_DupValue(ctx, op2);+    }++    /* XXX: could apply JS_ToPrimitive() if primitive type so that the+       operator function does not get a value object */+    +    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+    if (ovop == JS_OVOP_LESS && (op == OP_lte || op == OP_gt)) {+        args[0] = new_op2;+        args[1] = new_op1;+    } else {+        args[0] = new_op1;+        args[1] = new_op2;+    }+    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);+    JS_FreeValue(ctx, new_op1);+    JS_FreeValue(ctx, new_op2);+    if (JS_IsException(ret))+        goto exception;+    if (ovop == JS_OVOP_EQ) {+        BOOL res = JS_ToBoolFree(ctx, ret);+        if (op == OP_neq)+            res ^= 1;+        ret = JS_NewBool(ctx, res);+    } else if (ovop == JS_OVOP_LESS) {+        if (JS_IsUndefined(ret)) {+            ret = JS_FALSE;+        } else {+            BOOL res = JS_ToBoolFree(ctx, ret);+            if (op == OP_lte || op == OP_gte)+                res ^= 1;+            ret = JS_NewBool(ctx, res);+        }+    }+    JS_FreeValue(ctx, opset1_obj);+    JS_FreeValue(ctx, opset2_obj);+    *pret = ret;+    return 1;+ exception:+    JS_FreeValue(ctx, opset1_obj);+    JS_FreeValue(ctx, opset2_obj);+    *pret = JS_UNDEFINED;+    return -1;+}++/* try to call the operation on the operatorSet field of 'obj'. Only+   used for "/" and "**" on the BigInt prototype in math mode */+static __exception int js_call_binary_op_simple(JSContext *ctx,+                                                JSValue *pret,+                                                JSValueConst obj,+                                                JSValueConst op1,+                                                JSValueConst op2,+                                                OPCodeEnum op)+{+    JSValue opset1_obj, method, ret, new_op1, new_op2;+    JSOperatorSetData *opset1;+    JSOverloadableOperatorEnum ovop;+    JSObject *p;+    JSValueConst args[2];++    opset1_obj = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);+    if (JS_IsException(opset1_obj))+        goto exception;+    if (JS_IsUndefined(opset1_obj))+        return 0;+    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);+    if (!opset1)+        goto exception;+    ovop = get_ovop_from_opcode(op);++    p = opset1->self_ops[ovop];+    if (!p) {+        JS_FreeValue(ctx, opset1_obj);+        return 0;+    }++    new_op1 = JS_ToNumeric(ctx, op1);+    if (JS_IsException(new_op1))+        goto exception;+    new_op2 = JS_ToNumeric(ctx, op2);+    if (JS_IsException(new_op2)) {+        JS_FreeValue(ctx, new_op1);+        goto exception;+    }++    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+    args[0] = new_op1;+    args[1] = new_op2;+    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 2, args);+    JS_FreeValue(ctx, new_op1);+    JS_FreeValue(ctx, new_op2);+    if (JS_IsException(ret))+        goto exception;+    JS_FreeValue(ctx, opset1_obj);+    *pret = ret;+    return 1;+ exception:+    JS_FreeValue(ctx, opset1_obj);+    *pret = JS_UNDEFINED;+    return -1;+}++/* return -1 if exception, 0 if no operator overloading, 1 if+   overloaded operator called */+static __exception int js_call_unary_op_fallback(JSContext *ctx,+                                                 JSValue *pret,+                                                 JSValueConst op1,+                                                 OPCodeEnum op)+{+    JSValue opset1_obj, method, ret;+    JSOperatorSetData *opset1;+    JSOverloadableOperatorEnum ovop;+    JSObject *p;++    if (!ctx->allow_operator_overloading)+        return 0;+    +    opset1_obj = JS_GetProperty(ctx, op1, JS_ATOM_Symbol_operatorSet);+    if (JS_IsException(opset1_obj))+        goto exception;+    if (JS_IsUndefined(opset1_obj))+        return 0;+    opset1 = JS_GetOpaque2(ctx, opset1_obj, JS_CLASS_OPERATOR_SET);+    if (!opset1)+        goto exception;+    if (opset1->is_primitive) {+        JS_FreeValue(ctx, opset1_obj);+        return 0;+    }++    ovop = get_ovop_from_opcode(op);++    p = opset1->self_ops[ovop];+    if (!p) {+        JS_ThrowTypeError(ctx, "no overloaded operator %s",+                          js_overloadable_operator_names[ovop]);+        goto exception;+    }+    method = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p));+    ret = JS_CallFree(ctx, method, JS_UNDEFINED, 1, &op1);+    if (JS_IsException(ret))+        goto exception;+    JS_FreeValue(ctx, opset1_obj);+    *pret = ret;+    return 1;+ exception:+    JS_FreeValue(ctx, opset1_obj);+    *pret = JS_UNDEFINED;+    return -1;+}++static JSValue throw_bf_exception(JSContext *ctx, int status)+{+    const char *str;+    if (status & BF_ST_MEM_ERROR)+        return JS_ThrowOutOfMemory(ctx);+    if (status & BF_ST_DIVIDE_ZERO) {+        str = "division by zero";+    } else if (status & BF_ST_INVALID_OP) {+        str = "invalid operation";+    } else {+        str = "integer overflow";+    }+    return JS_ThrowRangeError(ctx, "%s", str);+}++static int js_unary_arith_bigint(JSContext *ctx,+                                 JSValue *pres, OPCodeEnum op, JSValue op1)+{+    bf_t a_s, *r, *a;+    int ret, v;+    JSValue res;+    +    if (op == OP_plus && !is_math_mode(ctx)) {+        JS_ThrowTypeError(ctx, "bigint argument with unary +");+        JS_FreeValue(ctx, op1);+        return -1;+    }+    res = JS_NewBigInt(ctx);+    if (JS_IsException(res)) {+        JS_FreeValue(ctx, op1);+        return -1;+    }+    r = JS_GetBigInt(res);+    a = JS_ToBigInt(ctx, &a_s, op1);+    ret = 0;+    switch(op) {+    case OP_inc:+    case OP_dec:+        v = 2 * (op - OP_dec) - 1;+        ret = bf_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_plus:+        ret = bf_set(r, a);+        break;+    case OP_neg:+        ret = bf_set(r, a);+        bf_neg(r);+        break;+    case OP_not:+        ret = bf_add_si(r, a, 1, BF_PREC_INF, BF_RNDZ);+        bf_neg(r);+        break;+    default:+        abort();+    }+    JS_FreeBigInt(ctx, a, &a_s);+    JS_FreeValue(ctx, op1);+    if (unlikely(ret)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    res = JS_CompactBigInt(ctx, res);+    *pres = res;+    return 0;+}++static int js_unary_arith_bigfloat(JSContext *ctx,+                                   JSValue *pres, OPCodeEnum op, JSValue op1)+{+    bf_t a_s, *r, *a;+    int ret, v;+    JSValue res;+    +    if (op == OP_plus && !is_math_mode(ctx)) {+        JS_ThrowTypeError(ctx, "bigfloat argument with unary +");+        JS_FreeValue(ctx, op1);+        return -1;+    }++    res = JS_NewBigFloat(ctx);+    if (JS_IsException(res)) {+        JS_FreeValue(ctx, op1);+        return -1;+    }+    r = JS_GetBigFloat(res);+    a = JS_ToBigFloat(ctx, &a_s, op1);+    ret = 0;+    switch(op) {+    case OP_inc:+    case OP_dec:+        v = 2 * (op - OP_dec) - 1;+        ret = bf_add_si(r, a, v, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case OP_plus:+        ret = bf_set(r, a);+        break;+    case OP_neg:+        ret = bf_set(r, a);+        bf_neg(r);+        break;+    default:+        abort();+    }+    if (a == &a_s)+        bf_delete(a);+    JS_FreeValue(ctx, op1);+    if (unlikely(ret & BF_ST_MEM_ERROR)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    *pres = res;+    return 0;+}++static int js_unary_arith_bigdecimal(JSContext *ctx,+                                     JSValue *pres, OPCodeEnum op, JSValue op1)+{+    bfdec_t *r, *a;+    int ret, v;+    JSValue res;+    +    if (op == OP_plus && !is_math_mode(ctx)) {+        JS_ThrowTypeError(ctx, "bigdecimal argument with unary +");+        JS_FreeValue(ctx, op1);+        return -1;+    }++    res = JS_NewBigDecimal(ctx);+    if (JS_IsException(res)) {+        JS_FreeValue(ctx, op1);+        return -1;+    }+    r = JS_GetBigDecimal(res);+    a = JS_ToBigDecimal(ctx, op1);+    ret = 0;+    switch(op) {+    case OP_inc:+    case OP_dec:+        v = 2 * (op - OP_dec) - 1;+        ret = bfdec_add_si(r, a, v, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_plus:+        ret = bfdec_set(r, a);+        break;+    case OP_neg:+        ret = bfdec_set(r, a);+        bfdec_neg(r);+        break;+    default:+        abort();+    }+    JS_FreeValue(ctx, op1);+    if (unlikely(ret)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    *pres = res;+    return 0;+}++static no_inline __exception int js_unary_arith_slow(JSContext *ctx,+                                                     JSValue *sp,+                                                     OPCodeEnum op)+{+    JSValue op1, val;+    int v, ret;+    uint32_t tag;++    op1 = sp[-1];+    /* fast path for float64 */+    if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)))+        goto handle_float64;+    if (JS_IsObject(op1)) {+        ret = js_call_unary_op_fallback(ctx, &val, op1, op);+        if (ret < 0)+            return -1;+        if (ret) {+            JS_FreeValue(ctx, op1);+            sp[-1] = val;+            return 0;+        }+    }++    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1))+        goto exception;+    tag = JS_VALUE_GET_TAG(op1);+    switch(tag) {+    case JS_TAG_INT:+        {+            int64_t v64;+            v64 = JS_VALUE_GET_INT(op1);+            switch(op) {+            case OP_inc:+            case OP_dec:+                v = 2 * (op - OP_dec) - 1;+                v64 += v;+                break;+            case OP_plus:+                break;+            case OP_neg:+                if (v64 == 0) {+                    sp[-1] = __JS_NewFloat64(ctx, -0.0);+                    return 0;+                } else {+                    v64 = -v64;+                }+                break;+            default:+                abort();+            }+            sp[-1] = JS_NewInt64(ctx, v64);+        }+        break;+    case JS_TAG_BIG_INT:+    handle_bigint:+        if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, op, op1))+            goto exception;+        break;+    case JS_TAG_BIG_FLOAT:+        if (ctx->rt->bigfloat_ops.unary_arith(ctx, sp - 1, op, op1))+            goto exception;+        break;+    case JS_TAG_BIG_DECIMAL:+        if (ctx->rt->bigdecimal_ops.unary_arith(ctx, sp - 1, op, op1))+            goto exception;+        break;+    default:+    handle_float64:+        {+            double d;+            if (is_math_mode(ctx))+                goto handle_bigint;+            d = JS_VALUE_GET_FLOAT64(op1);+            switch(op) {+            case OP_inc:+            case OP_dec:+                v = 2 * (op - OP_dec) - 1;+                d += v;+                break;+            case OP_plus:+                break;+            case OP_neg:+                d = -d;+                break;+            default:+                abort();+            }+            sp[-1] = __JS_NewFloat64(ctx, d);+        }+        break;+    }+    return 0;+ exception:+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static __exception int js_post_inc_slow(JSContext *ctx,+                                        JSValue *sp, OPCodeEnum op)+{+    JSValue op1;++    /* XXX: allow custom operators */+    op1 = sp[-1];+    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1)) {+        sp[-1] = JS_UNDEFINED;+        return -1;+    }+    sp[-1] = op1;+    sp[0] = JS_DupValue(ctx, op1);+    return js_unary_arith_slow(ctx, sp + 1, op - OP_post_dec + OP_dec);+}++static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)+{+    JSValue op1, val;+    int ret;+    +    op1 = sp[-1];+    if (JS_IsObject(op1)) {+        ret = js_call_unary_op_fallback(ctx, &val, op1, OP_not);+        if (ret < 0)+            return -1;+        if (ret) {+            JS_FreeValue(ctx, op1);+            sp[-1] = val;+            return 0;+        }+    }++    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1))+        goto exception;+    if (is_math_mode(ctx) || JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT) {+        if (ctx->rt->bigint_ops.unary_arith(ctx, sp - 1, OP_not, op1))+            goto exception;+    } else {+        int32_t v1;+        if (unlikely(JS_ToInt32Free(ctx, &v1, op1)))+            goto exception;+        sp[-1] = JS_NewInt32(ctx, ~v1);+    }+    return 0;+ exception:+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op,+                                    JSValue *pres, JSValue op1, JSValue op2)+{+    bf_t a_s, b_s, *r, *a, *b;+    int ret;+    JSValue res;+    +    res = JS_NewBigFloat(ctx);+    if (JS_IsException(res)) {+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+        return -1;+    }+    r = JS_GetBigFloat(res);+    a = JS_ToBigFloat(ctx, &a_s, op1);+    b = JS_ToBigFloat(ctx, &b_s, op2);+    bf_init(ctx->bf_ctx, r);+    switch(op) {+    case OP_add:+        ret = bf_add(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case OP_sub:+        ret = bf_sub(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case OP_mul:+        ret = bf_mul(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case OP_div:+        ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case OP_math_mod:+        /* Euclidian remainder */+        ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,+                     BF_DIVREM_EUCLIDIAN);+        break;+    case OP_mod:+        ret = bf_rem(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags,+                     BF_RNDZ);+        break;+    case OP_pow:+        ret = bf_pow(r, a, b, ctx->fp_env.prec,+                     ctx->fp_env.flags | BF_POW_JS_QUIRKS);+        break;+    default:+        abort();+    }+    if (a == &a_s)+        bf_delete(a);+    if (b == &b_s)+        bf_delete(b);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    if (unlikely(ret & BF_ST_MEM_ERROR)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    *pres = res;+    return 0;+}++static int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op,+                                  JSValue *pres, JSValue op1, JSValue op2)+{+    bf_t a_s, b_s, *r, *a, *b;+    int ret;+    JSValue res;+    +    res = JS_NewBigInt(ctx);+    if (JS_IsException(res))+        goto fail;+    a = JS_ToBigInt(ctx, &a_s, op1);+    if (!a)+        goto fail;+    b = JS_ToBigInt(ctx, &b_s, op2);+    if (!b) {+        JS_FreeBigInt(ctx, a, &a_s);+        goto fail;+    }+    r = JS_GetBigInt(res);+    ret = 0;+    switch(op) {+    case OP_add:+        ret = bf_add(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_sub:+        ret = bf_sub(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_mul:+        ret = bf_mul(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_div:+        if (!is_math_mode(ctx)) {+            bf_t rem_s, *rem = &rem_s;+            bf_init(ctx->bf_ctx, rem);+            ret = bf_divrem(r, rem, a, b, BF_PREC_INF, BF_RNDZ,+                            BF_RNDZ);+            bf_delete(rem);+        } else {+            goto math_mode_div_pow;+        }+        break;+    case OP_math_mod:+        /* Euclidian remainder */+        ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,+                     BF_DIVREM_EUCLIDIAN) & BF_ST_INVALID_OP;+        break;+    case OP_mod:+        ret = bf_rem(r, a, b, BF_PREC_INF, BF_RNDZ,+                     BF_RNDZ) & BF_ST_INVALID_OP;+        break;+    case OP_pow:+        if (b->sign) {+            if (!is_math_mode(ctx)) {+                ret = BF_ST_INVALID_OP;+            } else {+            math_mode_div_pow:+                JS_FreeValue(ctx, res);+                ret = js_call_binary_op_simple(ctx, &res, ctx->class_proto[JS_CLASS_BIG_INT], op1, op2, op);+                if (ret != 0) {+                    JS_FreeBigInt(ctx, a, &a_s);+                    JS_FreeBigInt(ctx, b, &b_s);+                    JS_FreeValue(ctx, op1);+                    JS_FreeValue(ctx, op2);+                    if (ret < 0) {+                        return -1;+                    } else {+                        *pres = res;+                        return 0;+                    }+                }+                /* if no BigInt power operator defined, return a+                   bigfloat */+                res = JS_NewBigFloat(ctx);+                if (JS_IsException(res)) {+                    JS_FreeBigInt(ctx, a, &a_s);+                    JS_FreeBigInt(ctx, b, &b_s);+                    goto fail;+                }+                r = JS_GetBigFloat(res);+                if (op == OP_div) {+                    ret = bf_div(r, a, b, ctx->fp_env.prec, ctx->fp_env.flags) & BF_ST_MEM_ERROR;+                } else {+                    ret = bf_pow(r, a, b, ctx->fp_env.prec,+                                 ctx->fp_env.flags | BF_POW_JS_QUIRKS) & BF_ST_MEM_ERROR;+                }+                JS_FreeBigInt(ctx, a, &a_s);+                JS_FreeBigInt(ctx, b, &b_s);+                JS_FreeValue(ctx, op1);+                JS_FreeValue(ctx, op2);+                if (unlikely(ret)) {+                    JS_FreeValue(ctx, res);+                    throw_bf_exception(ctx, ret);+                    return -1;+                }+                *pres = res;+                return 0;+            }+        } else {+            ret = bf_pow(r, a, b, BF_PREC_INF, BF_RNDZ | BF_POW_JS_QUIRKS);+        }+        break;++        /* logical operations */+    case OP_shl:+    case OP_sar:+        {+            slimb_t v2;+#if LIMB_BITS == 32+            bf_get_int32(&v2, b, 0);+            if (v2 == INT32_MIN)+                v2 = INT32_MIN + 1;+#else+            bf_get_int64(&v2, b, 0);+            if (v2 == INT64_MIN)+                v2 = INT64_MIN + 1;+#endif+            if (op == OP_sar)+                v2 = -v2;+            ret = bf_set(r, a);+            ret |= bf_mul_2exp(r, v2, BF_PREC_INF, BF_RNDZ);+            if (v2 < 0) {+                ret |= bf_rint(r, BF_RNDD) & (BF_ST_OVERFLOW | BF_ST_MEM_ERROR);+            }+        }+        break;+    case OP_and:+        ret = bf_logic_and(r, a, b);+        break;+    case OP_or:+        ret = bf_logic_or(r, a, b);+        break;+    case OP_xor:+        ret = bf_logic_xor(r, a, b);+        break;+    default:+        abort();+    }+    JS_FreeBigInt(ctx, a, &a_s);+    JS_FreeBigInt(ctx, b, &b_s);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    if (unlikely(ret)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    *pres = JS_CompactBigInt(ctx, res);+    return 0;+ fail:+    JS_FreeValue(ctx, res);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return -1;+}++/* b must be a positive integer */+static int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b)+{+    bfdec_t b1;+    int32_t b2;+    int ret;++    bfdec_init(b->ctx, &b1);+    ret = bfdec_set(&b1, b);+    if (ret) {+        bfdec_delete(&b1);+        return ret;+    }+    ret = bfdec_rint(&b1, BF_RNDZ);+    if (ret) {+        bfdec_delete(&b1);+        return BF_ST_INVALID_OP; /* must be an integer */+    }+    ret = bfdec_get_int32(&b2, &b1);+    bfdec_delete(&b1);+    if (ret)+        return ret; /* overflow */+    if (b2 < 0)+        return BF_ST_INVALID_OP; /* must be positive */+    return bfdec_pow_ui(r, a, b2);+}++static int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op,+                                      JSValue *pres, JSValue op1, JSValue op2)+{+    bfdec_t *r, *a, *b;+    int ret;+    JSValue res;++    res = JS_NewBigDecimal(ctx);+    if (JS_IsException(res))+        goto fail;+    r = JS_GetBigDecimal(res);+    +    a = JS_ToBigDecimal(ctx, op1);+    if (!a)+        goto fail;+    b = JS_ToBigDecimal(ctx, op2);+    if (!b)+        goto fail;+    switch(op) {+    case OP_add:+        ret = bfdec_add(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_sub:+        ret = bfdec_sub(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_mul:+        ret = bfdec_mul(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_div:+        ret = bfdec_div(r, a, b, BF_PREC_INF, BF_RNDZ);+        break;+    case OP_math_mod:+        /* Euclidian remainder */+        ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_DIVREM_EUCLIDIAN);+        break;+    case OP_mod:+        ret = bfdec_rem(r, a, b, BF_PREC_INF, BF_RNDZ, BF_RNDZ);+        break;+    case OP_pow:+        ret = js_bfdec_pow(r, a, b);+        break;+    default:+        abort();+    }+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    if (unlikely(ret)) {+        JS_FreeValue(ctx, res);+        throw_bf_exception(ctx, ret);+        return -1;+    }+    *pres = res;+    return 0;+ fail:+    JS_FreeValue(ctx, res);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return -1;+}++static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,+                                                      OPCodeEnum op)+{+    JSValue op1, op2, res;+    uint32_t tag1, tag2;+    int ret;+    double d1, d2;++    op1 = sp[-2];+    op2 = sp[-1];+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    /* fast path for float operations */+    if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) {+        d1 = JS_VALUE_GET_FLOAT64(op1);+        d2 = JS_VALUE_GET_FLOAT64(op2);+        goto handle_float64;+    }++    /* try to call an overloaded operator */+    if ((tag1 == JS_TAG_OBJECT &&+         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||+        (tag2 == JS_TAG_OBJECT &&+         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {+        ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);+        if (ret != 0) {+            JS_FreeValue(ctx, op1);+            JS_FreeValue(ctx, op2);+            if (ret < 0) {+                goto exception;+            } else {+                sp[-2] = res;+                return 0;+            }+        }+    }++    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToNumericFree(ctx, op2);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);++    if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {+        int32_t v1, v2;+        int64_t v;+        v1 = JS_VALUE_GET_INT(op1);+        v2 = JS_VALUE_GET_INT(op2);+        switch(op) {+        case OP_sub:+            v = (int64_t)v1 - (int64_t)v2;+            break;+        case OP_mul:+            v = (int64_t)v1 * (int64_t)v2;+            if (is_math_mode(ctx) &&+                (v < -MAX_SAFE_INTEGER || v > MAX_SAFE_INTEGER))+                goto handle_bigint;+            if (v == 0 && (v1 | v2) < 0) {+                sp[-2] = __JS_NewFloat64(ctx, -0.0);+                return 0;+            }+            break;+        case OP_div:+            if (is_math_mode(ctx))+                goto handle_bigint;+            sp[-2] = __JS_NewFloat64(ctx, (double)v1 / (double)v2);+            return 0;+        case OP_math_mod:+            if (unlikely(v2 == 0)) {+                throw_bf_exception(ctx, BF_ST_DIVIDE_ZERO);+                goto exception;+            }+            v = (int64_t)v1 % (int64_t)v2;+            if (v < 0) {+                if (v2 < 0)+                    v -= v2;+                else+                    v += v2;+            }+            break;+        case OP_mod:+            if (v1 < 0 || v2 <= 0) {+                sp[-2] = JS_NewFloat64(ctx, fmod(v1, v2));+                return 0;+            } else {+                v = (int64_t)v1 % (int64_t)v2;+            }+            break;+        case OP_pow:+            if (!is_math_mode(ctx)) {+                sp[-2] = JS_NewFloat64(ctx, js_pow(v1, v2));+                return 0;+            } else {+                goto handle_bigint;+            }+            break;+        default:+            abort();+        }+        sp[-2] = JS_NewInt64(ctx, v);+    } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {+        if (ctx->rt->bigdecimal_ops.binary_arith(ctx, op, sp - 2, op1, op2))+            goto exception;+    } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {+        if (ctx->rt->bigfloat_ops.binary_arith(ctx, op, sp - 2, op1, op2))+            goto exception;+    } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {+    handle_bigint:+        if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))+            goto exception;+    } else {+        double dr;+        /* float64 result */+        if (JS_ToFloat64Free(ctx, &d1, op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        if (JS_ToFloat64Free(ctx, &d2, op2))+            goto exception;+    handle_float64:+        if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))+            goto handle_bigint;+        switch(op) {+        case OP_sub:+            dr = d1 - d2;+            break;+        case OP_mul:+            dr = d1 * d2;+            break;+        case OP_div:+            dr = d1 / d2;+            break;+        case OP_mod:+            dr = fmod(d1, d2);+            break;+        case OP_math_mod:+            d2 = fabs(d2);+            dr = fmod(d1, d2);+            /* XXX: loss of accuracy if dr < 0 */+            if (dr < 0)+                dr += d2;+            break;+        case OP_pow:+            dr = js_pow(d1, d2);+            break;+        default:+            abort();+        }+        sp[-2] = __JS_NewFloat64(ctx, dr);+    }+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2, res;+    uint32_t tag1, tag2;+    int ret;++    op1 = sp[-2];+    op2 = sp[-1];++    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    /* fast path for float64 */+    if (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_FLOAT64) {+        double d1, d2;+        d1 = JS_VALUE_GET_FLOAT64(op1);+        d2 = JS_VALUE_GET_FLOAT64(op2);+        sp[-2] = __JS_NewFloat64(ctx, d1 + d2);+        return 0;+    }++    if (tag1 == JS_TAG_OBJECT || tag2 == JS_TAG_OBJECT) {+        /* try to call an overloaded operator */+        if ((tag1 == JS_TAG_OBJECT &&+             (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED &&+              tag2 != JS_TAG_STRING)) ||+            (tag2 == JS_TAG_OBJECT &&+             (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED &&+              tag1 != JS_TAG_STRING))) {+            ret = js_call_binary_op_fallback(ctx, &res, op1, op2, OP_add,+                                             FALSE, HINT_NONE);+            if (ret != 0) {+                JS_FreeValue(ctx, op1);+                JS_FreeValue(ctx, op2);+                if (ret < 0) {+                    goto exception;+                } else {+                    sp[-2] = res;+                    return 0;+                }+            }+        }++        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);+        if (JS_IsException(op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }++        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            goto exception;+        }+        tag1 = JS_VALUE_GET_NORM_TAG(op1);+        tag2 = JS_VALUE_GET_NORM_TAG(op2);+    }++    if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {+        sp[-2] = JS_ConcatString(ctx, op1, op2);+        if (JS_IsException(sp[-2]))+            goto exception;+        return 0;+    }++    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToNumericFree(ctx, op2);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);++    if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {+        int32_t v1, v2;+        int64_t v;+        v1 = JS_VALUE_GET_INT(op1);+        v2 = JS_VALUE_GET_INT(op2);+        v = (int64_t)v1 + (int64_t)v2;+        sp[-2] = JS_NewInt64(ctx, v);+    } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {+        if (ctx->rt->bigdecimal_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))+            goto exception;+    } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {+        if (ctx->rt->bigfloat_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))+            goto exception;+    } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {+    handle_bigint:+        if (ctx->rt->bigint_ops.binary_arith(ctx, OP_add, sp - 2, op1, op2))+            goto exception;+    } else {+        double d1, d2;+        /* float64 result */+        if (JS_ToFloat64Free(ctx, &d1, op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        if (JS_ToFloat64Free(ctx, &d2, op2))+            goto exception;+        if (is_math_mode(ctx) && is_safe_integer(d1) && is_safe_integer(d2))+            goto handle_bigint;+        sp[-2] = __JS_NewFloat64(ctx, d1 + d2);+    }+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline __exception int js_binary_logic_slow(JSContext *ctx,+                                                      JSValue *sp,+                                                      OPCodeEnum op)+{+    JSValue op1, op2, res;+    int ret;+    uint32_t tag1, tag2;+    uint32_t v1, v2, r;++    op1 = sp[-2];+    op2 = sp[-1];+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);++    /* try to call an overloaded operator */+    if ((tag1 == JS_TAG_OBJECT &&+         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||+        (tag2 == JS_TAG_OBJECT &&+         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {+        ret = js_call_binary_op_fallback(ctx, &res, op1, op2, op, TRUE, 0);+        if (ret != 0) {+            JS_FreeValue(ctx, op1);+            JS_FreeValue(ctx, op2);+            if (ret < 0) {+                goto exception;+            } else {+                sp[-2] = res;+                return 0;+            }+        }+    }++    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToNumericFree(ctx, op2);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }++    if (is_math_mode(ctx))+        goto bigint_op;++    tag1 = JS_VALUE_GET_TAG(op1);+    tag2 = JS_VALUE_GET_TAG(op2);+    if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {+        if (tag1 != tag2) {+            JS_FreeValue(ctx, op1);+            JS_FreeValue(ctx, op2);+            JS_ThrowTypeError(ctx, "both operands must be bigint");+            goto exception;+        } else {+        bigint_op:+            if (ctx->rt->bigint_ops.binary_arith(ctx, op, sp - 2, op1, op2))+                goto exception;+        }+    } else {+        if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))+            goto exception;+        switch(op) {+        case OP_shl:+            r = v1 << (v2 & 0x1f);+            break;+        case OP_sar:+            r = (int)v1 >> (v2 & 0x1f);+            break;+        case OP_and:+            r = v1 & v2;+            break;+        case OP_or:+            r = v1 | v2;+            break;+        case OP_xor:+            r = v1 ^ v2;+            break;+        default:+            abort();+        }+        sp[-2] = JS_NewInt32(ctx, r);+    }+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++/* Note: also used for bigint */+static int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op,+                               JSValue op1, JSValue op2)+{+    bf_t a_s, b_s, *a, *b;+    int res;+    +    a = JS_ToBigFloat(ctx, &a_s, op1);+    if (!a) {+        JS_FreeValue(ctx, op2);+        return -1;+    }+    b = JS_ToBigFloat(ctx, &b_s, op2);+    if (!b) {+        if (a == &a_s)+            bf_delete(a);+        JS_FreeValue(ctx, op1);+        return -1;+    }+    switch(op) {+    case OP_lt:+        res = bf_cmp_lt(a, b); /* if NaN return false */+        break;+    case OP_lte:+        res = bf_cmp_le(a, b); /* if NaN return false */+        break;+    case OP_gt:+        res = bf_cmp_lt(b, a); /* if NaN return false */+        break;+    case OP_gte:+        res = bf_cmp_le(b, a); /* if NaN return false */+        break;+    case OP_eq:+        res = bf_cmp_eq(a, b); /* if NaN return false */+        break;+    default:+        abort();+    }+    if (a == &a_s)+        bf_delete(a);+    if (b == &b_s)+        bf_delete(b);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return res;+}++static int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op,+                                 JSValue op1, JSValue op2)+{+    bfdec_t *a, *b;+    int res;++    /* Note: binary floats are converted to bigdecimal with+       toString(). It is not mathematically correct but is consistent+       with the BigDecimal() constructor behavior */+    op1 = JS_ToBigDecimalFree(ctx, op1, TRUE);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        return -1;+    }+    op2 = JS_ToBigDecimalFree(ctx, op2, TRUE);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        return -1;+    }+    a = JS_ToBigDecimal(ctx, op1);+    b = JS_ToBigDecimal(ctx, op2);+    +    switch(op) {+    case OP_lt:+        res = bfdec_cmp_lt(a, b); /* if NaN return false */+        break;+    case OP_lte:+        res = bfdec_cmp_le(a, b); /* if NaN return false */+        break;+    case OP_gt:+        res = bfdec_cmp_lt(b, a); /* if NaN return false */+        break;+    case OP_gte:+        res = bfdec_cmp_le(b, a); /* if NaN return false */+        break;+    case OP_eq:+        res = bfdec_cmp_eq(a, b); /* if NaN return false */+        break;+    default:+        abort();+    }+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return res;+}++static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,+                                        OPCodeEnum op)+{+    JSValue op1, op2, ret;+    int res;+    uint32_t tag1, tag2;++    op1 = sp[-2];+    op2 = sp[-1];+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    /* try to call an overloaded operator */+    if ((tag1 == JS_TAG_OBJECT &&+         (tag2 != JS_TAG_NULL && tag2 != JS_TAG_UNDEFINED)) ||+        (tag2 == JS_TAG_OBJECT &&+         (tag1 != JS_TAG_NULL && tag1 != JS_TAG_UNDEFINED))) {+        res = js_call_binary_op_fallback(ctx, &ret, op1, op2, op,+                                         FALSE, HINT_NUMBER);+        if (res != 0) {+            JS_FreeValue(ctx, op1);+            JS_FreeValue(ctx, op2);+            if (res < 0) {+                goto exception;+            } else {+                sp[-2] = ret;+                return 0;+            }+        }+    }+    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);++    if (tag1 == JS_TAG_STRING && tag2 == JS_TAG_STRING) {+        JSString *p1, *p2;+        p1 = JS_VALUE_GET_STRING(op1);+        p2 = JS_VALUE_GET_STRING(op2);+        res = js_string_compare(ctx, p1, p2);+        switch(op) {+        case OP_lt:+            res = (res < 0);+            break;+        case OP_lte:+            res = (res <= 0);+            break;+        case OP_gt:+            res = (res > 0);+            break;+        default:+        case OP_gte:+            res = (res >= 0);+            break;+        }+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+    } else if ((tag1 <= JS_TAG_NULL || tag1 == JS_TAG_FLOAT64) &&+               (tag2 <= JS_TAG_NULL || tag2 == JS_TAG_FLOAT64)) {+        /* fast path for float64/int */+        goto float64_compare;+    } else {+        if (((tag1 == JS_TAG_BIG_INT && tag2 == JS_TAG_STRING) ||+             (tag2 == JS_TAG_BIG_INT && tag1 == JS_TAG_STRING)) &&+            !is_math_mode(ctx)) {+            if (tag1 == JS_TAG_STRING) {+                op1 = JS_StringToBigInt(ctx, op1);+                if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)+                    goto invalid_bigint_string;+            }+            if (tag2 == JS_TAG_STRING) {+                op2 = JS_StringToBigInt(ctx, op2);+                if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT) {+                invalid_bigint_string:+                    JS_FreeValue(ctx, op1);+                    JS_FreeValue(ctx, op2);+                    res = FALSE;+                    goto done;+                }+            }+        } else {+            op1 = JS_ToNumericFree(ctx, op1);+            if (JS_IsException(op1)) {+                JS_FreeValue(ctx, op2);+                goto exception;+            }+            op2 = JS_ToNumericFree(ctx, op2);+            if (JS_IsException(op2)) {+                JS_FreeValue(ctx, op1);+                goto exception;+            }+        }++        tag1 = JS_VALUE_GET_NORM_TAG(op1);+        tag2 = JS_VALUE_GET_NORM_TAG(op2);++        if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {+            res = ctx->rt->bigdecimal_ops.compare(ctx, op, op1, op2);+            if (res < 0)+                goto exception;+        } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {+            res = ctx->rt->bigfloat_ops.compare(ctx, op, op1, op2);+            if (res < 0)+                goto exception;+        } else if (tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) {+            res = ctx->rt->bigint_ops.compare(ctx, op, op1, op2);+            if (res < 0)+                goto exception;+        } else {+            double d1, d2;++        float64_compare:+            /* can use floating point comparison */+            if (tag1 == JS_TAG_FLOAT64) {+                d1 = JS_VALUE_GET_FLOAT64(op1);+            } else {+                d1 = JS_VALUE_GET_INT(op1);+            }+            if (tag2 == JS_TAG_FLOAT64) {+                d2 = JS_VALUE_GET_FLOAT64(op2);+            } else {+                d2 = JS_VALUE_GET_INT(op2);+            }+            switch(op) {+            case OP_lt:+                res = (d1 < d2); /* if NaN return false */+                break;+            case OP_lte:+                res = (d1 <= d2); /* if NaN return false */+                break;+            case OP_gt:+                res = (d1 > d2); /* if NaN return false */+                break;+            default:+            case OP_gte:+                res = (d1 >= d2); /* if NaN return false */+                break;+            }+        }+    }+ done:+    sp[-2] = JS_NewBool(ctx, res);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static BOOL tag_is_number(uint32_t tag)+{+    return (tag == JS_TAG_INT || tag == JS_TAG_BIG_INT ||+            tag == JS_TAG_FLOAT64 || tag == JS_TAG_BIG_FLOAT ||+            tag == JS_TAG_BIG_DECIMAL);+}++static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,+                                            BOOL is_neq)+{+    JSValue op1, op2, ret;+    int res;+    uint32_t tag1, tag2;++    op1 = sp[-2];+    op2 = sp[-1];+ redo:+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    if (tag_is_number(tag1) && tag_is_number(tag2)) {+        if (tag1 == JS_TAG_INT && tag2 == JS_TAG_INT) {+            res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);+        } else if ((tag1 == JS_TAG_FLOAT64 &&+                    (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64)) ||+                   (tag2 == JS_TAG_FLOAT64 &&+                    (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64))) {+            double d1, d2;+            if (tag1 == JS_TAG_FLOAT64) {+                d1 = JS_VALUE_GET_FLOAT64(op1);+            } else {+                d1 = JS_VALUE_GET_INT(op1);+            }+            if (tag2 == JS_TAG_FLOAT64) {+                d2 = JS_VALUE_GET_FLOAT64(op2);+            } else {+                d2 = JS_VALUE_GET_INT(op2);+            }+            res = (d1 == d2);+        } else if (tag1 == JS_TAG_BIG_DECIMAL || tag2 == JS_TAG_BIG_DECIMAL) {+            res = ctx->rt->bigdecimal_ops.compare(ctx, OP_eq, op1, op2);+            if (res < 0)+                goto exception;+        } else if (tag1 == JS_TAG_BIG_FLOAT || tag2 == JS_TAG_BIG_FLOAT) {+            res = ctx->rt->bigfloat_ops.compare(ctx, OP_eq, op1, op2);+            if (res < 0)+                goto exception;+        } else {+            res = ctx->rt->bigint_ops.compare(ctx, OP_eq, op1, op2);+            if (res < 0)+                goto exception;+        }+    } else if (tag1 == tag2) {+        if (tag1 == JS_TAG_OBJECT) {+            /* try the fallback operator */+            res = js_call_binary_op_fallback(ctx, &ret, op1, op2,+                                             is_neq ? OP_neq : OP_eq,+                                             FALSE, HINT_NONE);+            if (res != 0) {+                JS_FreeValue(ctx, op1);+                JS_FreeValue(ctx, op2);+                if (res < 0) {+                    goto exception;+                } else {+                    sp[-2] = ret;+                    return 0;+                }+            }+        }+        res = js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);+    } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||+               (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {+        res = TRUE;+    } else if ((tag1 == JS_TAG_STRING && tag_is_number(tag2)) ||+               (tag2 == JS_TAG_STRING && tag_is_number(tag1))) {++        if ((tag1 == JS_TAG_BIG_INT || tag2 == JS_TAG_BIG_INT) &&+            !is_math_mode(ctx)) {+            if (tag1 == JS_TAG_STRING) {+                op1 = JS_StringToBigInt(ctx, op1);+                if (JS_VALUE_GET_TAG(op1) != JS_TAG_BIG_INT)+                    goto invalid_bigint_string;+            }+            if (tag2 == JS_TAG_STRING) {+                op2 = JS_StringToBigInt(ctx, op2);+                if (JS_VALUE_GET_TAG(op2) != JS_TAG_BIG_INT) {+                invalid_bigint_string:+                    JS_FreeValue(ctx, op1);+                    JS_FreeValue(ctx, op2);+                    res = FALSE;+                    goto done;+                }+            }+        } else {+            op1 = JS_ToNumericFree(ctx, op1);+            if (JS_IsException(op1)) {+                JS_FreeValue(ctx, op2);+                goto exception;+            }+            op2 = JS_ToNumericFree(ctx, op2);+            if (JS_IsException(op2)) {+                JS_FreeValue(ctx, op1);+                goto exception;+            }+        }+        res = js_strict_eq(ctx, op1, op2);+    } else if (tag1 == JS_TAG_BOOL) {+        op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));+        goto redo;+    } else if (tag2 == JS_TAG_BOOL) {+        op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));+        goto redo;+    } else if ((tag1 == JS_TAG_OBJECT &&+                (tag_is_number(tag2) || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) ||+               (tag2 == JS_TAG_OBJECT &&+                (tag_is_number(tag1) || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL))) {++        /* try the fallback operator */+        res = js_call_binary_op_fallback(ctx, &ret, op1, op2,+                                         is_neq ? OP_neq : OP_eq,+                                         FALSE, HINT_NONE);+        if (res != 0) {+            JS_FreeValue(ctx, op1);+            JS_FreeValue(ctx, op2);+            if (res < 0) {+                goto exception;+            } else {+                sp[-2] = ret;+                return 0;+            }+        }++        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);+        if (JS_IsException(op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            goto exception;+        }+        goto redo;+    } else {+        /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */+        if ((JS_IsHTMLDDA(ctx, op1) &&+             (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||+            (JS_IsHTMLDDA(ctx, op2) &&+             (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {+            res = TRUE;+        } else {+            res = FALSE;+        }+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+    }+ done:+    sp[-2] = JS_NewBool(ctx, res ^ is_neq);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    uint32_t v1, v2, r;++    op1 = sp[-2];+    op2 = sp[-1];+    op1 = JS_ToNumericFree(ctx, op1);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToNumericFree(ctx, op2);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }+    /* XXX: could forbid >>> in bignum mode */+    if (!is_math_mode(ctx) &&+        (JS_VALUE_GET_TAG(op1) == JS_TAG_BIG_INT ||+         JS_VALUE_GET_TAG(op2) == JS_TAG_BIG_INT)) {+        JS_ThrowTypeError(ctx, "bigint operands are forbidden for >>>");+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    /* cannot give an exception */+    JS_ToUint32Free(ctx, &v1, op1);+    JS_ToUint32Free(ctx, &v2, op2);+    r = v1 >> (v2 & 0x1f);+    sp[-2] = JS_NewUint32(ctx, r);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a,+                                       int64_t exponent)+{+    bf_t r_s, *r = &r_s;+    double d;+    int ret;+    +    /* always convert to Float64 */+    bf_init(ctx->bf_ctx, r);+    ret = bf_mul_pow_radix(r, a, 10, exponent,+                           53, bf_set_exp_bits(11) | BF_RNDN |+                           BF_FLAG_SUBNORMAL);+    bf_get_float64(r, &d, BF_RNDN);+    bf_delete(r);+    if (ret & BF_ST_MEM_ERROR)+        return JS_ThrowOutOfMemory(ctx);+    else+        return __JS_NewFloat64(ctx, d);+}++static no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp)+{+    bf_t a_s, *a, *r;+    JSValue op1, op2, res;+    int64_t e;+    int ret;++    res = JS_NewBigFloat(ctx);+    if (JS_IsException(res))+        return -1;+    r = JS_GetBigFloat(res);+    op1 = sp[-2];+    op2 = sp[-1];+    a = JS_ToBigFloat(ctx, &a_s, op1);+    if (!a)+        return -1;+    if (JS_IsBigInt(ctx, op2)) {+        ret = JS_ToBigInt64(ctx, &e, op2);+    } else {+        ret = JS_ToInt64(ctx, &e, op2);+    }+    if (ret) {+        if (a == &a_s)+            bf_delete(a);+        JS_FreeValue(ctx, res);+        return -1;+    }++    bf_mul_pow_radix(r, a, 10, e, ctx->fp_env.prec, ctx->fp_env.flags);+    if (a == &a_s)+        bf_delete(a);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    sp[-2] = res;+    return 0;+}++#else /* !CONFIG_BIGNUM */++static JSValue JS_ThrowUnsupportedBigint(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "bigint is not supported");+}++JSValue JS_NewBigInt64(JSContext *ctx, int64_t v)+{+    return JS_ThrowUnsupportedBigint(ctx);+}++JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v)+{+    return JS_ThrowUnsupportedBigint(ctx);+}++int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val)+{+    JS_ThrowUnsupportedBigint(ctx);+    *pres = 0;+    return -1;+}++static no_inline __exception int js_unary_arith_slow(JSContext *ctx,+                                                     JSValue *sp,+                                                     OPCodeEnum op)+{+    JSValue op1;+    double d;++    op1 = sp[-1];+    if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {+        sp[-1] = JS_UNDEFINED;+        return -1;+    }+    switch(op) {+    case OP_inc:+        d++;+        break;+    case OP_dec:+        d--;+        break;+    case OP_plus:+        break;+    case OP_neg:+        d = -d;+        break;+    default:+        abort();+    }+    sp[-1] = JS_NewFloat64(ctx, d);+    return 0;+}++/* specific case necessary for correct return value semantics */+static __exception int js_post_inc_slow(JSContext *ctx,+                                        JSValue *sp, OPCodeEnum op)+{+    JSValue op1;+    double d, r;++    op1 = sp[-1];+    if (unlikely(JS_ToFloat64Free(ctx, &d, op1))) {+        sp[-1] = JS_UNDEFINED;+        return -1;+    }+    r = d + 2 * (op - OP_post_dec) - 1;+    sp[0] = JS_NewFloat64(ctx, r);+    sp[-1] = JS_NewFloat64(ctx, d);+    return 0;+}++static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp,+                                                      OPCodeEnum op)+{+    JSValue op1, op2;+    double d1, d2, r;++    op1 = sp[-2];+    op2 = sp[-1];+    if (unlikely(JS_ToFloat64Free(ctx, &d1, op1))) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    if (unlikely(JS_ToFloat64Free(ctx, &d2, op2))) {+        goto exception;+    }+    switch(op) {+    case OP_sub:+        r = d1 - d2;+        break;+    case OP_mul:+        r = d1 * d2;+        break;+    case OP_div:+        r = d1 / d2;+        break;+    case OP_mod:+        r = fmod(d1, d2);+        break;+    case OP_pow:+        r = js_pow(d1, d2);+        break;+    default:+        abort();+    }+    sp[-2] = JS_NewFloat64(ctx, r);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    uint32_t tag1, tag2;++    op1 = sp[-2];+    op2 = sp[-1];+    tag1 = JS_VALUE_GET_TAG(op1);+    tag2 = JS_VALUE_GET_TAG(op2);+    if ((tag1 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag1)) &&+        (tag2 == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag2))) {+        goto add_numbers;+    } else {+        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);+        if (JS_IsException(op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            goto exception;+        }+        tag1 = JS_VALUE_GET_TAG(op1);+        tag2 = JS_VALUE_GET_TAG(op2);+        if (tag1 == JS_TAG_STRING || tag2 == JS_TAG_STRING) {+            sp[-2] = JS_ConcatString(ctx, op1, op2);+            if (JS_IsException(sp[-2]))+                goto exception;+        } else {+            double d1, d2;+        add_numbers:+            if (JS_ToFloat64Free(ctx, &d1, op1)) {+                JS_FreeValue(ctx, op2);+                goto exception;+            }+            if (JS_ToFloat64Free(ctx, &d2, op2))+                goto exception;+            sp[-2] = JS_NewFloat64(ctx, d1 + d2);+        }+    }+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline __exception int js_binary_logic_slow(JSContext *ctx,+                                                      JSValue *sp,+                                                      OPCodeEnum op)+{+    JSValue op1, op2;+    uint32_t v1, v2, r;++    op1 = sp[-2];+    op2 = sp[-1];+    if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))+        goto exception;+    switch(op) {+    case OP_shl:+        r = v1 << (v2 & 0x1f);+        break;+    case OP_sar:+        r = (int)v1 >> (v2 & 0x1f);+        break;+    case OP_and:+        r = v1 & v2;+        break;+    case OP_or:+        r = v1 | v2;+        break;+    case OP_xor:+        r = v1 ^ v2;+        break;+    default:+        abort();+    }+    sp[-2] = JS_NewInt32(ctx, r);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline int js_not_slow(JSContext *ctx, JSValue *sp)+{+    int32_t v1;++    if (unlikely(JS_ToInt32Free(ctx, &v1, sp[-1]))) {+        sp[-1] = JS_UNDEFINED;+        return -1;+    }+    sp[-1] = JS_NewInt32(ctx, ~v1);+    return 0;+}++static no_inline int js_relational_slow(JSContext *ctx, JSValue *sp,+                                        OPCodeEnum op)+{+    JSValue op1, op2;+    int res;++    op1 = sp[-2];+    op2 = sp[-1];+    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NUMBER);+    if (JS_IsException(op1)) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NUMBER);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        goto exception;+    }+    if (JS_VALUE_GET_TAG(op1) == JS_TAG_STRING &&+        JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {+        JSString *p1, *p2;+        p1 = JS_VALUE_GET_STRING(op1);+        p2 = JS_VALUE_GET_STRING(op2);+        res = js_string_compare(ctx, p1, p2);+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+        switch(op) {+        case OP_lt:+            res = (res < 0);+            break;+        case OP_lte:+            res = (res <= 0);+            break;+        case OP_gt:+            res = (res > 0);+            break;+        default:+        case OP_gte:+            res = (res >= 0);+            break;+        }+    } else {+        double d1, d2;+        if (JS_ToFloat64Free(ctx, &d1, op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        if (JS_ToFloat64Free(ctx, &d2, op2))+            goto exception;+        switch(op) {+        case OP_lt:+            res = (d1 < d2); /* if NaN return false */+            break;+        case OP_lte:+            res = (d1 <= d2); /* if NaN return false */+            break;+        case OP_gt:+            res = (d1 > d2); /* if NaN return false */+            break;+        default:+        case OP_gte:+            res = (d1 >= d2); /* if NaN return false */+            break;+        }+    }+    sp[-2] = JS_NewBool(ctx, res);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp,+                                            BOOL is_neq)+{+    JSValue op1, op2;+    int tag1, tag2;+    BOOL res;++    op1 = sp[-2];+    op2 = sp[-1];+ redo:+    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    if (tag1 == tag2 ||+        (tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) ||+        (tag2 == JS_TAG_INT && tag1 == JS_TAG_FLOAT64)) {+        res = js_strict_eq(ctx, op1, op2);+    } else if ((tag1 == JS_TAG_NULL && tag2 == JS_TAG_UNDEFINED) ||+               (tag2 == JS_TAG_NULL && tag1 == JS_TAG_UNDEFINED)) {+        res = TRUE;+    } else if ((tag1 == JS_TAG_STRING && (tag2 == JS_TAG_INT ||+                                   tag2 == JS_TAG_FLOAT64)) ||+        (tag2 == JS_TAG_STRING && (tag1 == JS_TAG_INT ||+                                   tag1 == JS_TAG_FLOAT64))) {+        double d1;+        double d2;+        if (JS_ToFloat64Free(ctx, &d1, op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        if (JS_ToFloat64Free(ctx, &d2, op2))+            goto exception;+        res = (d1 == d2);+    } else if (tag1 == JS_TAG_BOOL) {+        op1 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op1));+        goto redo;+    } else if (tag2 == JS_TAG_BOOL) {+        op2 = JS_NewInt32(ctx, JS_VALUE_GET_INT(op2));+        goto redo;+    } else if (tag1 == JS_TAG_OBJECT &&+               (tag2 == JS_TAG_INT || tag2 == JS_TAG_FLOAT64 || tag2 == JS_TAG_STRING || tag2 == JS_TAG_SYMBOL)) {+        op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);+        if (JS_IsException(op1)) {+            JS_FreeValue(ctx, op2);+            goto exception;+        }+        goto redo;+    } else if (tag2 == JS_TAG_OBJECT &&+               (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64 || tag1 == JS_TAG_STRING || tag1 == JS_TAG_SYMBOL)) {+        op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            goto exception;+        }+        goto redo;+    } else {+        /* IsHTMLDDA object is equivalent to undefined for '==' and '!=' */+        if ((JS_IsHTMLDDA(ctx, op1) &&+             (tag2 == JS_TAG_NULL || tag2 == JS_TAG_UNDEFINED)) ||+            (JS_IsHTMLDDA(ctx, op2) &&+             (tag1 == JS_TAG_NULL || tag1 == JS_TAG_UNDEFINED))) {+            res = TRUE;+        } else {+            res = FALSE;+        }+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+    }+    sp[-2] = JS_NewBool(ctx, res ^ is_neq);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static no_inline int js_shr_slow(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    uint32_t v1, v2, r;++    op1 = sp[-2];+    op2 = sp[-1];+    if (unlikely(JS_ToUint32Free(ctx, &v1, op1))) {+        JS_FreeValue(ctx, op2);+        goto exception;+    }+    if (unlikely(JS_ToUint32Free(ctx, &v2, op2)))+        goto exception;+    r = v1 >> (v2 & 0x1f);+    sp[-2] = JS_NewUint32(ctx, r);+    return 0;+ exception:+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++#endif /* !CONFIG_BIGNUM */++/* XXX: Should take JSValueConst arguments */+static BOOL js_strict_eq2(JSContext *ctx, JSValue op1, JSValue op2,+                          JSStrictEqModeEnum eq_mode)+{+    BOOL res;+    int tag1, tag2;+    double d1, d2;++    tag1 = JS_VALUE_GET_NORM_TAG(op1);+    tag2 = JS_VALUE_GET_NORM_TAG(op2);+    switch(tag1) {+    case JS_TAG_BOOL:+        if (tag1 != tag2) {+            res = FALSE;+        } else {+            res = JS_VALUE_GET_INT(op1) == JS_VALUE_GET_INT(op2);+            goto done_no_free;+        }+        break;+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        res = (tag1 == tag2);+        break;+    case JS_TAG_STRING:+        {+            JSString *p1, *p2;+            if (tag1 != tag2) {+                res = FALSE;+            } else {+                p1 = JS_VALUE_GET_STRING(op1);+                p2 = JS_VALUE_GET_STRING(op2);+                res = (js_string_compare(ctx, p1, p2) == 0);+            }+        }+        break;+    case JS_TAG_SYMBOL:+        {+            JSAtomStruct *p1, *p2;+            if (tag1 != tag2) {+                res = FALSE;+            } else {+                p1 = JS_VALUE_GET_PTR(op1);+                p2 = JS_VALUE_GET_PTR(op2);+                res = (p1 == p2);+            }+        }+        break;+    case JS_TAG_OBJECT:+        if (tag1 != tag2)+            res = FALSE;+        else+            res = JS_VALUE_GET_OBJ(op1) == JS_VALUE_GET_OBJ(op2);+        break;+    case JS_TAG_INT:+        d1 = JS_VALUE_GET_INT(op1);+        if (tag2 == JS_TAG_INT) {+            d2 = JS_VALUE_GET_INT(op2);+            goto number_test;+        } else if (tag2 == JS_TAG_FLOAT64) {+            d2 = JS_VALUE_GET_FLOAT64(op2);+            goto number_test;+        } else {+            res = FALSE;+        }+        break;+    case JS_TAG_FLOAT64:+        d1 = JS_VALUE_GET_FLOAT64(op1);+        if (tag2 == JS_TAG_FLOAT64) {+            d2 = JS_VALUE_GET_FLOAT64(op2);+        } else if (tag2 == JS_TAG_INT) {+            d2 = JS_VALUE_GET_INT(op2);+        } else {+            res = FALSE;+            break;+        }+    number_test:+        if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) {+            JSFloat64Union u1, u2;+            /* NaN is not always normalized, so this test is necessary */+            if (isnan(d1) || isnan(d2)) {+                res = isnan(d1) == isnan(d2);+            } else if (eq_mode == JS_EQ_SAME_VALUE_ZERO) {+                res = (d1 == d2); /* +0 == -0 */+            } else {+                u1.d = d1;+                u2.d = d2;+                res = (u1.u64 == u2.u64); /* +0 != -0 */+            }+        } else {+            res = (d1 == d2); /* if NaN return false and +0 == -0 */+        }+        goto done_no_free;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        {+            bf_t a_s, *a, b_s, *b;+            if (tag1 != tag2) {+                res = FALSE;+                break;+            }+            a = JS_ToBigFloat(ctx, &a_s, op1);+            b = JS_ToBigFloat(ctx, &b_s, op2);+            res = bf_cmp_eq(a, b);+            if (a == &a_s)+                bf_delete(a);+            if (b == &b_s)+                bf_delete(b);+        }+        break;+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p1, *p2;+            const bf_t *a, *b;+            if (tag1 != tag2) {+                res = FALSE;+                break;+            }+            p1 = JS_VALUE_GET_PTR(op1);+            p2 = JS_VALUE_GET_PTR(op2);+            a = &p1->num;+            b = &p2->num;+            if (unlikely(eq_mode >= JS_EQ_SAME_VALUE)) {+                if (eq_mode == JS_EQ_SAME_VALUE_ZERO &&+                           a->expn == BF_EXP_ZERO && b->expn == BF_EXP_ZERO) {+                    res = TRUE;+                } else {+                    res = (bf_cmp_full(a, b) == 0);+                }+            } else {+                res = bf_cmp_eq(a, b);+            }+        }+        break;+    case JS_TAG_BIG_DECIMAL:+        {+            JSBigDecimal *p1, *p2;+            const bfdec_t *a, *b;+            if (tag1 != tag2) {+                res = FALSE;+                break;+            }+            p1 = JS_VALUE_GET_PTR(op1);+            p2 = JS_VALUE_GET_PTR(op2);+            a = &p1->num;+            b = &p2->num;+            res = bfdec_cmp_eq(a, b);+        }+        break;+#endif+    default:+        res = FALSE;+        break;+    }+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+ done_no_free:+    return res;+}++static BOOL js_strict_eq(JSContext *ctx, JSValue op1, JSValue op2)+{+    return js_strict_eq2(ctx, op1, op2, JS_EQ_STRICT);+}++static BOOL js_same_value(JSContext *ctx, JSValueConst op1, JSValueConst op2)+{+    return js_strict_eq2(ctx,+                         JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),+                         JS_EQ_SAME_VALUE);+}++static BOOL js_same_value_zero(JSContext *ctx, JSValueConst op1, JSValueConst op2)+{+    return js_strict_eq2(ctx,+                         JS_DupValue(ctx, op1), JS_DupValue(ctx, op2),+                         JS_EQ_SAME_VALUE_ZERO);+}++static no_inline int js_strict_eq_slow(JSContext *ctx, JSValue *sp,+                                       BOOL is_neq)+{+    BOOL res;+    res = js_strict_eq(ctx, sp[-2], sp[-1]);+    sp[-2] = JS_NewBool(ctx, res ^ is_neq);+    return 0;+}++static __exception int js_operator_in(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    JSAtom atom;+    int ret;++    op1 = sp[-2];+    op2 = sp[-1];++    if (JS_VALUE_GET_TAG(op2) != JS_TAG_OBJECT) {+        JS_ThrowTypeError(ctx, "invalid 'in' operand");+        return -1;+    }+    atom = JS_ValueToAtom(ctx, op1);+    if (unlikely(atom == JS_ATOM_NULL))+        return -1;+    ret = JS_HasProperty(ctx, op2, atom);+    JS_FreeAtom(ctx, atom);+    if (ret < 0)+        return -1;+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    sp[-2] = JS_NewBool(ctx, ret);+    return 0;+}++static __exception int js_has_unscopable(JSContext *ctx, JSValueConst obj,+                                         JSAtom atom)+{+    JSValue arr, val;+    int ret;++    arr = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_unscopables);+    if (JS_IsException(arr))+        return -1;+    ret = 0;+    if (JS_IsObject(arr)) {+        val = JS_GetProperty(ctx, arr, atom);+        ret = JS_ToBoolFree(ctx, val);+    }+    JS_FreeValue(ctx, arr);+    return ret;+}++static __exception int js_operator_instanceof(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    BOOL ret;++    op1 = sp[-2];+    op2 = sp[-1];+    ret = JS_IsInstanceOf(ctx, op1, op2);+    if (ret < 0)+        return ret;+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    sp[-2] = JS_NewBool(ctx, ret);+    return 0;+}++static __exception int js_operator_typeof(JSContext *ctx, JSValueConst op1)+{+    JSAtom atom;+    uint32_t tag;++    tag = JS_VALUE_GET_NORM_TAG(op1);+    switch(tag) {+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        atom = JS_ATOM_bigint;+        break;+    case JS_TAG_BIG_FLOAT:+        atom = JS_ATOM_bigfloat;+        break;+    case JS_TAG_BIG_DECIMAL:+        atom = JS_ATOM_bigdecimal;+        break;+#endif+    case JS_TAG_INT:+    case JS_TAG_FLOAT64:+        atom = JS_ATOM_number;+        break;+    case JS_TAG_UNDEFINED:+        atom = JS_ATOM_undefined;+        break;+    case JS_TAG_BOOL:+        atom = JS_ATOM_boolean;+        break;+    case JS_TAG_STRING:+        atom = JS_ATOM_string;+        break;+    case JS_TAG_OBJECT:+        {+            JSObject *p;+            p = JS_VALUE_GET_OBJ(op1);+            if (unlikely(p->is_HTMLDDA)) +                atom = JS_ATOM_undefined;+            else if (JS_IsFunction(ctx, op1))+                atom = JS_ATOM_function;+            else+                goto obj_type;+        }+        break;+    case JS_TAG_NULL:+    obj_type:+        atom = JS_ATOM_object;+        break;+    case JS_TAG_SYMBOL:+        atom = JS_ATOM_symbol;+        break;+    default:+        atom = JS_ATOM_unknown;+        break;+    }+    return atom;+}++static __exception int js_operator_delete(JSContext *ctx, JSValue *sp)+{+    JSValue op1, op2;+    JSAtom atom;+    int ret;++    op1 = sp[-2];+    op2 = sp[-1];+    atom = JS_ValueToAtom(ctx, op2);+    if (unlikely(atom == JS_ATOM_NULL))+        return -1;+    ret = JS_DeleteProperty(ctx, op1, atom, JS_PROP_THROW_STRICT);+    JS_FreeAtom(ctx, atom);+    if (unlikely(ret < 0))+        return -1;+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    sp[-2] = JS_NewBool(ctx, ret);+    return 0;+}++static JSValue js_throw_type_error(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    return JS_ThrowTypeError(ctx, "invalid property access");+}++/* XXX: not 100% compatible, but mozilla seems to use a similar+   implementation to ensure that caller in non strict mode does not+   throw (ES5 compatibility) */+static JSValue js_function_proto_caller(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);+    if (!b || (b->js_mode & JS_MODE_STRICT) || !b->has_prototype) {+        return js_throw_type_error(ctx, this_val, 0, NULL);+    }+    return JS_UNDEFINED;+}++static JSValue js_function_proto_fileName(JSContext *ctx,+                                          JSValueConst this_val)+{+    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);+    if (b && b->has_debug) {+        return JS_AtomToString(ctx, b->debug.filename);+    }+    return JS_UNDEFINED;+}++static JSValue js_function_proto_lineNumber(JSContext *ctx,+                                            JSValueConst this_val)+{+    JSFunctionBytecode *b = JS_GetFunctionBytecode(this_val);+    if (b && b->has_debug) {+        return JS_NewInt32(ctx, b->debug.line_num);+    }+    return JS_UNDEFINED;+}++static int js_arguments_define_own_property(JSContext *ctx,+                                            JSValueConst this_obj,+                                            JSAtom prop, JSValueConst val,+                                            JSValueConst getter, JSValueConst setter, int flags)+{+    JSObject *p;+    uint32_t idx;+    p = JS_VALUE_GET_OBJ(this_obj);+    /* convert to normal array when redefining an existing numeric field */+    if (p->fast_array && JS_AtomIsArrayIndex(ctx, &idx, prop) &&+        idx < p->u.array.count) {+        if (convert_fast_array_to_array(ctx, p))+            return -1;+    }+    /* run the default define own property */+    return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,+                             flags | JS_PROP_NO_EXOTIC);+}++static const JSClassExoticMethods js_arguments_exotic_methods = {+    .define_own_property = js_arguments_define_own_property,+};++static JSValue js_build_arguments(JSContext *ctx, int argc, JSValueConst *argv)+{+    JSValue val, *tab;+    JSProperty *pr;+    JSObject *p;+    int i;++    val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                                 JS_CLASS_ARGUMENTS);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_OBJ(val);++    /* add the length field (cannot fail) */+    pr = add_property(ctx, p, JS_ATOM_length,+                      JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    pr->u.value = JS_NewInt32(ctx, argc);++    /* initialize the fast array part */+    tab = NULL;+    if (argc > 0) {+        tab = js_malloc(ctx, sizeof(tab[0]) * argc);+        if (!tab) {+            JS_FreeValue(ctx, val);+            return JS_EXCEPTION;+        }+        for(i = 0; i < argc; i++) {+            tab[i] = JS_DupValue(ctx, argv[i]);+        }+    }+    p->u.array.u.values = tab;+    p->u.array.count = argc;++    JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,+                           JS_DupValue(ctx, ctx->array_proto_values),+                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);+    /* add callee property to throw a TypeError in strict mode */+    JS_DefineProperty(ctx, val, JS_ATOM_callee, JS_UNDEFINED,+                      ctx->throw_type_error, ctx->throw_type_error,+                      JS_PROP_HAS_GET | JS_PROP_HAS_SET);+    return val;+}++#define GLOBAL_VAR_OFFSET 0x40000000+#define ARGUMENT_VAR_OFFSET 0x20000000++/* legacy arguments object: add references to the function arguments */+static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,+                                         JSValueConst *argv,+                                         JSStackFrame *sf, int arg_count)+{+    JSValue val;+    JSProperty *pr;+    JSObject *p;+    int i;++    val = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                                 JS_CLASS_MAPPED_ARGUMENTS);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_OBJ(val);++    /* add the length field (cannot fail) */+    pr = add_property(ctx, p, JS_ATOM_length,+                      JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    pr->u.value = JS_NewInt32(ctx, argc);++    for(i = 0; i < arg_count; i++) {+        JSVarRef *var_ref;+        var_ref = get_var_ref(ctx, sf, i, TRUE);+        if (!var_ref)+            goto fail;+        pr = add_property(ctx, p, __JS_AtomFromUInt32(i), JS_PROP_C_W_E | JS_PROP_VARREF);+        if (!pr) {+            free_var_ref(ctx->rt, var_ref);+            goto fail;+        }+        pr->u.var_ref = var_ref;+    }++    /* the arguments not mapped to the arguments of the function can+       be normal properties */+    for(i = arg_count; i < argc; i++) {+        if (JS_DefinePropertyValueUint32(ctx, val, i,+                                         JS_DupValue(ctx, argv[i]),+                                         JS_PROP_C_W_E) < 0)+            goto fail;+    }++    JS_DefinePropertyValue(ctx, val, JS_ATOM_Symbol_iterator,+                           JS_DupValue(ctx, ctx->array_proto_values),+                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);+    /* callee returns this function in non strict mode */+    JS_DefinePropertyValue(ctx, val, JS_ATOM_callee,+                           JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func),+                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);+    return val;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_build_rest(JSContext *ctx, int first, int argc, JSValueConst *argv)+{+    JSValue val;+    int i, ret;++    val = JS_NewArray(ctx);+    if (JS_IsException(val))+        return val;+    for (i = first; i < argc; i++) {+        ret = JS_DefinePropertyValueUint32(ctx, val, i - first,+                                           JS_DupValue(ctx, argv[i]),+                                           JS_PROP_C_W_E);+        if (ret < 0) {+            JS_FreeValue(ctx, val);+            return JS_EXCEPTION;+        }+    }+    return val;+}++static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj)+{+    JSObject *p, *p1;+    JSPropertyEnum *tab_atom;+    int i;+    JSValue enum_obj;+    JSForInIterator *it;+    uint32_t tag, tab_atom_count;++    tag = JS_VALUE_GET_TAG(obj);+    if (tag != JS_TAG_OBJECT && tag != JS_TAG_NULL && tag != JS_TAG_UNDEFINED) {+        obj = JS_ToObjectFree(ctx, obj);+    }++    it = js_malloc(ctx, sizeof(*it));+    if (!it) {+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    enum_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_FOR_IN_ITERATOR);+    if (JS_IsException(enum_obj)) {+        js_free(ctx, it);+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    it->is_array = FALSE;+    it->obj = obj;+    it->idx = 0;+    p = JS_VALUE_GET_OBJ(enum_obj);+    p->u.for_in_iterator = it;++    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED)+        return enum_obj;++    p = JS_VALUE_GET_OBJ(obj);++    /* fast path: assume no enumerable properties in the prototype chain */+    p1 = p->shape->proto;+    while (p1 != NULL) {+        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p1,+                                   JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))+            goto fail;+        js_free_prop_enum(ctx, tab_atom, tab_atom_count);+        if (tab_atom_count != 0) {+            goto slow_path;+        }+        p1 = p1->shape->proto;+    }+    if (p->fast_array) {+        JSShape *sh;+        JSShapeProperty *prs;+        /* check that there are no enumerable normal fields */+        sh = p->shape;+        for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {+            if (prs->flags & JS_PROP_ENUMERABLE)+                goto normal_case;+        }+        /* for fast arrays, we only store the number of elements */+        it->is_array = TRUE;+        it->array_length = p->u.array.count;+    } else {+    normal_case:+        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,+                                   JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY))+            goto fail;+        for(i = 0; i < tab_atom_count; i++) {+            JS_SetPropertyInternal(ctx, enum_obj, tab_atom[i].atom, JS_NULL, 0);+        }+        js_free_prop_enum(ctx, tab_atom, tab_atom_count);+    }+    return enum_obj;++ slow_path:+    /* non enumerable properties hide the enumerables ones in the+       prototype chain */+    while (p != NULL) {+        if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,+                                   JS_GPN_STRING_MASK | JS_GPN_SET_ENUM))+            goto fail;+        for(i = 0; i < tab_atom_count; i++) {+            JS_DefinePropertyValue(ctx, enum_obj, tab_atom[i].atom, JS_NULL,+                                   (tab_atom[i].is_enumerable ?+                                    JS_PROP_ENUMERABLE : 0));+        }+        js_free_prop_enum(ctx, tab_atom, tab_atom_count);+        p = p->shape->proto;+    }+    return enum_obj;++ fail:+    JS_FreeValue(ctx, enum_obj);+    return JS_EXCEPTION;+}++/* obj -> enum_obj */+static __exception int js_for_in_start(JSContext *ctx, JSValue *sp)+{+    sp[-1] = build_for_in_iterator(ctx, sp[-1]);+    if (JS_IsException(sp[-1]))+        return -1;+    return 0;+}++/* enum_obj -> enum_obj value done */+static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)+{+    JSValueConst enum_obj;+    JSObject *p;+    JSAtom prop;+    JSForInIterator *it;+    int ret;++    enum_obj = sp[-1];+    /* fail safe */+    if (JS_VALUE_GET_TAG(enum_obj) != JS_TAG_OBJECT)+        goto done;+    p = JS_VALUE_GET_OBJ(enum_obj);+    if (p->class_id != JS_CLASS_FOR_IN_ITERATOR)+        goto done;+    it = p->u.for_in_iterator;++    for(;;) {+        if (it->is_array) {+            if (it->idx >= it->array_length)+                goto done;+            prop = __JS_AtomFromUInt32(it->idx);+            it->idx++;+        } else {+            JSShape *sh = p->shape;+            JSShapeProperty *prs;+            if (it->idx >= sh->prop_count)+                goto done;+            prs = get_shape_prop(sh) + it->idx;+            prop = prs->atom;+            it->idx++;+            if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE))+                continue;+        }+        /* check if the property was deleted */+        ret = JS_HasProperty(ctx, it->obj, prop);+        if (ret < 0)+            return ret;+        if (ret)+            break;+    }+    /* return the property */+    sp[0] = JS_AtomToValue(ctx, prop);+    sp[1] = JS_FALSE;+    return 0;+ done:+    /* return the end */+    sp[0] = JS_UNDEFINED;+    sp[1] = JS_TRUE;+    return 0;+}++static JSValue JS_GetIterator2(JSContext *ctx, JSValueConst obj,+                               JSValueConst method)+{+    JSValue enum_obj;++    enum_obj = JS_Call(ctx, method, obj, 0, NULL);+    if (JS_IsException(enum_obj))+        return enum_obj;+    if (!JS_IsObject(enum_obj)) {+        JS_FreeValue(ctx, enum_obj);+        return JS_ThrowTypeErrorNotAnObject(ctx);+    }+    return enum_obj;+}++static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async)+{+    JSValue method, ret, sync_iter;++    if (is_async) {+        method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_asyncIterator);+        if (JS_IsException(method))+            return method;+        if (JS_IsUndefined(method) || JS_IsNull(method)) {+            method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);+            if (JS_IsException(method))+                return method;+            sync_iter = JS_GetIterator2(ctx, obj, method);+            JS_FreeValue(ctx, method);+            if (JS_IsException(sync_iter))+                return sync_iter;+            ret = JS_CreateAsyncFromSyncIterator(ctx, sync_iter);+            JS_FreeValue(ctx, sync_iter);+            return ret;+        }+    } else {+        method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);+        if (JS_IsException(method))+            return method;+    }+    if (!JS_IsFunction(ctx, method)) {+        JS_FreeValue(ctx, method);+        return JS_ThrowTypeError(ctx, "value is not iterable");+    }+    ret = JS_GetIterator2(ctx, obj, method);+    JS_FreeValue(ctx, method);+    return ret;+}++/* return *pdone = 2 if the iterator object is not parsed */+static JSValue JS_IteratorNext2(JSContext *ctx, JSValueConst enum_obj,+                                JSValueConst method,+                                int argc, JSValueConst *argv, int *pdone)+{+    JSValue obj;++    /* fast path for the built-in iterators (avoid creating the+       intermediate result object) */+    if (JS_IsObject(method)) {+        JSObject *p = JS_VALUE_GET_OBJ(method);+        if (p->class_id == JS_CLASS_C_FUNCTION &&+            p->u.cfunc.cproto == JS_CFUNC_iterator_next) {+            JSCFunctionType func;+            JSValueConst args[1];++            /* in case the function expects one argument */+            if (argc == 0) {+                args[0] = JS_UNDEFINED;+                argv = args;+            }+            func = p->u.cfunc.c_function;+            return func.iterator_next(ctx, enum_obj, argc, argv,+                                      pdone, p->u.cfunc.magic);+        }+    }+    obj = JS_Call(ctx, method, enum_obj, argc, argv);+    if (JS_IsException(obj))+        goto fail;+    if (!JS_IsObject(obj)) {+        JS_FreeValue(ctx, obj);+        JS_ThrowTypeError(ctx, "iterator must return an object");+        goto fail;+    }+    *pdone = 2;+    return obj;+ fail:+    *pdone = FALSE;+    return JS_EXCEPTION;+}++static JSValue JS_IteratorNext(JSContext *ctx, JSValueConst enum_obj,+                               JSValueConst method,+                               int argc, JSValueConst *argv, BOOL *pdone)+{+    JSValue obj, value, done_val;+    int done;++    obj = JS_IteratorNext2(ctx, enum_obj, method, argc, argv, &done);+    if (JS_IsException(obj))+        goto fail;+    if (done != 2) {+        *pdone = done;+        return obj;+    } else {+        done_val = JS_GetProperty(ctx, obj, JS_ATOM_done);+        if (JS_IsException(done_val))+            goto fail;+        *pdone = JS_ToBoolFree(ctx, done_val);+        value = JS_UNDEFINED;+        if (!*pdone) {+            value = JS_GetProperty(ctx, obj, JS_ATOM_value);+        }+        JS_FreeValue(ctx, obj);+        return value;+    }+ fail:+    JS_FreeValue(ctx, obj);+    *pdone = FALSE;+    return JS_EXCEPTION;+}++/* return < 0 in case of exception */+static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,+                            BOOL is_exception_pending)+{+    JSValue method, ret, ex_obj;+    int res;++    if (is_exception_pending) {+        ex_obj = ctx->rt->current_exception;+        ctx->rt->current_exception = JS_NULL;+        res = -1;+    } else {+        ex_obj = JS_UNDEFINED;+        res = 0;+    }+    method = JS_GetProperty(ctx, enum_obj, JS_ATOM_return);+    if (JS_IsException(method)) {+        res = -1;+        goto done;+    }+    if (JS_IsUndefined(method) || JS_IsNull(method)) {+        goto done;+    }+    ret = JS_CallFree(ctx, method, enum_obj, 0, NULL);+    if (!is_exception_pending) {+        if (JS_IsException(ret)) {+            res = -1;+        } else if (!JS_IsObject(ret)) {+            JS_ThrowTypeErrorNotAnObject(ctx);+            res = -1;+        }+    }+    JS_FreeValue(ctx, ret);+ done:+    if (is_exception_pending) {+        JS_Throw(ctx, ex_obj);+    }+    return res;+}++/* obj -> enum_rec (3 slots) */+static __exception int js_for_of_start(JSContext *ctx, JSValue *sp,+                                       BOOL is_async)+{+    JSValue op1, obj, method;+    op1 = sp[-1];+    obj = JS_GetIterator(ctx, op1, is_async);+    if (JS_IsException(obj))+        return -1;+    JS_FreeValue(ctx, op1);+    sp[-1] = obj;+    method = JS_GetProperty(ctx, obj, JS_ATOM_next);+    if (JS_IsException(method))+        return -1;+    sp[0] = method;+    return 0;+}++/* enum_rec [objs] -> enum_rec [objs] value done. There are 'offset'+   objs. If 'done' is true or in case of exception, 'enum_rec' is set+   to undefined. If 'done' is true, 'value' is always set to+   undefined. */+static __exception int js_for_of_next(JSContext *ctx, JSValue *sp, int offset)+{+    JSValue value = JS_UNDEFINED;+    int done = 1;++    if (likely(!JS_IsUndefined(sp[offset]))) {+        value = JS_IteratorNext(ctx, sp[offset], sp[offset + 1], 0, NULL, &done);+        if (JS_IsException(value))+            done = -1;+        if (done) {+            /* value is JS_UNDEFINED or JS_EXCEPTION */+            /* replace the iteration object with undefined */+            JS_FreeValue(ctx, sp[offset]);+            sp[offset] = JS_UNDEFINED;+            if (done < 0) {+                return -1;+            } else {+                JS_FreeValue(ctx, value);+                value = JS_UNDEFINED;+            }+        }+    }+    sp[0] = value;+    sp[1] = JS_NewBool(ctx, done);+    return 0;+}++static JSValue JS_IteratorGetCompleteValue(JSContext *ctx, JSValueConst obj,+                                           BOOL *pdone)+{+    JSValue done_val, value;+    BOOL done;+    done_val = JS_GetProperty(ctx, obj, JS_ATOM_done);+    if (JS_IsException(done_val))+        goto fail;+    done = JS_ToBoolFree(ctx, done_val);+    value = JS_GetProperty(ctx, obj, JS_ATOM_value);+    if (JS_IsException(value))+        goto fail;+    *pdone = done;+    return value;+ fail:+    *pdone = FALSE;+    return JS_EXCEPTION;+}++static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp)+{+    JSValue obj, value;+    BOOL done;+    obj = sp[-1];+    if (!JS_IsObject(obj)) {+        JS_ThrowTypeError(ctx, "iterator must return an object");+        return -1;+    }+    value = JS_IteratorGetCompleteValue(ctx, obj, &done);+    if (JS_IsException(value))+        return -1;+    JS_FreeValue(ctx, obj);+    sp[-1] = value;+    sp[0] = JS_NewBool(ctx, done);+    return 0;+}++static JSValue js_create_iterator_result(JSContext *ctx,+                                         JSValue val,+                                         BOOL done)+{+    JSValue obj;+    obj = JS_NewObject(ctx);+    if (JS_IsException(obj)) {+        JS_FreeValue(ctx, val);+        return obj;+    }+    if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_value,+                               val, JS_PROP_C_W_E) < 0) {+        goto fail;+    }+    if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_done,+                               JS_NewBool(ctx, done), JS_PROP_C_W_E) < 0) {+    fail:+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    return obj;+}++static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv,+                                      BOOL *pdone, int magic);++static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv, int magic);++static BOOL js_is_fast_array(JSContext *ctx, JSValueConst obj)+{+    /* Try and handle fast arrays explicitly */+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(obj);+        if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {+            return TRUE;+        }+    }+    return FALSE;+}++/* Access an Array's internal JSValue array if available */+static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj,+                              JSValue **arrpp, uint32_t *countp)+{+    /* Try and handle fast arrays explicitly */+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(obj);+        if (p->class_id == JS_CLASS_ARRAY && p->fast_array) {+            *countp = p->u.array.count;+            *arrpp = p->u.array.u.values;+            return TRUE;+        }+    }+    return FALSE;+}++static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)+{+    JSValue iterator, enumobj, method, value;+    int is_array_iterator;+    JSValue *arrp;+    uint32_t i, count32, pos;+    +    if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {+        JS_ThrowInternalError(ctx, "invalid index for append");+        return -1;+    }++    pos = JS_VALUE_GET_INT(sp[-2]);++    /* XXX: further optimisations:+       - use ctx->array_proto_values?+       - check if array_iterator_prototype next method is built-in and+         avoid constructing actual iterator object?+       - build this into js_for_of_start and use in all `for (x of o)` loops+     */+    iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator);+    if (JS_IsException(iterator))+        return -1;+    is_array_iterator = JS_IsCFunction(ctx, iterator,+                                       (JSCFunction *)js_create_array_iterator,+                                       JS_ITERATOR_KIND_VALUE);+    JS_FreeValue(ctx, iterator);++    enumobj = JS_GetIterator(ctx, sp[-1], FALSE);+    if (JS_IsException(enumobj))+        return -1;+    method = JS_GetProperty(ctx, enumobj, JS_ATOM_next);+    if (JS_IsException(method)) {+        JS_FreeValue(ctx, enumobj);+        return -1;+    }+    if (is_array_iterator+    &&  JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)+    &&  js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {+        uint32_t len;+        if (js_get_length32(ctx, &len, sp[-1]))+            goto exception;+        /* if len > count32, the elements >= count32 might be read in+           the prototypes and might have side effects */+        if (len != count32)+            goto general_case;+        /* Handle fast arrays explicitly */+        for (i = 0; i < count32; i++) {+            if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++,+                                             JS_DupValue(ctx, arrp[i]), JS_PROP_C_W_E) < 0)+                goto exception;+        }+    } else {+    general_case:+        for (;;) {+            BOOL done;+            value = JS_IteratorNext(ctx, enumobj, method, 0, NULL, &done);+            if (JS_IsException(value))+                goto exception;+            if (done) {+                /* value is JS_UNDEFINED */+                break;+            }+            if (JS_DefinePropertyValueUint32(ctx, sp[-3], pos++, value, JS_PROP_C_W_E) < 0)+                goto exception;+        }+    }+    /* Note: could raise an error if too many elements */+    sp[-2] = JS_NewInt32(ctx, pos);+    JS_FreeValue(ctx, enumobj);+    JS_FreeValue(ctx, method);+    return 0;++exception:+    JS_IteratorClose(ctx, enumobj, TRUE);+    JS_FreeValue(ctx, enumobj);+    JS_FreeValue(ctx, method);+    return -1;+}++static __exception int JS_CopyDataProperties(JSContext *ctx,+                                             JSValueConst target,+                                             JSValueConst source,+                                             JSValueConst excluded,+                                             BOOL setprop)+{+    JSPropertyEnum *tab_atom;+    JSValue val;+    uint32_t i, tab_atom_count;+    JSObject *p;+    JSObject *pexcl = NULL;+    int ret = 0, flags;++    if (JS_VALUE_GET_TAG(source) != JS_TAG_OBJECT)+        return 0;++    if (JS_VALUE_GET_TAG(excluded) == JS_TAG_OBJECT)+        pexcl = JS_VALUE_GET_OBJ(excluded);++    p = JS_VALUE_GET_OBJ(source);+    if (JS_GetOwnPropertyNamesInternal(ctx, &tab_atom, &tab_atom_count, p,+                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK |+                               JS_GPN_ENUM_ONLY))+        return -1;++    flags = JS_PROP_C_W_E;++    for (i = 0; i < tab_atom_count; i++) {+        if (pexcl) {+            ret = JS_GetOwnPropertyInternal(ctx, NULL, pexcl, tab_atom[i].atom);+            if (ret) {+                if (ret < 0)+                    break;+                ret = 0;+                continue;+            }+        }+        ret = -1;+        val = JS_GetProperty(ctx, source, tab_atom[i].atom);+        if (JS_IsException(val))+            break;+        if (setprop)+            ret = JS_SetProperty(ctx, target, tab_atom[i].atom, val);+        else+            ret = JS_DefinePropertyValue(ctx, target, tab_atom[i].atom, val, flags);+        if (ret < 0)+            break;+        ret = 0;+    }+    js_free_prop_enum(ctx, tab_atom, tab_atom_count);+    return ret;+}++/* only valid inside C functions */+static JSValueConst JS_GetActiveFunction(JSContext *ctx)+{+    return ctx->rt->current_stack_frame->cur_func;+}++static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,+                             int var_idx, BOOL is_arg)+{+    JSVarRef *var_ref;+    struct list_head *el;++    list_for_each(el, &sf->var_ref_list) {+        var_ref = list_entry(el, JSVarRef, header.link);+        if (var_ref->var_idx == var_idx && var_ref->is_arg == is_arg) {+            var_ref->header.ref_count++;+            return var_ref;+        }+    }+    /* create a new one */+    var_ref = js_malloc(ctx, sizeof(JSVarRef));+    if (!var_ref)+        return NULL;+    var_ref->header.ref_count = 1;+    var_ref->is_detached = FALSE;+    var_ref->is_arg = is_arg;+    var_ref->var_idx = var_idx;+    list_add_tail(&var_ref->header.link, &sf->var_ref_list);+    if (is_arg)+        var_ref->pvalue = &sf->arg_buf[var_idx];+    else+        var_ref->pvalue = &sf->var_buf[var_idx];+    var_ref->value = JS_UNDEFINED;+    return var_ref;+}++static JSValue js_closure2(JSContext *ctx, JSValue func_obj,+                           JSFunctionBytecode *b,+                           JSVarRef **cur_var_refs,+                           JSStackFrame *sf)+{+    JSObject *p;+    JSVarRef **var_refs;+    int i;++    p = JS_VALUE_GET_OBJ(func_obj);+    p->u.func.function_bytecode = b;+    p->u.func.home_object = NULL;+    p->u.func.var_refs = NULL;+    if (b->closure_var_count) {+        var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count);+        if (!var_refs)+            goto fail;+        p->u.func.var_refs = var_refs;+        for(i = 0; i < b->closure_var_count; i++) {+            JSClosureVar *cv = &b->closure_var[i];+            JSVarRef *var_ref;+            if (cv->is_local) {+                /* reuse the existing variable reference if it already exists */+                var_ref = get_var_ref(ctx, sf, cv->var_idx, cv->is_arg);+                if (!var_ref)+                    goto fail;+            } else {+                var_ref = cur_var_refs[cv->var_idx];+                var_ref->header.ref_count++;+            }+            var_refs[i] = var_ref;+        }+    }+    return func_obj;+ fail:+    /* bfunc is freed when func_obj is freed */+    JS_FreeValue(ctx, func_obj);+    return JS_EXCEPTION;+}++static JSValue js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque)+{+    JSValue obj, this_val;+    int ret;++    this_val = JS_MKPTR(JS_TAG_OBJECT, p);+    obj = JS_NewObject(ctx);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    set_cycle_flag(ctx, obj);+    set_cycle_flag(ctx, this_val);+    ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_constructor,+                                 JS_DupValue(ctx, this_val),+                                 JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    if (ret < 0) {+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    return obj;+}++static const uint16_t func_kind_to_class_id[] = {+    [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION,+    [JS_FUNC_GENERATOR] = JS_CLASS_GENERATOR_FUNCTION,+    [JS_FUNC_ASYNC] = JS_CLASS_ASYNC_FUNCTION,+    [JS_FUNC_ASYNC_GENERATOR] = JS_CLASS_ASYNC_GENERATOR_FUNCTION,+};++static JSValue js_closure(JSContext *ctx, JSValue bfunc,+                          JSVarRef **cur_var_refs,+                          JSStackFrame *sf)+{+    JSFunctionBytecode *b;+    JSValue func_obj;+    JSAtom name_atom;++    b = JS_VALUE_GET_PTR(bfunc);+    func_obj = JS_NewObjectClass(ctx, func_kind_to_class_id[b->func_kind]);+    if (JS_IsException(func_obj)) {+        JS_FreeValue(ctx, bfunc);+        return JS_EXCEPTION;+    }+    func_obj = js_closure2(ctx, func_obj, b, cur_var_refs, sf);+    if (JS_IsException(func_obj)) {+        /* bfunc has been freed */+        goto fail;+    }+    name_atom = b->func_name;+    if (name_atom == JS_ATOM_NULL)+        name_atom = JS_ATOM_empty_string;+    js_function_set_properties(ctx, func_obj, name_atom,+                               b->defined_arg_count);++    if (b->func_kind & JS_FUNC_GENERATOR) {+        JSValue proto;+        int proto_class_id;+        /* generators have a prototype field which is used as+           prototype for the generator object */+        if (b->func_kind == JS_FUNC_ASYNC_GENERATOR)+            proto_class_id = JS_CLASS_ASYNC_GENERATOR;+        else+            proto_class_id = JS_CLASS_GENERATOR;+        proto = JS_NewObjectProto(ctx, ctx->class_proto[proto_class_id]);+        if (JS_IsException(proto))+            goto fail;+        JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype, proto,+                               JS_PROP_WRITABLE);+    } else if (b->has_prototype) {+        /* add the 'prototype' property: delay instantiation to avoid+           creating cycles for every javascript function. The prototype+           object is created on the fly when first accessed */+        JS_SetConstructorBit(ctx, func_obj, TRUE);+        JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype,+                                  JS_AUTOINIT_ID_PROTOTYPE, NULL,+                                  JS_PROP_WRITABLE);+    }+    return func_obj;+ fail:+    /* bfunc is freed when func_obj is freed */+    JS_FreeValue(ctx, func_obj);+    return JS_EXCEPTION;+}++#define JS_DEFINE_CLASS_HAS_HERITAGE     (1 << 0)++static int js_op_define_class(JSContext *ctx, JSValue *sp,+                              JSAtom class_name, int class_flags,+                              JSVarRef **cur_var_refs,+                              JSStackFrame *sf, BOOL is_computed_name)+{+    JSValue bfunc, parent_class, proto = JS_UNDEFINED;+    JSValue ctor = JS_UNDEFINED, parent_proto = JS_UNDEFINED;+    JSFunctionBytecode *b;++    parent_class = sp[-2];+    bfunc = sp[-1];++    if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE) {+        if (JS_IsNull(parent_class)) {+            parent_proto = JS_NULL;+            parent_class = JS_DupValue(ctx, ctx->function_proto);+        } else {+            if (!JS_IsConstructor(ctx, parent_class)) {+                JS_ThrowTypeError(ctx, "parent class must be constructor");+                goto fail;+            }+            parent_proto = JS_GetProperty(ctx, parent_class, JS_ATOM_prototype);+            if (JS_IsException(parent_proto))+                goto fail;+            if (!JS_IsNull(parent_proto) && !JS_IsObject(parent_proto)) {+                JS_ThrowTypeError(ctx, "parent prototype must be an object or null");+                goto fail;+            }+        }+    } else {+        /* parent_class is JS_UNDEFINED in this case */+        parent_proto = JS_DupValue(ctx, ctx->class_proto[JS_CLASS_OBJECT]);+        parent_class = JS_DupValue(ctx, ctx->function_proto);+    }+    proto = JS_NewObjectProto(ctx, parent_proto);+    if (JS_IsException(proto))+        goto fail;++    b = JS_VALUE_GET_PTR(bfunc);+    assert(b->func_kind == JS_FUNC_NORMAL);+    ctor = JS_NewObjectProtoClass(ctx, parent_class,+                                  JS_CLASS_BYTECODE_FUNCTION);+    if (JS_IsException(ctor))+        goto fail;+    ctor = js_closure2(ctx, ctor, b, cur_var_refs, sf);+    bfunc = JS_UNDEFINED;+    if (JS_IsException(ctor))+        goto fail;+    js_method_set_home_object(ctx, ctor, proto);+    JS_SetConstructorBit(ctx, ctor, TRUE);++    JS_DefinePropertyValue(ctx, ctor, JS_ATOM_length,+                           JS_NewInt32(ctx, b->defined_arg_count),+                           JS_PROP_CONFIGURABLE);++    if (is_computed_name) {+        if (JS_DefineObjectNameComputed(ctx, ctor, sp[-3],+                                        JS_PROP_CONFIGURABLE) < 0)+            goto fail;+    } else {+        if (JS_DefineObjectName(ctx, ctor, class_name, JS_PROP_CONFIGURABLE) < 0)+            goto fail;+    }++    /* the constructor property must be first. It can be overriden by+       computed property names */+    if (JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,+                               JS_DupValue(ctx, ctor),+                               JS_PROP_CONFIGURABLE |+                               JS_PROP_WRITABLE | JS_PROP_THROW) < 0)+        goto fail;+    /* set the prototype property */+    if (JS_DefinePropertyValue(ctx, ctor, JS_ATOM_prototype,+                               JS_DupValue(ctx, proto), JS_PROP_THROW) < 0)+        goto fail;+    set_cycle_flag(ctx, ctor);+    set_cycle_flag(ctx, proto);++    JS_FreeValue(ctx, parent_proto);+    JS_FreeValue(ctx, parent_class);++    sp[-2] = ctor;+    sp[-1] = proto;+    return 0;+ fail:+    JS_FreeValue(ctx, parent_class);+    JS_FreeValue(ctx, parent_proto);+    JS_FreeValue(ctx, bfunc);+    JS_FreeValue(ctx, proto);+    JS_FreeValue(ctx, ctor);+    sp[-2] = JS_UNDEFINED;+    sp[-1] = JS_UNDEFINED;+    return -1;+}++static void close_var_refs(JSRuntime *rt, JSStackFrame *sf)+{+    struct list_head *el, *el1;+    JSVarRef *var_ref;+    int var_idx;++    list_for_each_safe(el, el1, &sf->var_ref_list) {+        var_ref = list_entry(el, JSVarRef, header.link);+        var_idx = var_ref->var_idx;+        if (var_ref->is_arg)+            var_ref->value = JS_DupValueRT(rt, sf->arg_buf[var_idx]);+        else+            var_ref->value = JS_DupValueRT(rt, sf->var_buf[var_idx]);+        var_ref->pvalue = &var_ref->value;+        /* the reference is no longer to a local variable */+        var_ref->is_detached = TRUE;+        add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);+    }+}++static void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_arg)+{+    struct list_head *el, *el1;+    JSVarRef *var_ref;+    int var_idx = idx;++    list_for_each_safe(el, el1, &sf->var_ref_list) {+        var_ref = list_entry(el, JSVarRef, header.link);+        if (var_idx == var_ref->var_idx && var_ref->is_arg == is_arg) {+            var_ref->value = JS_DupValue(ctx, sf->var_buf[var_idx]);+            var_ref->pvalue = &var_ref->value;+            list_del(&var_ref->header.link);+            /* the reference is no longer to a local variable */+            var_ref->is_detached = TRUE;+            add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);+        }+    }+}++#define JS_CALL_FLAG_COPY_ARGV   (1 << 1)+#define JS_CALL_FLAG_GENERATOR   (1 << 2)++static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,+                                  JSValueConst this_obj,+                                  int argc, JSValueConst *argv, int flags)+{+    JSRuntime *rt = ctx->rt;+    JSCFunctionType func;+    JSObject *p;+    JSStackFrame sf_s, *sf = &sf_s, *prev_sf;+    JSValue ret_val;+    JSValueConst *arg_buf;+    int arg_count, i;+    JSCFunctionEnum cproto;++    p = JS_VALUE_GET_OBJ(func_obj);+    cproto = p->u.cfunc.cproto;+    arg_count = p->u.cfunc.length;++    /* better to always check stack overflow */+    if (js_check_stack_overflow(rt, sizeof(arg_buf[0]) * arg_count))+        return JS_ThrowStackOverflow(ctx);++    prev_sf = rt->current_stack_frame;+    sf->prev_frame = prev_sf;+    rt->current_stack_frame = sf;+    ctx = p->u.cfunc.realm; /* change the current realm */+    +#ifdef CONFIG_BIGNUM+    /* we only propagate the bignum mode as some runtime functions+       test it */+    if (prev_sf)+        sf->js_mode = prev_sf->js_mode & JS_MODE_MATH;+    else+        sf->js_mode = 0;+#else+    sf->js_mode = 0;+#endif+    sf->cur_func = (JSValue)func_obj;+    sf->arg_count = argc;+    arg_buf = argv;++    if (unlikely(argc < arg_count)) {+        /* ensure that at least argc_count arguments are readable */+        arg_buf = alloca(sizeof(arg_buf[0]) * arg_count);+        for(i = 0; i < argc; i++)+            arg_buf[i] = argv[i];+        for(i = argc; i < arg_count; i++)+            arg_buf[i] = JS_UNDEFINED;+        sf->arg_count = arg_count;+    }+    sf->arg_buf = (JSValue*)arg_buf;++    func = p->u.cfunc.c_function;+    switch(cproto) {+    case JS_CFUNC_constructor:+    case JS_CFUNC_constructor_or_func:+        if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) {+            if (cproto == JS_CFUNC_constructor) {+            not_a_constructor:+                ret_val = JS_ThrowTypeError(ctx, "must be called with new");+                break;+            } else {+                this_obj = JS_UNDEFINED;+            }+        }+        /* here this_obj is new_target */+        /* fall thru */+    case JS_CFUNC_generic:+        ret_val = func.generic(ctx, this_obj, argc, arg_buf);+        break;+    case JS_CFUNC_constructor_magic:+    case JS_CFUNC_constructor_or_func_magic:+        if (!(flags & JS_CALL_FLAG_CONSTRUCTOR)) {+            if (cproto == JS_CFUNC_constructor_magic) {+                goto not_a_constructor;+            } else {+                this_obj = JS_UNDEFINED;+            }+        }+        /* fall thru */+    case JS_CFUNC_generic_magic:+        ret_val = func.generic_magic(ctx, this_obj, argc, arg_buf,+                                     p->u.cfunc.magic);+        break;+    case JS_CFUNC_getter:+        ret_val = func.getter(ctx, this_obj);+        break;+    case JS_CFUNC_setter:+        ret_val = func.setter(ctx, this_obj, arg_buf[0]);+        break;+    case JS_CFUNC_getter_magic:+        ret_val = func.getter_magic(ctx, this_obj, p->u.cfunc.magic);+        break;+    case JS_CFUNC_setter_magic:+        ret_val = func.setter_magic(ctx, this_obj, arg_buf[0], p->u.cfunc.magic);+        break;+    case JS_CFUNC_f_f:+        {+            double d1;++            if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) {+                ret_val = JS_EXCEPTION;+                break;+            }+            ret_val = JS_NewFloat64(ctx, func.f_f(d1));+        }+        break;+    case JS_CFUNC_f_f_f:+        {+            double d1, d2;++            if (unlikely(JS_ToFloat64(ctx, &d1, arg_buf[0]))) {+                ret_val = JS_EXCEPTION;+                break;+            }+            if (unlikely(JS_ToFloat64(ctx, &d2, arg_buf[1]))) {+                ret_val = JS_EXCEPTION;+                break;+            }+            ret_val = JS_NewFloat64(ctx, func.f_f_f(d1, d2));+        }+        break;+    case JS_CFUNC_iterator_next:+        {+            int done;+            ret_val = func.iterator_next(ctx, this_obj, argc, arg_buf,+                                         &done, p->u.cfunc.magic);+            if (!JS_IsException(ret_val) && done != 2) {+                ret_val = js_create_iterator_result(ctx, ret_val, done);+            }+        }+        break;+    default:+        abort();+    }++    rt->current_stack_frame = sf->prev_frame;+    return ret_val;+}++static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,+                                      JSValueConst this_obj,+                                      int argc, JSValueConst *argv, int flags)+{+    JSObject *p;+    JSBoundFunction *bf;+    JSValueConst *arg_buf, new_target;+    int arg_count, i;++    p = JS_VALUE_GET_OBJ(func_obj);+    bf = p->u.bound_function;+    arg_count = bf->argc + argc;+    if (js_check_stack_overflow(ctx->rt, sizeof(JSValue) * arg_count))+        return JS_ThrowStackOverflow(ctx);+    arg_buf = alloca(sizeof(JSValue) * arg_count);+    for(i = 0; i < bf->argc; i++) {+        arg_buf[i] = bf->argv[i];+    }+    for(i = 0; i < argc; i++) {+        arg_buf[bf->argc + i] = argv[i];+    }+    if (flags & JS_CALL_FLAG_CONSTRUCTOR) {+        new_target = this_obj;+        if (js_same_value(ctx, func_obj, new_target))+            new_target = bf->func_obj;+        return JS_CallConstructor2(ctx, bf->func_obj, new_target,+                                   arg_count, arg_buf);+    } else {+        return JS_Call(ctx, bf->func_obj, bf->this_val,+                       arg_count, arg_buf);+    }+}++/* argument of OP_special_object */+typedef enum {+    OP_SPECIAL_OBJECT_ARGUMENTS,+    OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS,+    OP_SPECIAL_OBJECT_THIS_FUNC,+    OP_SPECIAL_OBJECT_NEW_TARGET,+    OP_SPECIAL_OBJECT_HOME_OBJECT,+    OP_SPECIAL_OBJECT_VAR_OBJECT,+    OP_SPECIAL_OBJECT_IMPORT_META,+} OPSpecialObjectEnum;++#define FUNC_RET_AWAIT      0+#define FUNC_RET_YIELD      1+#define FUNC_RET_YIELD_STAR 2++/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */+static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,+                               JSValueConst this_obj, JSValueConst new_target,+                               int argc, JSValue *argv, int flags)+{+    JSRuntime *rt = caller_ctx->rt;+    JSContext *ctx;+    JSObject *p;+    JSFunctionBytecode *b;+    JSStackFrame sf_s, *sf = &sf_s;+    const uint8_t *pc;+    int opcode, arg_allocated_size, i;+    JSValue *local_buf, *stack_buf, *var_buf, *arg_buf, *sp, ret_val, *pval;+    JSVarRef **var_refs;+    size_t alloca_size;++#if !DIRECT_DISPATCH+#define SWITCH(pc)      switch (opcode = *pc++)+#define CASE(op)        case op+#define DEFAULT         default+#define BREAK           break+#else+    static const void * const dispatch_table[256] = {+#define DEF(id, size, n_pop, n_push, f) && case_OP_ ## id,+#if SHORT_OPCODES+#define def(id, size, n_pop, n_push, f)+#else                                                     +#define def(id, size, n_pop, n_push, f) && case_default,+#endif+#include "quickjs-opcode.h"+        [ OP_COUNT ... 255 ] = &&case_default+    };+#define SWITCH(pc)      goto *dispatch_table[opcode = *pc++];+#define CASE(op)        case_ ## op+#define DEFAULT         case_default+#define BREAK           SWITCH(pc)+#endif++    if (js_poll_interrupts(caller_ctx))+        return JS_EXCEPTION;+    if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) {+        if (flags & JS_CALL_FLAG_GENERATOR) {+            JSAsyncFunctionState *s = JS_VALUE_GET_PTR(func_obj);+            /* func_obj get contains a pointer to JSFuncAsyncState */+            /* the stack frame is already allocated */+            sf = &s->frame;+            p = JS_VALUE_GET_OBJ(sf->cur_func);+            b = p->u.func.function_bytecode;+            ctx = b->realm;+            var_refs = p->u.func.var_refs;+            local_buf = arg_buf = sf->arg_buf;+            var_buf = sf->var_buf;+            stack_buf = sf->var_buf + b->var_count;+            sp = sf->cur_sp;+            sf->cur_sp = NULL; /* cur_sp is NULL if the function is running */+            pc = sf->cur_pc;+            sf->prev_frame = rt->current_stack_frame;+            rt->current_stack_frame = sf;+            if (s->throw_flag)+                goto exception;+            else+                goto restart;+        } else {+            goto not_a_function;+        }+    }+    p = JS_VALUE_GET_OBJ(func_obj);+    if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {+        JSClassCall *call_func;+        call_func = rt->class_array[p->class_id].call;+        if (!call_func) {+        not_a_function:+            return JS_ThrowTypeError(caller_ctx, "not a function");+        }+        return call_func(caller_ctx, func_obj, this_obj, argc,+                         (JSValueConst *)argv, flags);+    }+    b = p->u.func.function_bytecode;++    if (unlikely(argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV))) {+        arg_allocated_size = b->arg_count;+    } else {+        arg_allocated_size = 0;+    }++    alloca_size = sizeof(JSValue) * (arg_allocated_size + b->var_count ++                                     b->stack_size);+    if (js_check_stack_overflow(rt, alloca_size))+        return JS_ThrowStackOverflow(caller_ctx);++    sf->js_mode = b->js_mode;+    arg_buf = argv;+    sf->arg_count = argc;+    sf->cur_func = (JSValue)func_obj;+    init_list_head(&sf->var_ref_list);+    var_refs = p->u.func.var_refs;++    local_buf = alloca(alloca_size);+    if (unlikely(arg_allocated_size)) {+        int n = min_int(argc, b->arg_count);+        arg_buf = local_buf;+        for(i = 0; i < n; i++)+            arg_buf[i] = JS_DupValue(caller_ctx, argv[i]);+        for(; i < b->arg_count; i++)+            arg_buf[i] = JS_UNDEFINED;+        sf->arg_count = b->arg_count;+    }+    var_buf = local_buf + arg_allocated_size;+    sf->var_buf = var_buf;+    sf->arg_buf = arg_buf;++    for(i = 0; i < b->var_count; i++)+        var_buf[i] = JS_UNDEFINED;++    stack_buf = var_buf + b->var_count;+    sp = stack_buf;+    pc = b->byte_code_buf;+    sf->prev_frame = rt->current_stack_frame;+    rt->current_stack_frame = sf;+    ctx = b->realm; /* set the current realm */+    + restart:+    for(;;) {+        int call_argc;+        JSValue *call_argv;++        SWITCH(pc) {+        CASE(OP_push_i32):+            *sp++ = JS_NewInt32(ctx, get_u32(pc));+            pc += 4;+            BREAK;+        CASE(OP_push_const):+            *sp++ = JS_DupValue(ctx, b->cpool[get_u32(pc)]);+            pc += 4;+            BREAK;+#if SHORT_OPCODES+        CASE(OP_push_minus1):+        CASE(OP_push_0):+        CASE(OP_push_1):+        CASE(OP_push_2):+        CASE(OP_push_3):+        CASE(OP_push_4):+        CASE(OP_push_5):+        CASE(OP_push_6):+        CASE(OP_push_7):+            *sp++ = JS_NewInt32(ctx, opcode - OP_push_0);+            BREAK;+        CASE(OP_push_i8):+            *sp++ = JS_NewInt32(ctx, get_i8(pc));+            pc += 1;+            BREAK;+        CASE(OP_push_i16):+            *sp++ = JS_NewInt32(ctx, get_i16(pc));+            pc += 2;+            BREAK;+        CASE(OP_push_const8):+            *sp++ = JS_DupValue(ctx, b->cpool[*pc++]);+            BREAK;+        CASE(OP_fclosure8):+            *sp++ = js_closure(ctx, JS_DupValue(ctx, b->cpool[*pc++]), var_refs, sf);+            if (unlikely(JS_IsException(sp[-1])))+                goto exception;+            BREAK;+        CASE(OP_push_empty_string):+            *sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);+            BREAK;+        CASE(OP_get_length):+            {+                JSValue val;++                val = JS_GetProperty(ctx, sp[-1], JS_ATOM_length);+                if (unlikely(JS_IsException(val)))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = val;+            }+            BREAK;+#endif+        CASE(OP_push_atom_value):+            *sp++ = JS_AtomToValue(ctx, get_u32(pc));+            pc += 4;+            BREAK;+        CASE(OP_undefined):+            *sp++ = JS_UNDEFINED;+            BREAK;+        CASE(OP_null):+            *sp++ = JS_NULL;+            BREAK;+        CASE(OP_push_this):+            /* OP_push_this is only called at the start of a function */+            {+                JSValue val;+                if (!(b->js_mode & JS_MODE_STRICT)) {+                    uint32_t tag = JS_VALUE_GET_TAG(this_obj);+                    if (likely(tag == JS_TAG_OBJECT))+                        goto normal_this;+                    if (tag == JS_TAG_NULL || tag == JS_TAG_UNDEFINED) {+                        val = JS_DupValue(ctx, ctx->global_obj);+                    } else {+                        val = JS_ToObject(ctx, this_obj);+                        if (JS_IsException(val))+                            goto exception;+                    }+                } else {+                normal_this:+                    val = JS_DupValue(ctx, this_obj);+                }+                *sp++ = val;+            }+            BREAK;+        CASE(OP_push_false):+            *sp++ = JS_FALSE;+            BREAK;+        CASE(OP_push_true):+            *sp++ = JS_TRUE;+            BREAK;+        CASE(OP_object):+            *sp++ = JS_NewObject(ctx);+            if (unlikely(JS_IsException(sp[-1])))+                goto exception;+            BREAK;+        CASE(OP_special_object):+            {+                int arg = *pc++;+                switch(arg) {+                case OP_SPECIAL_OBJECT_ARGUMENTS:+                    *sp++ = js_build_arguments(ctx, argc, (JSValueConst *)argv);+                    if (unlikely(JS_IsException(sp[-1])))+                        goto exception;+                    break;+                case OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS:+                    *sp++ = js_build_mapped_arguments(ctx, argc, (JSValueConst *)argv,+                                                      sf, min_int(argc, b->arg_count));+                    if (unlikely(JS_IsException(sp[-1])))+                        goto exception;+                    break;+                case OP_SPECIAL_OBJECT_THIS_FUNC:+                    *sp++ = JS_DupValue(ctx, sf->cur_func);+                    break;+                case OP_SPECIAL_OBJECT_NEW_TARGET:+                    *sp++ = JS_DupValue(ctx, new_target);+                    break;+                case OP_SPECIAL_OBJECT_HOME_OBJECT:+                    {+                        JSObject *p1;+                        p1 = p->u.func.home_object;+                        if (unlikely(!p1))+                            *sp++ = JS_UNDEFINED;+                        else+                            *sp++ = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1));+                    }+                    break;+                case OP_SPECIAL_OBJECT_VAR_OBJECT:+                    *sp++ = JS_NewObjectProto(ctx, JS_NULL);+                    if (unlikely(JS_IsException(sp[-1])))+                        goto exception;+                    break;+                case OP_SPECIAL_OBJECT_IMPORT_META:+                    *sp++ = js_import_meta(ctx);+                    if (unlikely(JS_IsException(sp[-1])))+                        goto exception;+                    break;+                default:+                    abort();+                }+            }+            BREAK;+        CASE(OP_rest):+            {+                int first = get_u16(pc);+                pc += 2;+                *sp++ = js_build_rest(ctx, first, argc, (JSValueConst *)argv);+                if (unlikely(JS_IsException(sp[-1])))+                    goto exception;+            }+            BREAK;++        CASE(OP_drop):+            JS_FreeValue(ctx, sp[-1]);+            sp--;+            BREAK;+        CASE(OP_nip):+            JS_FreeValue(ctx, sp[-2]);+            sp[-2] = sp[-1];+            sp--;+            BREAK;+        CASE(OP_nip1): /* a b c -> b c */+            JS_FreeValue(ctx, sp[-3]);+            sp[-3] = sp[-2];+            sp[-2] = sp[-1];+            sp--;+            BREAK;+        CASE(OP_dup):+            sp[0] = JS_DupValue(ctx, sp[-1]);+            sp++;+            BREAK;+        CASE(OP_dup2): /* a b -> a b a b */+            sp[0] = JS_DupValue(ctx, sp[-2]);+            sp[1] = JS_DupValue(ctx, sp[-1]);+            sp += 2;+            BREAK;+        CASE(OP_dup3): /* a b c -> a b c a b c */+            sp[0] = JS_DupValue(ctx, sp[-3]);+            sp[1] = JS_DupValue(ctx, sp[-2]);+            sp[2] = JS_DupValue(ctx, sp[-1]);+            sp += 3;+            BREAK;+        CASE(OP_dup1): /* a b -> a a b */+            sp[0] = sp[-1];+            sp[-1] = JS_DupValue(ctx, sp[-2]);+            sp++;+            BREAK;+        CASE(OP_insert2): /* obj a -> a obj a (dup_x1) */+            sp[0] = sp[-1];+            sp[-1] = sp[-2];+            sp[-2] = JS_DupValue(ctx, sp[0]);+            sp++;+            BREAK;+        CASE(OP_insert3): /* obj prop a -> a obj prop a (dup_x2) */+            sp[0] = sp[-1];+            sp[-1] = sp[-2];+            sp[-2] = sp[-3];+            sp[-3] = JS_DupValue(ctx, sp[0]);+            sp++;+            BREAK;+        CASE(OP_insert4): /* this obj prop a -> a this obj prop a */+            sp[0] = sp[-1];+            sp[-1] = sp[-2];+            sp[-2] = sp[-3];+            sp[-3] = sp[-4];+            sp[-4] = JS_DupValue(ctx, sp[0]);+            sp++;+            BREAK;+        CASE(OP_perm3): /* obj a b -> a obj b (213) */+            {+                JSValue tmp;+                tmp = sp[-2];+                sp[-2] = sp[-3];+                sp[-3] = tmp;+            }+            BREAK;+        CASE(OP_rot3l): /* x a b -> a b x (231) */+            {+                JSValue tmp;+                tmp = sp[-3];+                sp[-3] = sp[-2];+                sp[-2] = sp[-1];+                sp[-1] = tmp;+            }+            BREAK;+        CASE(OP_rot4l): /* x a b c -> a b c x */+            {+                JSValue tmp;+                tmp = sp[-4];+                sp[-4] = sp[-3];+                sp[-3] = sp[-2];+                sp[-2] = sp[-1];+                sp[-1] = tmp;+            }+            BREAK;+        CASE(OP_rot5l): /* x a b c d -> a b c d x */+            {+                JSValue tmp;+                tmp = sp[-5];+                sp[-5] = sp[-4];+                sp[-4] = sp[-3];+                sp[-3] = sp[-2];+                sp[-2] = sp[-1];+                sp[-1] = tmp;+            }+            BREAK;+        CASE(OP_rot3r): /* a b x -> x a b (312) */+            {+                JSValue tmp;+                tmp = sp[-1];+                sp[-1] = sp[-2];+                sp[-2] = sp[-3];+                sp[-3] = tmp;+            }+            BREAK;+        CASE(OP_perm4): /* obj prop a b -> a obj prop b */+            {+                JSValue tmp;+                tmp = sp[-2];+                sp[-2] = sp[-3];+                sp[-3] = sp[-4];+                sp[-4] = tmp;+            }+            BREAK;+        CASE(OP_perm5): /* this obj prop a b -> a this obj prop b */+            {+                JSValue tmp;+                tmp = sp[-2];+                sp[-2] = sp[-3];+                sp[-3] = sp[-4];+                sp[-4] = sp[-5];+                sp[-5] = tmp;+            }+            BREAK;+        CASE(OP_swap): /* a b -> b a */+            {+                JSValue tmp;+                tmp = sp[-2];+                sp[-2] = sp[-1];+                sp[-1] = tmp;+            }+            BREAK;+        CASE(OP_swap2): /* a b c d -> c d a b */+            {+                JSValue tmp1, tmp2;+                tmp1 = sp[-4];+                tmp2 = sp[-3];+                sp[-4] = sp[-2];+                sp[-3] = sp[-1];+                sp[-2] = tmp1;+                sp[-1] = tmp2;+            }+            BREAK;++        CASE(OP_fclosure):+            {+                JSValue bfunc = JS_DupValue(ctx, b->cpool[get_u32(pc)]);+                pc += 4;+                *sp++ = js_closure(ctx, bfunc, var_refs, sf);+                if (unlikely(JS_IsException(sp[-1])))+                    goto exception;+            }+            BREAK;+#if SHORT_OPCODES+        CASE(OP_call0):+        CASE(OP_call1):+        CASE(OP_call2):+        CASE(OP_call3):+            call_argc = opcode - OP_call0;+            goto has_call_argc;+#endif+        CASE(OP_call):+        CASE(OP_tail_call):+            {+                call_argc = get_u16(pc);+                pc += 2;+                goto has_call_argc;+            has_call_argc:+                call_argv = sp - call_argc;+                sf->cur_pc = pc;+                ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED,+                                          JS_UNDEFINED, call_argc, call_argv, 0);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                if (opcode == OP_tail_call)+                    goto done;+                for(i = -1; i < call_argc; i++)+                    JS_FreeValue(ctx, call_argv[i]);+                sp -= call_argc + 1;+                *sp++ = ret_val;+            }+            BREAK;+        CASE(OP_call_constructor):+            {+                call_argc = get_u16(pc);+                pc += 2;+                call_argv = sp - call_argc;+                sf->cur_pc = pc;+                ret_val = JS_CallConstructorInternal(ctx, call_argv[-2],+                                                     call_argv[-1],+                                                     call_argc, call_argv, 0);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                for(i = -2; i < call_argc; i++)+                    JS_FreeValue(ctx, call_argv[i]);+                sp -= call_argc + 2;+                *sp++ = ret_val;+            }+            BREAK;+        CASE(OP_call_method):+        CASE(OP_tail_call_method):+            {+                call_argc = get_u16(pc);+                pc += 2;+                call_argv = sp - call_argc;+                sf->cur_pc = pc;+                ret_val = JS_CallInternal(ctx, call_argv[-1], call_argv[-2],+                                          JS_UNDEFINED, call_argc, call_argv, 0);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                if (opcode == OP_tail_call_method)+                    goto done;+                for(i = -2; i < call_argc; i++)+                    JS_FreeValue(ctx, call_argv[i]);+                sp -= call_argc + 2;+                *sp++ = ret_val;+            }+            BREAK;+        CASE(OP_array_from):+            {+                int i, ret;++                call_argc = get_u16(pc);+                pc += 2;+                ret_val = JS_NewArray(ctx);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                call_argv = sp - call_argc;+                for(i = 0; i < call_argc; i++) {+                    ret = JS_DefinePropertyValue(ctx, ret_val, __JS_AtomFromUInt32(i), call_argv[i],+                                                 JS_PROP_C_W_E | JS_PROP_THROW);+                    call_argv[i] = JS_UNDEFINED;+                    if (ret < 0) {+                        JS_FreeValue(ctx, ret_val);+                        goto exception;+                    }+                }+                sp -= call_argc;+                *sp++ = ret_val;+            }+            BREAK;++        CASE(OP_apply):+            {+                int magic;+                magic = get_u16(pc);+                pc += 2;++                ret_val = js_function_apply(ctx, sp[-3], 2, (JSValueConst *)&sp[-2], magic);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                JS_FreeValue(ctx, sp[-3]);+                JS_FreeValue(ctx, sp[-2]);+                JS_FreeValue(ctx, sp[-1]);+                sp -= 3;+                *sp++ = ret_val;+            }+            BREAK;+        CASE(OP_return):+            ret_val = *--sp;+            goto done;+        CASE(OP_return_undef):+            ret_val = JS_UNDEFINED;+            goto done;++        CASE(OP_check_ctor_return):+            /* return TRUE if 'this' should be returned */+            if (!JS_IsObject(sp[-1])) {+                if (!JS_IsUndefined(sp[-1])) {+                    JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined");+                    goto exception;+                }+                sp[0] = JS_TRUE;+            } else {+                sp[0] = JS_FALSE;+            }+            sp++;+            BREAK;+        CASE(OP_check_ctor):+            if (JS_IsUndefined(new_target)) {+                JS_ThrowTypeError(caller_ctx, "class constructors must be invoked with 'new'");+                goto exception;+            }+            BREAK;+        CASE(OP_check_brand):+            if (JS_CheckBrand(ctx, sp[-2], sp[-1]) < 0)+                goto exception;+            BREAK;+        CASE(OP_add_brand):+            if (JS_AddBrand(ctx, sp[-2], sp[-1]) < 0)+                goto exception;+            JS_FreeValue(ctx, sp[-2]);+            JS_FreeValue(ctx, sp[-1]);+            sp -= 2;+            BREAK;+            +        CASE(OP_throw):+            JS_Throw(ctx, *--sp);+            goto exception;++        CASE(OP_throw_error):+#define JS_THROW_VAR_RO             0+#define JS_THROW_VAR_REDECL         1+#define JS_THROW_VAR_UNINITIALIZED  2+#define JS_THROW_ERROR_DELETE_SUPER   3+#define JS_THROW_ERROR_ITERATOR_THROW 4+            {+                JSAtom atom;+                int type;+                atom = get_u32(pc);+                type = pc[4];+                pc += 5;+                if (type == JS_THROW_VAR_RO)+                    JS_ThrowTypeErrorReadOnly(ctx, JS_PROP_THROW, atom);+                else+                if (type == JS_THROW_VAR_REDECL)+                    JS_ThrowSyntaxErrorVarRedeclaration(ctx, atom);+                else+                if (type == JS_THROW_VAR_UNINITIALIZED)+                    JS_ThrowReferenceErrorUninitialized(ctx, atom);+                else+                if (type == JS_THROW_ERROR_DELETE_SUPER)+                    JS_ThrowReferenceError(ctx, "unsupported reference to 'super'");+                else+                if (type == JS_THROW_ERROR_ITERATOR_THROW)+                    JS_ThrowTypeError(ctx, "iterator does not have a throw method");+                else+                    JS_ThrowInternalError(ctx, "invalid throw var type %d", type);+            }+            goto exception;++        CASE(OP_eval):+            {+                JSValueConst obj;+                int scope_idx;+                call_argc = get_u16(pc);+                scope_idx = get_u16(pc + 2) - 1;+                pc += 4;+                call_argv = sp - call_argc;+                sf->cur_pc = pc;+                if (js_same_value(ctx, call_argv[-1], ctx->eval_obj)) {+                    if (call_argc >= 1)+                        obj = call_argv[0];+                    else+                        obj = JS_UNDEFINED;+                    ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj,+                                            JS_EVAL_TYPE_DIRECT, scope_idx);+                } else {+                    ret_val = JS_CallInternal(ctx, call_argv[-1], JS_UNDEFINED,+                                              JS_UNDEFINED, call_argc, call_argv, 0);+                }+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                for(i = -1; i < call_argc; i++)+                    JS_FreeValue(ctx, call_argv[i]);+                sp -= call_argc + 1;+                *sp++ = ret_val;+            }+            BREAK;+            /* could merge with OP_apply */+        CASE(OP_apply_eval):+            {+                int scope_idx;+                uint32_t len;+                JSValue *tab;+                JSValueConst obj;++                scope_idx = get_u16(pc) - 1;+                pc += 2;+                tab = build_arg_list(ctx, &len, sp[-1]);+                if (!tab)+                    goto exception;+                if (js_same_value(ctx, sp[-2], ctx->eval_obj)) {+                    if (len >= 1)+                        obj = tab[0];+                    else+                        obj = JS_UNDEFINED;+                    ret_val = JS_EvalObject(ctx, JS_UNDEFINED, obj,+                                            JS_EVAL_TYPE_DIRECT, scope_idx);+                } else {+                    ret_val = JS_Call(ctx, sp[-2], JS_UNDEFINED, len,+                                      (JSValueConst *)tab);+                }+                free_arg_list(ctx, tab, len);+                if (unlikely(JS_IsException(ret_val)))+                    goto exception;+                JS_FreeValue(ctx, sp[-2]);+                JS_FreeValue(ctx, sp[-1]);+                sp -= 2;+                *sp++ = ret_val;+            }+            BREAK;++        CASE(OP_regexp):+            {+                sp[-2] = js_regexp_constructor_internal(ctx, JS_UNDEFINED,+                                                        sp[-2], sp[-1]);+                sp--;+            }+            BREAK;++        CASE(OP_get_super):+            {+                JSValue proto;+                proto = JS_GetPrototype(ctx, sp[-1]);+                if (JS_IsException(proto))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = proto;+            }+            BREAK;++        CASE(OP_import):+            {+                JSValue val;+                val = js_dynamic_import(ctx, sp[-1]);+                if (JS_IsException(val))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = val;+            }+            BREAK;++        CASE(OP_check_var):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                ret = JS_CheckGlobalVar(ctx, atom);+                if (ret < 0)+                    goto exception;+                *sp++ = JS_NewBool(ctx, ret);+            }+            BREAK;++        CASE(OP_get_var_undef):+        CASE(OP_get_var):+            {+                JSValue val;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                val = JS_GetGlobalVar(ctx, atom, opcode - OP_get_var_undef);+                if (unlikely(JS_IsException(val)))+                    goto exception;+                *sp++ = val;+            }+            BREAK;++        CASE(OP_put_var):+        CASE(OP_put_var_init):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                ret = JS_SetGlobalVar(ctx, atom, sp[-1], opcode - OP_put_var);+                sp--;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_put_var_strict):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                /* sp[-2] is JS_TRUE or JS_FALSE */+                if (unlikely(!JS_VALUE_GET_INT(sp[-2]))) {+                    JS_ThrowReferenceErrorNotDefined(ctx, atom);+                    goto exception;+                }+                ret = JS_SetGlobalVar(ctx, atom, sp[-1], 2);+                sp -= 2;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_check_define_var):+            {+                JSAtom atom;+                int flags;+                atom = get_u32(pc);+                flags = pc[4];+                pc += 5;+                if (JS_CheckDefineGlobalVar(ctx, atom, flags))+                    goto exception;+            }+            BREAK;+        CASE(OP_define_var):+            {+                JSAtom atom;+                int flags;+                atom = get_u32(pc);+                flags = pc[4];+                pc += 5;+                if (JS_DefineGlobalVar(ctx, atom, flags))+                    goto exception;+            }+            BREAK;+        CASE(OP_define_func):+            {+                JSAtom atom;+                int flags;+                atom = get_u32(pc);+                flags = pc[4];+                pc += 5;+                if (JS_DefineGlobalFunction(ctx, atom, sp[-1], flags))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp--;+            }+            BREAK;++        CASE(OP_get_loc):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                sp[0] = JS_DupValue(ctx, var_buf[idx]);+                sp++;+            }+            BREAK;+        CASE(OP_put_loc):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, &var_buf[idx], sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_set_loc):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, &var_buf[idx], JS_DupValue(ctx, sp[-1]));+            }+            BREAK;+        CASE(OP_get_arg):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                sp[0] = JS_DupValue(ctx, arg_buf[idx]);+                sp++;+            }+            BREAK;+        CASE(OP_put_arg):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, &arg_buf[idx], sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_set_arg):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, &arg_buf[idx], JS_DupValue(ctx, sp[-1]));+            }+            BREAK;++#if SHORT_OPCODES+        CASE(OP_get_loc8): *sp++ = JS_DupValue(ctx, var_buf[*pc++]); BREAK;+        CASE(OP_put_loc8): set_value(ctx, &var_buf[*pc++], *--sp); BREAK;+        CASE(OP_set_loc8): set_value(ctx, &var_buf[*pc++], JS_DupValue(ctx, sp[-1])); BREAK;++        CASE(OP_get_loc0): *sp++ = JS_DupValue(ctx, var_buf[0]); BREAK;+        CASE(OP_get_loc1): *sp++ = JS_DupValue(ctx, var_buf[1]); BREAK;+        CASE(OP_get_loc2): *sp++ = JS_DupValue(ctx, var_buf[2]); BREAK;+        CASE(OP_get_loc3): *sp++ = JS_DupValue(ctx, var_buf[3]); BREAK;+        CASE(OP_put_loc0): set_value(ctx, &var_buf[0], *--sp); BREAK;+        CASE(OP_put_loc1): set_value(ctx, &var_buf[1], *--sp); BREAK;+        CASE(OP_put_loc2): set_value(ctx, &var_buf[2], *--sp); BREAK;+        CASE(OP_put_loc3): set_value(ctx, &var_buf[3], *--sp); BREAK;+        CASE(OP_set_loc0): set_value(ctx, &var_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_loc1): set_value(ctx, &var_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_loc2): set_value(ctx, &var_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_loc3): set_value(ctx, &var_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_get_arg0): *sp++ = JS_DupValue(ctx, arg_buf[0]); BREAK;+        CASE(OP_get_arg1): *sp++ = JS_DupValue(ctx, arg_buf[1]); BREAK;+        CASE(OP_get_arg2): *sp++ = JS_DupValue(ctx, arg_buf[2]); BREAK;+        CASE(OP_get_arg3): *sp++ = JS_DupValue(ctx, arg_buf[3]); BREAK;+        CASE(OP_put_arg0): set_value(ctx, &arg_buf[0], *--sp); BREAK;+        CASE(OP_put_arg1): set_value(ctx, &arg_buf[1], *--sp); BREAK;+        CASE(OP_put_arg2): set_value(ctx, &arg_buf[2], *--sp); BREAK;+        CASE(OP_put_arg3): set_value(ctx, &arg_buf[3], *--sp); BREAK;+        CASE(OP_set_arg0): set_value(ctx, &arg_buf[0], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_arg1): set_value(ctx, &arg_buf[1], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_arg2): set_value(ctx, &arg_buf[2], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_arg3): set_value(ctx, &arg_buf[3], JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_get_var_ref0): *sp++ = JS_DupValue(ctx, *var_refs[0]->pvalue); BREAK;+        CASE(OP_get_var_ref1): *sp++ = JS_DupValue(ctx, *var_refs[1]->pvalue); BREAK;+        CASE(OP_get_var_ref2): *sp++ = JS_DupValue(ctx, *var_refs[2]->pvalue); BREAK;+        CASE(OP_get_var_ref3): *sp++ = JS_DupValue(ctx, *var_refs[3]->pvalue); BREAK;+        CASE(OP_put_var_ref0): set_value(ctx, var_refs[0]->pvalue, *--sp); BREAK;+        CASE(OP_put_var_ref1): set_value(ctx, var_refs[1]->pvalue, *--sp); BREAK;+        CASE(OP_put_var_ref2): set_value(ctx, var_refs[2]->pvalue, *--sp); BREAK;+        CASE(OP_put_var_ref3): set_value(ctx, var_refs[3]->pvalue, *--sp); BREAK;+        CASE(OP_set_var_ref0): set_value(ctx, var_refs[0]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_var_ref1): set_value(ctx, var_refs[1]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_var_ref2): set_value(ctx, var_refs[2]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;+        CASE(OP_set_var_ref3): set_value(ctx, var_refs[3]->pvalue, JS_DupValue(ctx, sp[-1])); BREAK;+#endif++        CASE(OP_get_var_ref):+            {+                int idx;+                JSValue val;+                idx = get_u16(pc);+                pc += 2;+                val = *var_refs[idx]->pvalue;+                sp[0] = JS_DupValue(ctx, val);+                sp++;+            }+            BREAK;+        CASE(OP_put_var_ref):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_set_var_ref):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, var_refs[idx]->pvalue, JS_DupValue(ctx, sp[-1]));+            }+            BREAK;+        CASE(OP_get_var_ref_check):+            {+                int idx;+                JSValue val;+                idx = get_u16(pc);+                pc += 2;+                val = *var_refs[idx]->pvalue;+                if (unlikely(JS_IsUninitialized(val))) {+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);+                    goto exception;+                }+                sp[0] = JS_DupValue(ctx, val);+                sp++;+            }+            BREAK;+        CASE(OP_put_var_ref_check):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                if (unlikely(JS_IsUninitialized(*var_refs[idx]->pvalue))) {+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);+                    goto exception;+                }+                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_put_var_ref_check_init):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                if (unlikely(!JS_IsUninitialized(*var_refs[idx]->pvalue))) {+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, TRUE);+                    goto exception;+                }+                set_value(ctx, var_refs[idx]->pvalue, sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_set_loc_uninitialized):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                set_value(ctx, &var_buf[idx], JS_UNINITIALIZED);+            }+            BREAK;+        CASE(OP_get_loc_check):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                if (unlikely(JS_IsUninitialized(var_buf[idx]))) {+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);+                    goto exception;+                }+                sp[0] = JS_DupValue(ctx, var_buf[idx]);+                sp++;+            }+            BREAK;+        CASE(OP_put_loc_check):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                if (unlikely(JS_IsUninitialized(var_buf[idx]))) {+                    JS_ThrowReferenceErrorUninitialized2(ctx, b, idx, FALSE);+                    goto exception;+                }+                set_value(ctx, &var_buf[idx], sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_put_loc_check_init):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                if (unlikely(!JS_IsUninitialized(var_buf[idx]))) {+                    JS_ThrowReferenceError(ctx, "'this' can be initialized only once");+                    goto exception;+                }+                set_value(ctx, &var_buf[idx], sp[-1]);+                sp--;+            }+            BREAK;+        CASE(OP_close_loc):+            {+                int idx;+                idx = get_u16(pc);+                pc += 2;+                close_lexical_var(ctx, sf, idx, FALSE);+            }+            BREAK;++        CASE(OP_make_loc_ref):+        CASE(OP_make_arg_ref):+        CASE(OP_make_var_ref_ref):+            {+                JSVarRef *var_ref;+                JSProperty *pr;+                JSAtom atom;+                int idx;+                atom = get_u32(pc);+                idx = get_u16(pc + 4);+                pc += 6;+                *sp++ = JS_NewObjectProto(ctx, JS_NULL);+                if (unlikely(JS_IsException(sp[-1])))+                    goto exception;+                if (opcode == OP_make_var_ref_ref) {+                    var_ref = var_refs[idx];+                    var_ref->header.ref_count++;+                } else {+                    var_ref = get_var_ref(ctx, sf, idx, opcode == OP_make_arg_ref);+                    if (!var_ref)+                        goto exception;+                }+                pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom,+                                  JS_PROP_WRITABLE | JS_PROP_VARREF);+                if (!pr) {+                    free_var_ref(rt, var_ref);+                    goto exception;+                }+                pr->u.var_ref = var_ref;+                *sp++ = JS_AtomToValue(ctx, atom);+            }+            BREAK;+        CASE(OP_make_var_ref):+            {+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                if (JS_GetGlobalVarRef(ctx, atom, sp))+                    goto exception;+                sp += 2;+            }+            BREAK;++        CASE(OP_goto):+            pc += (int32_t)get_u32(pc);+            if (unlikely(js_poll_interrupts(ctx)))+                goto exception;+            BREAK;+#if SHORT_OPCODES+        CASE(OP_goto16):+            pc += (int16_t)get_u16(pc);+            if (unlikely(js_poll_interrupts(ctx)))+                goto exception;+            BREAK;+        CASE(OP_goto8):+            pc += (int8_t)pc[0];+            if (unlikely(js_poll_interrupts(ctx)))+                goto exception;+            BREAK;+#endif+        CASE(OP_if_true):+            {+                int res;+                JSValue op1;++                op1 = sp[-1];+                pc += 4;+                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {+                    res = JS_VALUE_GET_INT(op1);+                } else {+                    res = JS_ToBoolFree(ctx, op1);+                }+                sp--;+                if (res) {+                    pc += (int32_t)get_u32(pc - 4) - 4;+                }+                if (unlikely(js_poll_interrupts(ctx)))+                    goto exception;+            }+            BREAK;+        CASE(OP_if_false):+            {+                int res;+                JSValue op1;++                op1 = sp[-1];+                pc += 4;+                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {+                    res = JS_VALUE_GET_INT(op1);+                } else {+                    res = JS_ToBoolFree(ctx, op1);+                }+                sp--;+                if (!res) {+                    pc += (int32_t)get_u32(pc - 4) - 4;+                }+                if (unlikely(js_poll_interrupts(ctx)))+                    goto exception;+            }+            BREAK;+#if SHORT_OPCODES+        CASE(OP_if_true8):+            {+                int res;+                JSValue op1;++                op1 = sp[-1];+                pc += 1;+                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {+                    res = JS_VALUE_GET_INT(op1);+                } else {+                    res = JS_ToBoolFree(ctx, op1);+                }+                sp--;+                if (res) {+                    pc += (int8_t)pc[-1] - 1;+                }+                if (unlikely(js_poll_interrupts(ctx)))+                    goto exception;+            }+            BREAK;+        CASE(OP_if_false8):+            {+                int res;+                JSValue op1;++                op1 = sp[-1];+                pc += 1;+                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {+                    res = JS_VALUE_GET_INT(op1);+                } else {+                    res = JS_ToBoolFree(ctx, op1);+                }+                sp--;+                if (!res) {+                    pc += (int8_t)pc[-1] - 1;+                }+                if (unlikely(js_poll_interrupts(ctx)))+                    goto exception;+            }+            BREAK;+#endif+        CASE(OP_catch):+            {+                int32_t diff;+                diff = get_u32(pc);+                sp[0] = JS_NewCatchOffset(ctx, pc + diff - b->byte_code_buf);+                sp++;+                pc += 4;+            }+            BREAK;+        CASE(OP_gosub):+            {+                int32_t diff;+                diff = get_u32(pc);+                /* XXX: should have a different tag to avoid security flaw */+                sp[0] = JS_NewInt32(ctx, pc + 4 - b->byte_code_buf);+                sp++;+                pc += diff;+            }+            BREAK;+        CASE(OP_ret):+            {+                JSValue op1;+                uint32_t pos;+                op1 = sp[-1];+                if (unlikely(JS_VALUE_GET_TAG(op1) != JS_TAG_INT))+                    goto ret_fail;+                pos = JS_VALUE_GET_INT(op1);+                if (unlikely(pos >= b->byte_code_len)) {+                ret_fail:+                    JS_ThrowInternalError(ctx, "invalid ret value");+                    goto exception;+                }+                sp--;+                pc = b->byte_code_buf + pos;+            }+            BREAK;++        CASE(OP_for_in_start):+            if (js_for_in_start(ctx, sp))+                goto exception;+            BREAK;+        CASE(OP_for_in_next):+            if (js_for_in_next(ctx, sp))+                goto exception;+            sp += 2;+            BREAK;+        CASE(OP_for_of_start):+            if (js_for_of_start(ctx, sp, FALSE))+                goto exception;+            sp += 1;+            *sp++ = JS_NewCatchOffset(ctx, 0);+            BREAK;+        CASE(OP_for_of_next):+            {+                int offset = -3 - pc[0];+                pc += 1;+                if (js_for_of_next(ctx, sp, offset))+                    goto exception;+                sp += 2;+            }+            BREAK;+        CASE(OP_for_await_of_start):+            if (js_for_of_start(ctx, sp, TRUE))+                goto exception;+            sp += 1;+            *sp++ = JS_NewCatchOffset(ctx, 0);+            BREAK;+        CASE(OP_iterator_get_value_done):+            if (js_iterator_get_value_done(ctx, sp))+                goto exception;+            sp += 1;+            BREAK;+        CASE(OP_iterator_check_object):+            if (unlikely(!JS_IsObject(sp[-1]))) {+                JS_ThrowTypeError(ctx, "iterator must return an object");+                goto exception;+            }+            BREAK;++        CASE(OP_iterator_close):+            /* iter_obj next catch_offset -> */+            sp--; /* drop the catch offset to avoid getting caught by exception */+            JS_FreeValue(ctx, sp[-1]); /* drop the next method */+            sp--;+            if (!JS_IsUndefined(sp[-1])) {+                if (JS_IteratorClose(ctx, sp[-1], FALSE))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+            }+            sp--;+            BREAK;+        CASE(OP_iterator_close_return):+            {+                JSValue ret_val;+                /* iter_obj next catch_offset ... ret_val ->+                   ret_eval iter_obj next catch_offset */+                ret_val = *--sp;+                while (sp > stack_buf &&+                       JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_CATCH_OFFSET) {+                    JS_FreeValue(ctx, *--sp);+                }+                if (unlikely(sp < stack_buf + 3)) {+                    JS_ThrowInternalError(ctx, "iterator_close_return");+                    JS_FreeValue(ctx, ret_val);+                    goto exception;+                }+                sp[0] = sp[-1];+                sp[-1] = sp[-2];+                sp[-2] = sp[-3];+                sp[-3] = ret_val;+                sp++;+            }+            BREAK;++        CASE(OP_iterator_next):+            /* stack: iter_obj next catch_offset val */+            {+                JSValue ret;+                ret = JS_Call(ctx, sp[-3], sp[-4],+                              1, (JSValueConst *)(sp - 1));+                if (JS_IsException(ret))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = ret;+            }+            BREAK;++        CASE(OP_iterator_call):+            /* stack: iter_obj next catch_offset val */+            {+                JSValue method, ret;+                BOOL ret_flag;+                int flags;+                flags = *pc++;+                method = JS_GetProperty(ctx, sp[-4], (flags & 1) ?+                                        JS_ATOM_throw : JS_ATOM_return);+                if (JS_IsException(method))+                    goto exception;+                if (JS_IsUndefined(method) || JS_IsNull(method)) {+                    ret_flag = TRUE;+                } else {+                    if (flags & 2) {+                        /* no argument */+                        ret = JS_CallFree(ctx, method, sp[-4],+                                          0, NULL);+                    } else {+                        ret = JS_CallFree(ctx, method, sp[-4],+                                          1, (JSValueConst *)(sp - 1));+                    }+                    if (JS_IsException(ret))+                        goto exception;+                    JS_FreeValue(ctx, sp[-1]);+                    sp[-1] = ret;+                    ret_flag = FALSE;+                }+                sp[0] = JS_NewBool(ctx, ret_flag);+                sp += 1;+            }+            BREAK;++        CASE(OP_lnot):+            {+                int res;+                JSValue op1;++                op1 = sp[-1];+                if ((uint32_t)JS_VALUE_GET_TAG(op1) <= JS_TAG_UNDEFINED) {+                    res = JS_VALUE_GET_INT(op1) != 0;+                } else {+                    res = JS_ToBoolFree(ctx, op1);+                }+                sp[-1] = JS_NewBool(ctx, !res);+            }+            BREAK;++        CASE(OP_get_field):+            {+                JSValue val;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                val = JS_GetProperty(ctx, sp[-1], atom);+                if (unlikely(JS_IsException(val)))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = val;+            }+            BREAK;++        CASE(OP_get_field2):+            {+                JSValue val;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                val = JS_GetProperty(ctx, sp[-1], atom);+                if (unlikely(JS_IsException(val)))+                    goto exception;+                *sp++ = val;+            }+            BREAK;++        CASE(OP_put_field):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                ret = JS_SetPropertyInternal(ctx, sp[-2], atom, sp[-1],+                                             JS_PROP_THROW_STRICT);+                JS_FreeValue(ctx, sp[-2]);+                sp -= 2;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_private_symbol):+            {+                JSAtom atom;+                JSValue val;+                +                atom = get_u32(pc);+                pc += 4;+                val = JS_NewSymbolFromAtom(ctx, atom, JS_ATOM_TYPE_PRIVATE);+                if (JS_IsException(val))+                    goto exception;+                *sp++ = val;+            }+            BREAK;+            +        CASE(OP_get_private_field):+            {+                JSValue val;++                val = JS_GetPrivateField(ctx, sp[-2], sp[-1]);+                JS_FreeValue(ctx, sp[-1]);+                JS_FreeValue(ctx, sp[-2]);+                sp[-2] = val;+                sp--;+                if (unlikely(JS_IsException(val)))+                    goto exception;+            }+            BREAK;++        CASE(OP_put_private_field):+            {+                int ret;+                ret = JS_SetPrivateField(ctx, sp[-3], sp[-1], sp[-2]);+                JS_FreeValue(ctx, sp[-3]);+                JS_FreeValue(ctx, sp[-1]);+                sp -= 3;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_define_private_field):+            {+                int ret;+                ret = JS_DefinePrivateField(ctx, sp[-3], sp[-2], sp[-1]);+                JS_FreeValue(ctx, sp[-2]);+                sp -= 2;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_define_field):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                ret = JS_DefinePropertyValue(ctx, sp[-2], atom, sp[-1],+                                             JS_PROP_C_W_E | JS_PROP_THROW);+                sp--;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_set_name):+            {+                int ret;+                JSAtom atom;+                atom = get_u32(pc);+                pc += 4;++                ret = JS_DefineObjectName(ctx, sp[-1], atom, JS_PROP_CONFIGURABLE);+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;+        CASE(OP_set_name_computed):+            {+                int ret;+                ret = JS_DefineObjectNameComputed(ctx, sp[-1], sp[-2], JS_PROP_CONFIGURABLE);+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;+        CASE(OP_set_proto):+            {+                JSValue proto;+                proto = sp[-1];+                if (JS_IsObject(proto) || JS_IsNull(proto)) {+                    if (JS_SetPrototypeInternal(ctx, sp[-2], proto, TRUE) < 0)+                        goto exception;+                }+                JS_FreeValue(ctx, proto);+                sp--;+            }+            BREAK;+        CASE(OP_set_home_object):+            js_method_set_home_object(ctx, sp[-1], sp[-2]);+            BREAK;+        CASE(OP_define_method):+        CASE(OP_define_method_computed):+            {+                JSValue getter, setter, value;+                JSValueConst obj;+                JSAtom atom;+                int flags, ret, op_flags;+                BOOL is_computed;+#define OP_DEFINE_METHOD_METHOD 0+#define OP_DEFINE_METHOD_GETTER 1+#define OP_DEFINE_METHOD_SETTER 2+#define OP_DEFINE_METHOD_ENUMERABLE 4++                is_computed = (opcode == OP_define_method_computed);+                if (is_computed) {+                    atom = JS_ValueToAtom(ctx, sp[-2]);+                    if (unlikely(atom == JS_ATOM_NULL))+                        goto exception;+                    opcode += OP_define_method - OP_define_method_computed;+                } else {+                    atom = get_u32(pc);+                    pc += 4;+                }+                op_flags = *pc++;++                obj = sp[-2 - is_computed];+                flags = JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE |+                    JS_PROP_HAS_ENUMERABLE | JS_PROP_THROW;+                if (op_flags & OP_DEFINE_METHOD_ENUMERABLE)+                    flags |= JS_PROP_ENUMERABLE;+                op_flags &= 3;+                value = JS_UNDEFINED;+                getter = JS_UNDEFINED;+                setter = JS_UNDEFINED;+                if (op_flags == OP_DEFINE_METHOD_METHOD) {+                    value = sp[-1];+                    flags |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE;+                } else if (op_flags == OP_DEFINE_METHOD_GETTER) {+                    getter = sp[-1];+                    flags |= JS_PROP_HAS_GET;+                } else {+                    setter = sp[-1];+                    flags |= JS_PROP_HAS_SET;+                }+                ret = js_method_set_properties(ctx, sp[-1], atom, flags, obj);+                if (ret >= 0) {+                    ret = JS_DefineProperty(ctx, obj, atom, value,+                                            getter, setter, flags);+                }+                JS_FreeValue(ctx, sp[-1]);+                if (is_computed) {+                    JS_FreeAtom(ctx, atom);+                    JS_FreeValue(ctx, sp[-2]);+                }+                sp -= 1 + is_computed;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_define_class):+        CASE(OP_define_class_computed):+            {+                int class_flags;+                JSAtom atom;+                +                atom = get_u32(pc);+                class_flags = pc[4];+                pc += 5;+                if (js_op_define_class(ctx, sp, atom, class_flags,+                                       var_refs, sf,+                                       (opcode == OP_define_class_computed)) < 0)+                    goto exception;+            }+            BREAK;++        CASE(OP_get_array_el):+            {+                JSValue val;++                val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);+                JS_FreeValue(ctx, sp[-2]);+                sp[-2] = val;+                sp--;+                if (unlikely(JS_IsException(val)))+                    goto exception;+            }+            BREAK;++        CASE(OP_get_array_el2):+            {+                JSValue val;++                val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]);+                sp[-1] = val;+                if (unlikely(JS_IsException(val)))+                    goto exception;+            }+            BREAK;++        CASE(OP_get_ref_value):+            {+                JSValue val;+                if (unlikely(JS_IsUndefined(sp[-2]))) {+                    JSAtom atom = JS_ValueToAtom(ctx, sp[-1]);+                    if (atom != JS_ATOM_NULL) {+                        JS_ThrowReferenceErrorNotDefined(ctx, atom);+                        JS_FreeAtom(ctx, atom);+                    }+                    goto exception;+                }+                val = JS_GetPropertyValue(ctx, sp[-2],+                                          JS_DupValue(ctx, sp[-1]));+                if (unlikely(JS_IsException(val)))+                    goto exception;+                sp[0] = val;+                sp++;+            }+            BREAK;++        CASE(OP_get_super_value):+            {+                JSValue val;+                JSAtom atom;+                atom = JS_ValueToAtom(ctx, sp[-1]);+                if (unlikely(atom == JS_ATOM_NULL))+                    goto exception;+                val = JS_GetPropertyInternal(ctx, sp[-2], atom, sp[-3], FALSE);+                JS_FreeAtom(ctx, atom);+                if (unlikely(JS_IsException(val)))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                JS_FreeValue(ctx, sp[-2]);+                JS_FreeValue(ctx, sp[-3]);+                sp[-3] = val;+                sp -= 2;+            }+            BREAK;++        CASE(OP_put_array_el):+            {+                int ret;++                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], JS_PROP_THROW_STRICT);+                JS_FreeValue(ctx, sp[-3]);+                sp -= 3;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_put_ref_value):+            {+                int ret, flags;+                flags = JS_PROP_THROW_STRICT;+                if (unlikely(JS_IsUndefined(sp[-3]))) {+                    if (is_strict_mode(ctx)) {+                        JSAtom atom = JS_ValueToAtom(ctx, sp[-2]);+                        if (atom != JS_ATOM_NULL) {+                            JS_ThrowReferenceErrorNotDefined(ctx, atom);+                            JS_FreeAtom(ctx, atom);+                        }+                        goto exception;+                    } else {+                        sp[-3] = JS_DupValue(ctx, ctx->global_obj);+                    }+                } else {+                    if (is_strict_mode(ctx))+                        flags |= JS_PROP_NO_ADD;+                }+                ret = JS_SetPropertyValue(ctx, sp[-3], sp[-2], sp[-1], flags);+                JS_FreeValue(ctx, sp[-3]);+                sp -= 3;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_put_super_value):+            {+                int ret;+                JSAtom atom;+                if (JS_VALUE_GET_TAG(sp[-3]) != JS_TAG_OBJECT) {+                    JS_ThrowTypeErrorNotAnObject(ctx);+                    goto exception;+                }+                atom = JS_ValueToAtom(ctx, sp[-2]);+                if (unlikely(atom == JS_ATOM_NULL))+                    goto exception;+                ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(sp[-3]),+                                            atom, sp[-1], sp[-4],+                                            JS_PROP_THROW_STRICT);+                JS_FreeAtom(ctx, atom);+                JS_FreeValue(ctx, sp[-4]);+                JS_FreeValue(ctx, sp[-3]);+                JS_FreeValue(ctx, sp[-2]);+                sp -= 4;+                if (ret < 0)+                    goto exception;+            }+            BREAK;++        CASE(OP_define_array_el):+            {+                int ret;+                ret = JS_DefinePropertyValueValue(ctx, sp[-3], JS_DupValue(ctx, sp[-2]), sp[-1],+                                                  JS_PROP_C_W_E | JS_PROP_THROW);+                sp -= 1;+                if (unlikely(ret < 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_append):    /* array pos enumobj -- array pos */+            {+                if (js_append_enumerate(ctx, sp))+                    goto exception;+                JS_FreeValue(ctx, *--sp);+            }+            BREAK;++        CASE(OP_copy_data_properties):    /* target source excludeList */+            {+                /* stack offsets (-1 based):+                   2 bits for target,+                   3 bits for source,+                   2 bits for exclusionList */+                int mask;++                mask = *pc++;+                if (JS_CopyDataProperties(ctx, sp[-1 - (mask & 3)],+                                          sp[-1 - ((mask >> 2) & 7)],+                                          sp[-1 - ((mask >> 5) & 7)], 0))+                    goto exception;+            }+            BREAK;++        CASE(OP_add):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    int64_t r;+                    r = (int64_t)JS_VALUE_GET_INT(op1) + JS_VALUE_GET_INT(op2);+                    if (unlikely((int)r != r))+                        goto add_slow;+                    sp[-2] = JS_NewInt32(ctx, r);+                    sp--;+                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {+                    sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) ++                                             JS_VALUE_GET_FLOAT64(op2));+                    sp--;+                } else {+                add_slow:+                    if (js_add_slow(ctx, sp))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_add_loc):+            {+                JSValue *pv;+                int idx;+                idx = *pc;+                pc += 1;++                pv = &var_buf[idx];+                if (likely(JS_VALUE_IS_BOTH_INT(*pv, sp[-1]))) {+                    int64_t r;+                    r = (int64_t)JS_VALUE_GET_INT(*pv) ++                        JS_VALUE_GET_INT(sp[-1]);+                    if (unlikely((int)r != r))+                        goto add_loc_slow;+                    *pv = JS_NewInt32(ctx, r);+                    sp--;+                } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {+                    JSValue op1;+                    op1 = sp[-1];+                    sp--;+                    op1 = JS_ToPrimitiveFree(ctx, op1, HINT_NONE);+                    if (JS_IsException(op1))+                        goto exception;+                    op1 = JS_ConcatString(ctx, JS_DupValue(ctx, *pv), op1);+                    if (JS_IsException(op1))+                        goto exception;+                    set_value(ctx, pv, op1);+                } else {+                    JSValue ops[2];+                add_loc_slow:+                    /* In case of exception, js_add_slow frees ops[0]+                       and ops[1], so we must duplicate *pv */+                    ops[0] = JS_DupValue(ctx, *pv);+                    ops[1] = sp[-1];+                    sp--;+                    if (js_add_slow(ctx, ops + 2))+                        goto exception;+                    set_value(ctx, pv, ops[0]);+                }+            }+            BREAK;+        CASE(OP_sub):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    int64_t r;+                    r = (int64_t)JS_VALUE_GET_INT(op1) - JS_VALUE_GET_INT(op2);+                    if (unlikely((int)r != r))+                        goto binary_arith_slow;+                    sp[-2] = JS_NewInt32(ctx, r);+                    sp--;+                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {+                    sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) -+                                             JS_VALUE_GET_FLOAT64(op2));+                    sp--;+                } else {+                    goto binary_arith_slow;+                }+            }+            BREAK;+        CASE(OP_mul):+            {+                JSValue op1, op2;+                double d;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    int32_t v1, v2;+                    int64_t r;+                    v1 = JS_VALUE_GET_INT(op1);+                    v2 = JS_VALUE_GET_INT(op2);+                    r = (int64_t)v1 * v2;+                    if (unlikely((int)r != r)) {+#ifdef CONFIG_BIGNUM+                        if (unlikely(sf->js_mode & JS_MODE_MATH) &&+                            (r < -MAX_SAFE_INTEGER || r > MAX_SAFE_INTEGER))+                            goto binary_arith_slow;+#endif+                        d = (double)r;+                        goto mul_fp_res;+                    }+                    /* need to test zero case for -0 result */+                    if (unlikely(r == 0 && (v1 | v2) < 0)) {+                        d = -0.0;+                        goto mul_fp_res;+                    }+                    sp[-2] = JS_NewInt32(ctx, r);+                    sp--;+                } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) {+#ifdef CONFIG_BIGNUM+                    if (unlikely(sf->js_mode & JS_MODE_MATH))+                        goto binary_arith_slow;+#endif+                    d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2);+                mul_fp_res:+                    sp[-2] = __JS_NewFloat64(ctx, d);+                    sp--;+                } else {+                    goto binary_arith_slow;+                }+            }+            BREAK;+        CASE(OP_div):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    int v1, v2;+                    if (unlikely(sf->js_mode & JS_MODE_MATH))+                        goto binary_arith_slow;+                    v1 = JS_VALUE_GET_INT(op1);+                    v2 = JS_VALUE_GET_INT(op2);+                    sp[-2] = JS_NewFloat64(ctx, (double)v1 / (double)v2);+                    sp--;+                } else {+                    goto binary_arith_slow;+                }+            }+            BREAK;+        CASE(OP_mod):+#ifdef CONFIG_BIGNUM+        CASE(OP_math_mod):+#endif+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    int v1, v2, r;+                    v1 = JS_VALUE_GET_INT(op1);+                    v2 = JS_VALUE_GET_INT(op2);+                    /* We must avoid v2 = 0, v1 = INT32_MIN and v2 =+                       -1 and the cases where the result is -0. */+                    if (unlikely(v1 < 0 || v2 <= 0))+                        goto binary_arith_slow;+                    r = v1 % v2;+                    sp[-2] = JS_NewInt32(ctx, r);+                    sp--;+                } else {+                    goto binary_arith_slow;+                }+            }+            BREAK;+        CASE(OP_pow):+        binary_arith_slow:+            if (js_binary_arith_slow(ctx, sp, opcode))+                goto exception;+            sp--;+            BREAK;++        CASE(OP_plus):+            {+                JSValue op1;+                uint32_t tag;+                op1 = sp[-1];+                tag = JS_VALUE_GET_TAG(op1);+                if (tag == JS_TAG_INT || JS_TAG_IS_FLOAT64(tag)) {+                } else {+                    if (js_unary_arith_slow(ctx, sp, opcode))+                        goto exception;+                }+            }+            BREAK;+        CASE(OP_neg):+            {+                JSValue op1;+                uint32_t tag;+                int val;+                double d;+                op1 = sp[-1];+                tag = JS_VALUE_GET_TAG(op1);+                if (tag == JS_TAG_INT) {+                    val = JS_VALUE_GET_INT(op1);+                    /* Note: -0 cannot be expressed as integer */+                    if (unlikely(val == 0)) {+                        d = -0.0;+                        goto neg_fp_res;+                    }+                    if (unlikely(val == INT32_MIN)) {+                        d = -(double)val;+                        goto neg_fp_res;+                    }+                    sp[-1] = JS_NewInt32(ctx, -val);+                } else if (JS_TAG_IS_FLOAT64(tag)) {+                    d = -JS_VALUE_GET_FLOAT64(op1);+                neg_fp_res:+                    sp[-1] = __JS_NewFloat64(ctx, d);+                } else {+                    if (js_unary_arith_slow(ctx, sp, opcode))+                        goto exception;+                }+            }+            BREAK;+        CASE(OP_inc):+            {+                JSValue op1;+                int val;+                op1 = sp[-1];+                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {+                    val = JS_VALUE_GET_INT(op1);+                    if (unlikely(val == INT32_MAX))+                        goto inc_slow;+                    sp[-1] = JS_NewInt32(ctx, val + 1);+                } else {+                inc_slow:+                    if (js_unary_arith_slow(ctx, sp, opcode))+                        goto exception;+                }+            }+            BREAK;+        CASE(OP_dec):+            {+                JSValue op1;+                int val;+                op1 = sp[-1];+                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {+                    val = JS_VALUE_GET_INT(op1);+                    if (unlikely(val == INT32_MIN))+                        goto dec_slow;+                    sp[-1] = JS_NewInt32(ctx, val - 1);+                } else {+                dec_slow:+                    if (js_unary_arith_slow(ctx, sp, opcode))+                        goto exception;+                }+            }+            BREAK;+        CASE(OP_post_inc):+        CASE(OP_post_dec):+            if (js_post_inc_slow(ctx, sp, opcode))+                goto exception;+            sp++;+            BREAK;+        CASE(OP_inc_loc):+            {+                JSValue op1;+                int val;+                int idx;+                idx = *pc;+                pc += 1;++                op1 = var_buf[idx];+                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {+                    val = JS_VALUE_GET_INT(op1);+                    if (unlikely(val == INT32_MAX))+                        goto inc_loc_slow;+                    var_buf[idx] = JS_NewInt32(ctx, val + 1);+                } else {+                inc_loc_slow:+                    /* must duplicate otherwise the variable value may+                       be destroyed before JS code accesses it */+                    op1 = JS_DupValue(ctx, op1);+                    if (js_unary_arith_slow(ctx, &op1 + 1, OP_inc))+                        goto exception;+                    set_value(ctx, &var_buf[idx], op1);+                }+            }+            BREAK;+        CASE(OP_dec_loc):+            {+                JSValue op1;+                int val;+                int idx;+                idx = *pc;+                pc += 1;++                op1 = var_buf[idx];+                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {+                    val = JS_VALUE_GET_INT(op1);+                    if (unlikely(val == INT32_MIN))+                        goto dec_loc_slow;+                    var_buf[idx] = JS_NewInt32(ctx, val - 1);+                } else {+                dec_loc_slow:+                    /* must duplicate otherwise the variable value may+                       be destroyed before JS code accesses it */+                    op1 = JS_DupValue(ctx, op1);+                    if (js_unary_arith_slow(ctx, &op1 + 1, OP_dec))+                        goto exception;+                    set_value(ctx, &var_buf[idx], op1);+                }+            }+            BREAK;+        CASE(OP_not):+            {+                JSValue op1;+                op1 = sp[-1];+                if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) {+                    sp[-1] = JS_NewInt32(ctx, ~JS_VALUE_GET_INT(op1));+                } else {+                    if (js_not_slow(ctx, sp))+                        goto exception;+                }+            }+            BREAK;++        CASE(OP_shl):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    uint32_t v1, v2;+                    v1 = JS_VALUE_GET_INT(op1);+                    v2 = JS_VALUE_GET_INT(op2);+#ifdef CONFIG_BIGNUM+                    {+                        int64_t r;+                        if (unlikely(sf->js_mode & JS_MODE_MATH)) {+                            if (v2 > 0x1f)+                                goto shl_slow;+                            r = (int64_t)v1 << v2;+                            if ((int)r != r)+                                goto shl_slow;+                        } else {+                            v2 &= 0x1f;+                        }+                    }+#else+                    v2 &= 0x1f;+#endif+                    sp[-2] = JS_NewInt32(ctx, v1 << v2);+                    sp--;+                } else {+#ifdef CONFIG_BIGNUM+                shl_slow:+#endif+                    if (js_binary_logic_slow(ctx, sp, opcode))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_shr):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    uint32_t v2;+                    v2 = JS_VALUE_GET_INT(op2);+                    /* v1 >>> v2 retains its JS semantics if CONFIG_BIGNUM */+                    v2 &= 0x1f;+                    sp[-2] = JS_NewUint32(ctx,+                                          (uint32_t)JS_VALUE_GET_INT(op1) >>+                                          v2);+                    sp--;+                } else {+                    if (js_shr_slow(ctx, sp))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_sar):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    uint32_t v2;+                    v2 = JS_VALUE_GET_INT(op2);+#ifdef CONFIG_BIGNUM+                    if (unlikely(v2 > 0x1f)) {+                        if (unlikely(sf->js_mode & JS_MODE_MATH))+                            goto sar_slow;+                        else+                            v2 &= 0x1f;+                    }+#else+                    v2 &= 0x1f;+#endif+                    sp[-2] = JS_NewInt32(ctx,+                                          (int)JS_VALUE_GET_INT(op1) >> v2);+                    sp--;+                } else {+#ifdef CONFIG_BIGNUM+                sar_slow:+#endif+                    if (js_binary_logic_slow(ctx, sp, opcode))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_and):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    sp[-2] = JS_NewInt32(ctx,+                                         JS_VALUE_GET_INT(op1) &+                                         JS_VALUE_GET_INT(op2));+                    sp--;+                } else {+                    if (js_binary_logic_slow(ctx, sp, opcode))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_or):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    sp[-2] = JS_NewInt32(ctx,+                                         JS_VALUE_GET_INT(op1) |+                                         JS_VALUE_GET_INT(op2));+                    sp--;+                } else {+                    if (js_binary_logic_slow(ctx, sp, opcode))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+        CASE(OP_xor):+            {+                JSValue op1, op2;+                op1 = sp[-2];+                op2 = sp[-1];+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {+                    sp[-2] = JS_NewInt32(ctx,+                                         JS_VALUE_GET_INT(op1) ^+                                         JS_VALUE_GET_INT(op2));+                    sp--;+                } else {+                    if (js_binary_logic_slow(ctx, sp, opcode))+                        goto exception;+                    sp--;+                }+            }+            BREAK;+++#define OP_CMP(opcode, binary_op, slow_call)              \+            CASE(opcode):                                 \+                {                                         \+                JSValue op1, op2;                         \+                op1 = sp[-2];                             \+                op2 = sp[-1];                                   \+                if (likely(JS_VALUE_IS_BOTH_INT(op1, op2))) {           \+                    sp[-2] = JS_NewBool(ctx, JS_VALUE_GET_INT(op1) binary_op JS_VALUE_GET_INT(op2)); \+                    sp--;                                               \+                } else {                                                \+                    if (slow_call)                                      \+                        goto exception;                                 \+                    sp--;                                               \+                }                                                       \+                }                                                       \+            BREAK++            OP_CMP(OP_lt, <, js_relational_slow(ctx, sp, opcode));+            OP_CMP(OP_lte, <=, js_relational_slow(ctx, sp, opcode));+            OP_CMP(OP_gt, >, js_relational_slow(ctx, sp, opcode));+            OP_CMP(OP_gte, >=, js_relational_slow(ctx, sp, opcode));+            OP_CMP(OP_eq, ==, js_eq_slow(ctx, sp, 0));+            OP_CMP(OP_neq, !=, js_eq_slow(ctx, sp, 1));+            OP_CMP(OP_strict_eq, ==, js_strict_eq_slow(ctx, sp, 0));+            OP_CMP(OP_strict_neq, !=, js_strict_eq_slow(ctx, sp, 1));++#ifdef CONFIG_BIGNUM+        CASE(OP_mul_pow10):+            if (rt->bigfloat_ops.mul_pow10(ctx, sp))+                goto exception;+            sp--;+            BREAK;+#endif+        CASE(OP_in):+            if (js_operator_in(ctx, sp))+                goto exception;+            sp--;+            BREAK;+        CASE(OP_instanceof):+            if (js_operator_instanceof(ctx, sp))+                goto exception;+            sp--;+            BREAK;+        CASE(OP_typeof):+            {+                JSValue op1;+                JSAtom atom;++                op1 = sp[-1];+                atom = js_operator_typeof(ctx, op1);+                JS_FreeValue(ctx, op1);+                sp[-1] = JS_AtomToString(ctx, atom);+            }+            BREAK;+        CASE(OP_delete):+            if (js_operator_delete(ctx, sp))+                goto exception;+            sp--;+            BREAK;+        CASE(OP_delete_var):+            {+                JSAtom atom;+                int ret;++                atom = get_u32(pc);+                pc += 4;++                ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0);+                if (unlikely(ret < 0))+                    goto exception;+                *sp++ = JS_NewBool(ctx, ret);+            }+            BREAK;++        CASE(OP_to_object):+            if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_OBJECT) {+                ret_val = JS_ToObject(ctx, sp[-1]);+                if (JS_IsException(ret_val))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = ret_val;+            }+            BREAK;++        CASE(OP_to_propkey):+            switch (JS_VALUE_GET_TAG(sp[-1])) {+            case JS_TAG_INT:+            case JS_TAG_STRING:+            case JS_TAG_SYMBOL:+                break;+            default:+                ret_val = JS_ToPropertyKey(ctx, sp[-1]);+                if (JS_IsException(ret_val))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = ret_val;+                break;+            }+            BREAK;++        CASE(OP_to_propkey2):+            /* must be tested first */+            if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) {+                JS_ThrowTypeError(ctx, "value has no property");+                goto exception;+            }+            switch (JS_VALUE_GET_TAG(sp[-1])) {+            case JS_TAG_INT:+            case JS_TAG_STRING:+            case JS_TAG_SYMBOL:+                break;+            default:+                ret_val = JS_ToPropertyKey(ctx, sp[-1]);+                if (JS_IsException(ret_val))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = ret_val;+                break;+            }+            BREAK;+#if 0+        CASE(OP_to_string):+            if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_STRING) {+                ret_val = JS_ToString(ctx, sp[-1]);+                if (JS_IsException(ret_val))+                    goto exception;+                JS_FreeValue(ctx, sp[-1]);+                sp[-1] = ret_val;+            }+            BREAK;+#endif+        CASE(OP_with_get_var):+        CASE(OP_with_put_var):+        CASE(OP_with_delete_var):+        CASE(OP_with_make_ref):+        CASE(OP_with_get_ref):+        CASE(OP_with_get_ref_undef):+            {+                JSAtom atom;+                int32_t diff;+                JSValue obj, val;+                int ret, is_with;+                atom = get_u32(pc);+                diff = get_u32(pc + 4);+                is_with = pc[8];+                pc += 9;++                obj = sp[-1];+                ret = JS_HasProperty(ctx, obj, atom);+                if (unlikely(ret < 0))+                    goto exception;+                if (ret) {+                    if (is_with) {+                        ret = js_has_unscopable(ctx, obj, atom);+                        if (unlikely(ret < 0))+                            goto exception;+                        if (ret)+                            goto no_with;+                    }+                    switch (opcode) {+                    case OP_with_get_var:+                        val = JS_GetProperty(ctx, obj, atom);+                        if (unlikely(JS_IsException(val)))+                            goto exception;+                        set_value(ctx, &sp[-1], val);+                        break;+                    case OP_with_put_var:+                        /* XXX: check if strict mode */+                        ret = JS_SetPropertyInternal(ctx, obj, atom, sp[-2],+                                                     JS_PROP_THROW_STRICT);+                        JS_FreeValue(ctx, sp[-1]);+                        sp -= 2;+                        if (unlikely(ret < 0))+                            goto exception;+                        break;+                    case OP_with_delete_var:+                        ret = JS_DeleteProperty(ctx, obj, atom, 0);+                        if (unlikely(ret < 0))+                            goto exception;+                        JS_FreeValue(ctx, sp[-1]);+                        sp[-1] = JS_NewBool(ctx, ret);+                        break;+                    case OP_with_make_ref:+                        /* produce a pair object/propname on the stack */+                        *sp++ = JS_AtomToValue(ctx, atom);+                        break;+                    case OP_with_get_ref:+                        /* produce a pair object/method on the stack */+                        val = JS_GetProperty(ctx, obj, atom);+                        if (unlikely(JS_IsException(val)))+                            goto exception;+                        *sp++ = val;+                        break;+                    case OP_with_get_ref_undef:+                        /* produce a pair undefined/function on the stack */+                        val = JS_GetProperty(ctx, obj, atom);+                        if (unlikely(JS_IsException(val)))+                            goto exception;+                        JS_FreeValue(ctx, sp[-1]);+                        sp[-1] = JS_UNDEFINED;+                        *sp++ = val;+                        break;+                    }+                    pc += diff - 5;+                } else {+                no_with:+                    /* if not jumping, drop the object argument */+                    JS_FreeValue(ctx, sp[-1]);+                    sp--;+                }+            }+            BREAK;++        CASE(OP_await):+            ret_val = JS_NewInt32(ctx, FUNC_RET_AWAIT);+            goto done_generator;+        CASE(OP_yield):+            ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD);+            goto done_generator;+        CASE(OP_yield_star):+        CASE(OP_async_yield_star):+            ret_val = JS_NewInt32(ctx, FUNC_RET_YIELD_STAR);+            goto done_generator;+        CASE(OP_return_async):+        CASE(OP_initial_yield):+            ret_val = JS_UNDEFINED;+            goto done_generator;++        CASE(OP_nop):+            BREAK;+        CASE(OP_is_undefined_or_null):+            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED ||+                JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) {+                goto set_true;+            } else {+                goto free_and_set_false;+            }+#if SHORT_OPCODES+        CASE(OP_is_undefined):+            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_UNDEFINED) {+                goto set_true;+            } else {+                goto free_and_set_false;+            }+        CASE(OP_is_null):+            if (JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_NULL) {+                goto set_true;+            } else {+                goto free_and_set_false;+            }+            /* XXX: could merge to a single opcode */+        CASE(OP_typeof_is_undefined):+            /* different from OP_is_undefined because of isHTMLDDA */+            if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_undefined) {+                goto free_and_set_true;+            } else {+                goto free_and_set_false;+            }+        CASE(OP_typeof_is_function):+            if (js_operator_typeof(ctx, sp[-1]) == JS_ATOM_function) {+                goto free_and_set_true;+            } else {+                goto free_and_set_false;+            }+        free_and_set_true:+            JS_FreeValue(ctx, sp[-1]);+#endif+        set_true:+            sp[-1] = JS_TRUE;+            BREAK;+        free_and_set_false:+            JS_FreeValue(ctx, sp[-1]);+            sp[-1] = JS_FALSE;+            BREAK;+        CASE(OP_invalid):+        DEFAULT:+            JS_ThrowInternalError(ctx, "invalid opcode: pc=%u opcode=0x%02x",+                                  (int)(pc - b->byte_code_buf - 1), opcode);+            goto exception;+        }+    }+ exception:+    if (is_backtrace_needed(ctx, rt->current_exception)) {+        /* add the backtrace information now (it is not done+           before if the exception happens in a bytecode+           operation */+        sf->cur_pc = pc;+        build_backtrace(ctx, rt->current_exception, NULL, 0, 0);+    }+    if (!JS_IsUncatchableError(ctx, rt->current_exception)) {+        while (sp > stack_buf) {+            JSValue val = *--sp;+            JS_FreeValue(ctx, val);+            if (JS_VALUE_GET_TAG(val) == JS_TAG_CATCH_OFFSET) {+                int pos = JS_VALUE_GET_INT(val);+                if (pos == 0) {+                    /* enumerator: close it with a throw */+                    JS_FreeValue(ctx, sp[-1]); /* drop the next method */+                    sp--;+                    JS_IteratorClose(ctx, sp[-1], TRUE);+                } else {+                    *sp++ = rt->current_exception;+                    rt->current_exception = JS_NULL;+                    pc = b->byte_code_buf + pos;+                    goto restart;+                }+            }+        }+    }+    ret_val = JS_EXCEPTION;+    /* the local variables are freed by the caller in the generator+       case. Hence the label 'done' should never be reached in a+       generator function. */+    if (b->func_kind != JS_FUNC_NORMAL) {+    done_generator:+        sf->cur_pc = pc;+        sf->cur_sp = sp;+    } else {+    done:+        if (unlikely(!list_empty(&sf->var_ref_list))) {+            /* variable references reference the stack: must close them */+            close_var_refs(rt, sf);+        }+        /* free the local variables and stack */+        for(pval = local_buf; pval < sp; pval++) {+            JS_FreeValue(ctx, *pval);+        }+    }+    rt->current_stack_frame = sf->prev_frame;+    return ret_val;+}++JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,+                int argc, JSValueConst *argv)+{+    return JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,+                           argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);+}++static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_obj,+                           int argc, JSValueConst *argv)+{+    JSValue res = JS_CallInternal(ctx, func_obj, this_obj, JS_UNDEFINED,+                                  argc, (JSValue *)argv, JS_CALL_FLAG_COPY_ARGV);+    JS_FreeValue(ctx, func_obj);+    return res;+}++/* warning: the refcount of the context is not incremented. Return+   NULL in case of exception (case of revoked proxy only) */+static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)+{+    JSObject *p;+    JSContext *realm;+    +    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)+        return ctx;+    p = JS_VALUE_GET_OBJ(func_obj);+    switch(p->class_id) {+    case JS_CLASS_C_FUNCTION:+        realm = p->u.cfunc.realm;+        break;+    case JS_CLASS_BYTECODE_FUNCTION:+    case JS_CLASS_GENERATOR_FUNCTION:+    case JS_CLASS_ASYNC_FUNCTION:+    case JS_CLASS_ASYNC_GENERATOR_FUNCTION:+        {+            JSFunctionBytecode *b;+            b = p->u.func.function_bytecode;+            realm = b->realm;+        }+        break;+    case JS_CLASS_PROXY:+        {+            JSProxyData *s = p->u.opaque;+            if (!s)+                return ctx;+            if (s->is_revoked) {+                JS_ThrowTypeErrorRevokedProxy(ctx);+                return NULL;+            } else {+                realm = JS_GetFunctionRealm(ctx, s->target);+            }+        }+        break;+    case JS_CLASS_BOUND_FUNCTION:+        {+            JSBoundFunction *bf = p->u.bound_function;+            realm = JS_GetFunctionRealm(ctx, bf->func_obj);+        }+        break;+    default:+        realm = ctx;+        break;+    }+    return realm;+}++static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,+                                   int class_id)+{+    JSValue proto, obj;+    JSContext *realm;+    +    if (JS_IsUndefined(ctor)) {+        proto = JS_DupValue(ctx, ctx->class_proto[class_id]);+    } else {+        proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);+        if (JS_IsException(proto))+            return proto;+        if (!JS_IsObject(proto)) {+            JS_FreeValue(ctx, proto);+            realm = JS_GetFunctionRealm(ctx, ctor);+            if (!realm)+                return JS_EXCEPTION;+            proto = JS_DupValue(ctx, realm->class_proto[class_id]);+        }+    }+    obj = JS_NewObjectProtoClass(ctx, proto, class_id);+    JS_FreeValue(ctx, proto);+    return obj;+}++/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */+static JSValue JS_CallConstructorInternal(JSContext *ctx,+                                          JSValueConst func_obj,+                                          JSValueConst new_target,+                                          int argc, JSValue *argv, int flags)+{+    JSObject *p;+    JSFunctionBytecode *b;++    if (js_poll_interrupts(ctx))+        return JS_EXCEPTION;+    flags |= JS_CALL_FLAG_CONSTRUCTOR;+    if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT))+        goto not_a_function;+    p = JS_VALUE_GET_OBJ(func_obj);+    if (unlikely(!p->is_constructor))+        return JS_ThrowTypeError(ctx, "not a constructor");+    if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {+        JSClassCall *call_func;+        call_func = ctx->rt->class_array[p->class_id].call;+        if (!call_func) {+        not_a_function:+            return JS_ThrowTypeError(ctx, "not a function");+        }+        return call_func(ctx, func_obj, new_target, argc,+                         (JSValueConst *)argv, flags);+    }++    b = p->u.func.function_bytecode;+    if (b->is_derived_class_constructor) {+        return JS_CallInternal(ctx, func_obj, JS_UNDEFINED, new_target, argc, argv, flags);+    } else {+        JSValue obj, ret;+        /* legacy constructor behavior */+        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);+        if (JS_IsException(obj))+            return JS_EXCEPTION;+        ret = JS_CallInternal(ctx, func_obj, obj, new_target, argc, argv, flags);+        if (JS_VALUE_GET_TAG(ret) == JS_TAG_OBJECT ||+            JS_IsException(ret)) {+            JS_FreeValue(ctx, obj);+            return ret;+        } else {+            JS_FreeValue(ctx, ret);+            return obj;+        }+    }+}++JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,+                            JSValueConst new_target,+                            int argc, JSValueConst *argv)+{+    return JS_CallConstructorInternal(ctx, func_obj, new_target,+                                      argc, (JSValue *)argv,+                                      JS_CALL_FLAG_COPY_ARGV);+}++JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,+                           int argc, JSValueConst *argv)+{+    return JS_CallConstructorInternal(ctx, func_obj, func_obj,+                                      argc, (JSValue *)argv,+                                      JS_CALL_FLAG_COPY_ARGV);+}++JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,+                  int argc, JSValueConst *argv)+{+    JSValue func_obj;+    func_obj = JS_GetProperty(ctx, this_val, atom);+    if (JS_IsException(func_obj))+        return func_obj;+    return JS_CallFree(ctx, func_obj, this_val, argc, argv);+}++static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom,+                             int argc, JSValueConst *argv)+{+    JSValue res = JS_Invoke(ctx, this_val, atom, argc, argv);+    JS_FreeValue(ctx, this_val);+    return res;+}++/* JSAsyncFunctionState (used by generator and async functions) */+static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s,+                                       JSValueConst func_obj, JSValueConst this_obj,+                                       int argc, JSValueConst *argv)+{+    JSObject *p;+    JSFunctionBytecode *b;+    JSStackFrame *sf;+    int local_count, i, arg_buf_len, n;++    sf = &s->frame;+    init_list_head(&sf->var_ref_list);+    p = JS_VALUE_GET_OBJ(func_obj);+    b = p->u.func.function_bytecode;+    sf->js_mode = b->js_mode;+    sf->cur_pc = b->byte_code_buf;+    arg_buf_len = max_int(b->arg_count, argc);+    local_count = arg_buf_len + b->var_count + b->stack_size;+    sf->arg_buf = js_malloc(ctx, sizeof(JSValue) * max_int(local_count, 1));+    if (!sf->arg_buf)+        return -1;+    sf->cur_func = JS_DupValue(ctx, func_obj);+    s->this_val = JS_DupValue(ctx, this_obj);+    s->argc = argc;+    sf->arg_count = arg_buf_len;+    sf->var_buf = sf->arg_buf + arg_buf_len;+    sf->cur_sp = sf->var_buf + b->var_count;+    for(i = 0; i < argc; i++)+        sf->arg_buf[i] = JS_DupValue(ctx, argv[i]);+    n = arg_buf_len + b->var_count;+    for(i = argc; i < n; i++)+        sf->arg_buf[i] = JS_UNDEFINED;+    return 0;+}++static void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s,+                            JS_MarkFunc *mark_func)+{+    JSStackFrame *sf;+    JSValue *sp;++    sf = &s->frame;+    JS_MarkValue(rt, sf->cur_func, mark_func);+    JS_MarkValue(rt, s->this_val, mark_func);+    if (sf->cur_sp) {+        /* if the function is running, cur_sp is not known so we+           cannot mark the stack. Marking the variables is not needed+           because a running function cannot be part of a removable+           cycle */+        for(sp = sf->arg_buf; sp < sf->cur_sp; sp++)+            JS_MarkValue(rt, *sp, mark_func);+    }+}++static void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s)+{+    JSStackFrame *sf;+    JSValue *sp;++    sf = &s->frame;++    /* close the closure variables. */+    close_var_refs(rt, sf);+    +    if (sf->arg_buf) {+        /* cannot free the function if it is running */+        assert(sf->cur_sp != NULL);+        for(sp = sf->arg_buf; sp < sf->cur_sp; sp++) {+            JS_FreeValueRT(rt, *sp);+        }+        js_free_rt(rt, sf->arg_buf);+    }+    JS_FreeValueRT(rt, sf->cur_func);+    JS_FreeValueRT(rt, s->this_val);+}++static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s)+{+    JSValue func_obj;++    if (js_check_stack_overflow(ctx->rt, 0))+        return JS_ThrowStackOverflow(ctx);++    /* the tag does not matter provided it is not an object */+    func_obj = JS_MKPTR(JS_TAG_INT, s);+    return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED,+                           s->argc, s->frame.arg_buf, JS_CALL_FLAG_GENERATOR);+}+++/* Generators */++typedef enum JSGeneratorStateEnum {+    JS_GENERATOR_STATE_SUSPENDED_START,+    JS_GENERATOR_STATE_SUSPENDED_YIELD,+    JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR,+    JS_GENERATOR_STATE_EXECUTING,+    JS_GENERATOR_STATE_COMPLETED,+} JSGeneratorStateEnum;++typedef struct JSGeneratorData {+    JSGeneratorStateEnum state;+    JSAsyncFunctionState func_state;+} JSGeneratorData;++static void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s)+{+    if (s->state == JS_GENERATOR_STATE_COMPLETED)+        return;+    async_func_free(rt, &s->func_state);+    s->state = JS_GENERATOR_STATE_COMPLETED;+}++static void js_generator_finalizer(JSRuntime *rt, JSValue obj)+{+    JSGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_GENERATOR);++    if (s) {+        free_generator_stack_rt(rt, s);+        js_free_rt(rt, s);+    }+}++static void free_generator_stack(JSContext *ctx, JSGeneratorData *s)+{+    free_generator_stack_rt(ctx->rt, s);+}++static void js_generator_mark(JSRuntime *rt, JSValueConst val,+                              JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSGeneratorData *s = p->u.generator_data;++    if (!s || s->state == JS_GENERATOR_STATE_COMPLETED)+        return;+    async_func_mark(rt, &s->func_state, mark_func);+}++/* XXX: use enum */+#define GEN_MAGIC_NEXT   0+#define GEN_MAGIC_RETURN 1+#define GEN_MAGIC_THROW  2++static JSValue js_generator_next(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv,+                                 BOOL *pdone, int magic)+{+    JSGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_GENERATOR);+    JSStackFrame *sf;+    JSValue ret, func_ret;++    *pdone = TRUE;+    if (!s)+        return JS_ThrowTypeError(ctx, "not a generator");+    sf = &s->func_state.frame;+    switch(s->state) {+    default:+    case JS_GENERATOR_STATE_SUSPENDED_START:+        if (magic == GEN_MAGIC_NEXT) {+            goto exec_no_arg;+        } else {+            free_generator_stack(ctx, s);+            goto done;+        }+        break;+    case JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR:+    case JS_GENERATOR_STATE_SUSPENDED_YIELD:+        /* cur_sp[-1] was set to JS_UNDEFINED in the previous call */+        ret = JS_DupValue(ctx, argv[0]);+        if (magic == GEN_MAGIC_THROW &&+            s->state == JS_GENERATOR_STATE_SUSPENDED_YIELD) {+            JS_Throw(ctx, ret);+            s->func_state.throw_flag = TRUE;+        } else {+            sf->cur_sp[-1] = ret;+            sf->cur_sp[0] = JS_NewInt32(ctx, magic);+            sf->cur_sp++;+        exec_no_arg:+            s->func_state.throw_flag = FALSE;+        }+        s->state = JS_GENERATOR_STATE_EXECUTING;+        func_ret = async_func_resume(ctx, &s->func_state);+        s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD;+        if (JS_IsException(func_ret)) {+            /* finalize the execution in case of exception */+            free_generator_stack(ctx, s);+            return func_ret;+        }+        if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {+            /* get the returned yield value at the top of the stack */+            ret = sf->cur_sp[-1];+            sf->cur_sp[-1] = JS_UNDEFINED;+            if (JS_VALUE_GET_INT(func_ret) == FUNC_RET_YIELD_STAR) {+                s->state = JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR;+                /* return (value, done) object */+                *pdone = 2;+            } else {+                *pdone = FALSE;+            }+        } else {+            /* end of iterator */+            ret = sf->cur_sp[-1];+            sf->cur_sp[-1] = JS_UNDEFINED;+            JS_FreeValue(ctx, func_ret);+            free_generator_stack(ctx, s);+        }+        break;+    case JS_GENERATOR_STATE_COMPLETED:+    done:+        /* execution is finished */+        switch(magic) {+        default:+        case GEN_MAGIC_NEXT:+            ret = JS_UNDEFINED;+            break;+        case GEN_MAGIC_RETURN:+            ret = JS_DupValue(ctx, argv[0]);+            break;+        case GEN_MAGIC_THROW:+            ret = JS_Throw(ctx, JS_DupValue(ctx, argv[0]));+            break;+        }+        break;+    case JS_GENERATOR_STATE_EXECUTING:+        ret = JS_ThrowTypeError(ctx, "cannot invoke a running generator");+        break;+    }+    return ret;+}++static JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj,+                                          JSValueConst this_obj,+                                          int argc, JSValueConst *argv,+                                          int flags)+{+    JSValue obj, func_ret;+    JSGeneratorData *s;++    s = js_mallocz(ctx, sizeof(*s));+    if (!s)+        return JS_EXCEPTION;+    s->state = JS_GENERATOR_STATE_SUSPENDED_START;+    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {+        s->state = JS_GENERATOR_STATE_COMPLETED;+        goto fail;+    }++    /* execute the function up to 'OP_initial_yield' */+    func_ret = async_func_resume(ctx, &s->func_state);+    if (JS_IsException(func_ret))+        goto fail;+    JS_FreeValue(ctx, func_ret);++    obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_GENERATOR);+    if (JS_IsException(obj))+        goto fail;+    JS_SetOpaque(obj, s);+    return obj;+ fail:+    free_generator_stack_rt(ctx->rt, s);+    js_free(ctx, s);+    return JS_EXCEPTION;+}++/* AsyncFunction */++static void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s)+{+    if (s->is_active) {+        async_func_free(rt, &s->func_state);+        s->is_active = FALSE;+    }+}++static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s)+{+    js_async_function_terminate(rt, s);+    JS_FreeValueRT(rt, s->resolving_funcs[0]);+    JS_FreeValueRT(rt, s->resolving_funcs[1]);+    remove_gc_object(&s->header);+    js_free_rt(rt, s);+}++static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s)+{+    if (--s->header.ref_count == 0) {+        js_async_function_free0(rt, s);+    }+}++static void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSAsyncFunctionData *s = p->u.async_function_data;+    if (s) {+        js_async_function_free(rt, s);+    }+}++static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,+                                           JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSAsyncFunctionData *s = p->u.async_function_data;+    if (s) {+        mark_func(rt, &s->header);+    }+}++static int js_async_function_resolve_create(JSContext *ctx,+                                            JSAsyncFunctionData *s,+                                            JSValue *resolving_funcs)+{+    int i;+    JSObject *p;++    for(i = 0; i < 2; i++) {+        resolving_funcs[i] =+            JS_NewObjectProtoClass(ctx, ctx->function_proto,+                                   JS_CLASS_ASYNC_FUNCTION_RESOLVE + i);+        if (JS_IsException(resolving_funcs[i])) {+            if (i == 1)+                JS_FreeValue(ctx, resolving_funcs[0]);+            return -1;+        }+        p = JS_VALUE_GET_OBJ(resolving_funcs[i]);+        s->header.ref_count++;+        p->u.async_function_data = s;+    }+    return 0;+}++static void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s)+{+    JSValue func_ret, ret2;++    func_ret = async_func_resume(ctx, &s->func_state);+    if (JS_IsException(func_ret)) {+        JSValue error;+    fail:+        error = JS_GetException(ctx);+        ret2 = JS_Call(ctx, s->resolving_funcs[1], JS_UNDEFINED,+                       1, (JSValueConst *)&error);+        JS_FreeValue(ctx, error);+        js_async_function_terminate(ctx->rt, s);+        JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */+    } else {+        JSValue value;+        value = s->func_state.frame.cur_sp[-1];+        s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;+        if (JS_IsUndefined(func_ret)) {+            /* function returned */+            ret2 = JS_Call(ctx, s->resolving_funcs[0], JS_UNDEFINED,+                           1, (JSValueConst *)&value);+            JS_FreeValue(ctx, ret2); /* XXX: what to do if exception ? */+            JS_FreeValue(ctx, value);+            js_async_function_terminate(ctx->rt, s);+        } else {+            JSValue promise, resolving_funcs[2], resolving_funcs1[2];+            int i, res;++            /* await */+            JS_FreeValue(ctx, func_ret); /* not used */+            promise = js_promise_resolve(ctx, ctx->promise_ctor,+                                         1, (JSValueConst *)&value, 0);+            JS_FreeValue(ctx, value);+            if (JS_IsException(promise))+                goto fail;+            if (js_async_function_resolve_create(ctx, s, resolving_funcs)) {+                JS_FreeValue(ctx, promise);+                goto fail;+            }++            /* Note: no need to create 'thrownawayCapability' as in+               the spec */+            for(i = 0; i < 2; i++)+                resolving_funcs1[i] = JS_UNDEFINED;+            res = perform_promise_then(ctx, promise,+                                       (JSValueConst *)resolving_funcs,+                                       (JSValueConst *)resolving_funcs1);+            JS_FreeValue(ctx, promise);+            for(i = 0; i < 2; i++)+                JS_FreeValue(ctx, resolving_funcs[i]);+            if (res)+                goto fail;+        }+    }+}++static JSValue js_async_function_resolve_call(JSContext *ctx,+                                              JSValueConst func_obj,+                                              JSValueConst this_obj,+                                              int argc, JSValueConst *argv,+                                              int flags)+{+    JSObject *p = JS_VALUE_GET_OBJ(func_obj);+    JSAsyncFunctionData *s = p->u.async_function_data;+    BOOL is_reject = p->class_id - JS_CLASS_ASYNC_FUNCTION_RESOLVE;+    JSValueConst arg;++    if (argc > 0)+        arg = argv[0];+    else+        arg = JS_UNDEFINED;+    s->func_state.throw_flag = is_reject;+    if (is_reject) {+        JS_Throw(ctx, JS_DupValue(ctx, arg));+    } else {+        /* return value of await */+        s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);+    }+    js_async_function_resume(ctx, s);+    return JS_UNDEFINED;+}++static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj,+                                      JSValueConst this_obj,+                                      int argc, JSValueConst *argv, int flags)+{+    JSValue promise;+    JSAsyncFunctionData *s;++    s = js_mallocz(ctx, sizeof(*s));+    if (!s)+        return JS_EXCEPTION;+    s->header.ref_count = 1;+    add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION);+    s->is_active = FALSE;+    s->resolving_funcs[0] = JS_UNDEFINED;+    s->resolving_funcs[1] = JS_UNDEFINED;++    promise = JS_NewPromiseCapability(ctx, s->resolving_funcs);+    if (JS_IsException(promise))+        goto fail;++    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {+    fail:+        JS_FreeValue(ctx, promise);+        js_async_function_free(ctx->rt, s);+        return JS_EXCEPTION;+    }+    s->is_active = TRUE;++    js_async_function_resume(ctx, s);++    js_async_function_free(ctx->rt, s);++    return promise;+}++/* AsyncGenerator */++typedef enum JSAsyncGeneratorStateEnum {+    JS_ASYNC_GENERATOR_STATE_SUSPENDED_START,+    JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD,+    JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR,+    JS_ASYNC_GENERATOR_STATE_EXECUTING,+    JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN,+    JS_ASYNC_GENERATOR_STATE_COMPLETED,+} JSAsyncGeneratorStateEnum;++typedef struct JSAsyncGeneratorRequest {+    struct list_head link;+    /* completion */+    int completion_type; /* GEN_MAGIC_x */+    JSValue result;+    /* promise capability */+    JSValue promise;+    JSValue resolving_funcs[2];+} JSAsyncGeneratorRequest;++typedef struct JSAsyncGeneratorData {+    JSObject *generator; /* back pointer to the object (const) */+    JSAsyncGeneratorStateEnum state;+    JSAsyncFunctionState func_state;+    struct list_head queue; /* list of JSAsyncGeneratorRequest.link */+} JSAsyncGeneratorData;++static void js_async_generator_free(JSRuntime *rt,+                                    JSAsyncGeneratorData *s)+{+    struct list_head *el, *el1;+    JSAsyncGeneratorRequest *req;++    list_for_each_safe(el, el1, &s->queue) {+        req = list_entry(el, JSAsyncGeneratorRequest, link);+        JS_FreeValueRT(rt, req->result);+        JS_FreeValueRT(rt, req->promise);+        JS_FreeValueRT(rt, req->resolving_funcs[0]);+        JS_FreeValueRT(rt, req->resolving_funcs[1]);+        js_free_rt(rt, req);+    }+    if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&+        s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {+        async_func_free(rt, &s->func_state);+    }+    js_free_rt(rt, s);+}++static void js_async_generator_finalizer(JSRuntime *rt, JSValue obj)+{+    JSAsyncGeneratorData *s = JS_GetOpaque(obj, JS_CLASS_ASYNC_GENERATOR);++    if (s) {+        js_async_generator_free(rt, s);+    }+}++static void js_async_generator_mark(JSRuntime *rt, JSValueConst val,+                                    JS_MarkFunc *mark_func)+{+    JSAsyncGeneratorData *s = JS_GetOpaque(val, JS_CLASS_ASYNC_GENERATOR);+    struct list_head *el;+    JSAsyncGeneratorRequest *req;+    if (s) {+        list_for_each(el, &s->queue) {+            req = list_entry(el, JSAsyncGeneratorRequest, link);+            JS_MarkValue(rt, req->result, mark_func);+            JS_MarkValue(rt, req->promise, mark_func);+            JS_MarkValue(rt, req->resolving_funcs[0], mark_func);+            JS_MarkValue(rt, req->resolving_funcs[1], mark_func);+        }+        if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED &&+            s->state != JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN) {+            async_func_mark(rt, &s->func_state, mark_func);+        }+    }+}++static JSValue js_async_generator_resolve_function(JSContext *ctx,+                                          JSValueConst this_obj,+                                          int argc, JSValueConst *argv,+                                          int magic, JSValue *func_data);++static int js_async_generator_resolve_function_create(JSContext *ctx,+                                                      JSValueConst generator,+                                                      JSValue *resolving_funcs,+                                                      BOOL is_resume_next)+{+    int i;+    JSValue func;++    for(i = 0; i < 2; i++) {+        func = JS_NewCFunctionData(ctx, js_async_generator_resolve_function, 1,+                                   i + is_resume_next * 2, 1, &generator);+        if (JS_IsException(func)) {+            if (i == 1)+                JS_FreeValue(ctx, resolving_funcs[0]);+            return -1;+        }+        resolving_funcs[i] = func;+    }+    return 0;+}++static int js_async_generator_await(JSContext *ctx,+                                    JSAsyncGeneratorData *s,+                                    JSValueConst value)+{+    JSValue promise, resolving_funcs[2], resolving_funcs1[2];+    int i, res;++    promise = js_promise_resolve(ctx, ctx->promise_ctor,+                                 1, &value, 0);+    if (JS_IsException(promise))+        goto fail;++    if (js_async_generator_resolve_function_create(ctx, JS_MKPTR(JS_TAG_OBJECT, s->generator),+                                                   resolving_funcs, FALSE)) {+        JS_FreeValue(ctx, promise);+        goto fail;+    }++    /* Note: no need to create 'thrownawayCapability' as in+       the spec */+    for(i = 0; i < 2; i++)+        resolving_funcs1[i] = JS_UNDEFINED;+    res = perform_promise_then(ctx, promise,+                               (JSValueConst *)resolving_funcs,+                               (JSValueConst *)resolving_funcs1);+    JS_FreeValue(ctx, promise);+    for(i = 0; i < 2; i++)+        JS_FreeValue(ctx, resolving_funcs[i]);+    if (res)+        goto fail;+    return 0;+ fail:+    return -1;+}++static void js_async_generator_resolve_or_reject(JSContext *ctx,+                                                 JSAsyncGeneratorData *s,+                                                 JSValueConst result,+                                                 int is_reject)+{+    JSAsyncGeneratorRequest *next;+    JSValue ret;++    next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);+    list_del(&next->link);+    ret = JS_Call(ctx, next->resolving_funcs[is_reject], JS_UNDEFINED, 1,+                  &result);+    JS_FreeValue(ctx, ret);+    JS_FreeValue(ctx, next->result);+    JS_FreeValue(ctx, next->promise);+    JS_FreeValue(ctx, next->resolving_funcs[0]);+    JS_FreeValue(ctx, next->resolving_funcs[1]);+    js_free(ctx, next);+}++static void js_async_generator_resolve(JSContext *ctx,+                                       JSAsyncGeneratorData *s,+                                       JSValueConst value,+                                       BOOL done)+{+    JSValue result;+    result = js_create_iterator_result(ctx, JS_DupValue(ctx, value), done);+    /* XXX: better exception handling ? */+    js_async_generator_resolve_or_reject(ctx, s, result, 0);+    JS_FreeValue(ctx, result);+ }++static void js_async_generator_reject(JSContext *ctx,+                                       JSAsyncGeneratorData *s,+                                       JSValueConst exception)+{+    js_async_generator_resolve_or_reject(ctx, s, exception, 1);+}++static void js_async_generator_complete(JSContext *ctx,+                                        JSAsyncGeneratorData *s)+{+    if (s->state != JS_ASYNC_GENERATOR_STATE_COMPLETED) {+        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;+        async_func_free(ctx->rt, &s->func_state);+    }+}++static int js_async_generator_completed_return(JSContext *ctx,+                                               JSAsyncGeneratorData *s,+                                               JSValueConst value)+{+    JSValue promise, resolving_funcs[2], resolving_funcs1[2];+    int res;++    promise = js_promise_resolve(ctx, ctx->promise_ctor,+                                 1, (JSValueConst *)&value, 0);+    if (JS_IsException(promise))+        return -1;+    if (js_async_generator_resolve_function_create(ctx,+                                                   JS_MKPTR(JS_TAG_OBJECT, s->generator),+                                                   resolving_funcs1,+                                                   TRUE)) {+        JS_FreeValue(ctx, promise);+        return -1;+    }+    resolving_funcs[0] = JS_UNDEFINED;+    resolving_funcs[1] = JS_UNDEFINED;+    res = perform_promise_then(ctx, promise,+                               (JSValueConst *)resolving_funcs1,+                               (JSValueConst *)resolving_funcs);+    JS_FreeValue(ctx, resolving_funcs1[0]);+    JS_FreeValue(ctx, resolving_funcs1[1]);+    JS_FreeValue(ctx, promise);+    return res;+}++static void js_async_generator_resume_next(JSContext *ctx,+                                           JSAsyncGeneratorData *s)+{+    JSAsyncGeneratorRequest *next;+    JSValue func_ret, value;++    for(;;) {+        if (list_empty(&s->queue))+            break;+        next = list_entry(s->queue.next, JSAsyncGeneratorRequest, link);+        switch(s->state) {+        case JS_ASYNC_GENERATOR_STATE_EXECUTING:+            /* only happens when restarting execution after await() */+            goto resume_exec;+        case JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN:+            goto done;+        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_START:+            if (next->completion_type == GEN_MAGIC_NEXT) {+                goto exec_no_arg;+            } else {+                js_async_generator_complete(ctx, s);+            }+            break;+        case JS_ASYNC_GENERATOR_STATE_COMPLETED:+            if (next->completion_type == GEN_MAGIC_NEXT) {+                js_async_generator_resolve(ctx, s, JS_UNDEFINED, TRUE);+            } else if (next->completion_type == GEN_MAGIC_RETURN) {+                s->state = JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN;+                js_async_generator_completed_return(ctx, s, next->result);+                goto done;+            } else {+                js_async_generator_reject(ctx, s, next->result);+            }+            goto done;+        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD:+        case JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR:+            value = JS_DupValue(ctx, next->result);+            if (next->completion_type == GEN_MAGIC_THROW &&+                s->state == JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD) {+                JS_Throw(ctx, value);+                s->func_state.throw_flag = TRUE;+            } else {+                /* 'yield' returns a value. 'yield *' also returns a value+                   in case the 'throw' method is called */+                s->func_state.frame.cur_sp[-1] = value;+                s->func_state.frame.cur_sp[0] =+                    JS_NewInt32(ctx, next->completion_type);+                s->func_state.frame.cur_sp++;+            exec_no_arg:+                s->func_state.throw_flag = FALSE;+            }+            s->state = JS_ASYNC_GENERATOR_STATE_EXECUTING;+        resume_exec:+            func_ret = async_func_resume(ctx, &s->func_state);+            if (JS_IsException(func_ret)) {+                value = JS_GetException(ctx);+                js_async_generator_complete(ctx, s);+                js_async_generator_reject(ctx, s, value);+                JS_FreeValue(ctx, value);+            } else if (JS_VALUE_GET_TAG(func_ret) == JS_TAG_INT) {+                int func_ret_code;+                value = s->func_state.frame.cur_sp[-1];+                s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;+                func_ret_code = JS_VALUE_GET_INT(func_ret);+                switch(func_ret_code) {+                case FUNC_RET_YIELD:+                case FUNC_RET_YIELD_STAR:+                    if (func_ret_code == FUNC_RET_YIELD_STAR)+                        s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR;+                    else+                        s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD;+                    js_async_generator_resolve(ctx, s, value, FALSE);+                    JS_FreeValue(ctx, value);+                    break;+                case FUNC_RET_AWAIT:+                    js_async_generator_await(ctx, s, value);+                    JS_FreeValue(ctx, value);+                    goto done;+                default:+                    abort();+                }+            } else {+                assert(JS_IsUndefined(func_ret));+                /* end of function */+                value = s->func_state.frame.cur_sp[-1];+                s->func_state.frame.cur_sp[-1] = JS_UNDEFINED;+                js_async_generator_complete(ctx, s);+                js_async_generator_resolve(ctx, s, value, TRUE);+                JS_FreeValue(ctx, value);+            }+            break;+        default:+            abort();+        }+    }+ done: ;+}++static JSValue js_async_generator_resolve_function(JSContext *ctx,+                                                   JSValueConst this_obj,+                                                   int argc, JSValueConst *argv,+                                                   int magic, JSValue *func_data)+{+    BOOL is_reject = magic & 1;+    JSAsyncGeneratorData *s = JS_GetOpaque(func_data[0], JS_CLASS_ASYNC_GENERATOR);+    JSValueConst arg = argv[0];++    /* XXX: what if s == NULL */++    if (magic >= 2) {+        /* resume next case in AWAITING_RETURN state */+        assert(s->state == JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN ||+               s->state == JS_ASYNC_GENERATOR_STATE_COMPLETED);+        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;+        if (is_reject) {+            js_async_generator_reject(ctx, s, arg);+        } else {+            js_async_generator_resolve(ctx, s, arg, TRUE);+        }+    } else {+        /* restart function execution after await() */+        assert(s->state == JS_ASYNC_GENERATOR_STATE_EXECUTING);+        s->func_state.throw_flag = is_reject;+        if (is_reject) {+            JS_Throw(ctx, JS_DupValue(ctx, arg));+        } else {+            /* return value of await */+            s->func_state.frame.cur_sp[-1] = JS_DupValue(ctx, arg);+        }+        js_async_generator_resume_next(ctx, s);+    }+    return JS_UNDEFINED;+}++/* magic = GEN_MAGIC_x */+static JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv,+                                       int magic)+{+    JSAsyncGeneratorData *s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_GENERATOR);+    JSValue promise, resolving_funcs[2];+    JSAsyncGeneratorRequest *req;++    promise = JS_NewPromiseCapability(ctx, resolving_funcs);+    if (JS_IsException(promise))+        return JS_EXCEPTION;+    if (!s) {+        JSValue err, res2;+        JS_ThrowTypeError(ctx, "not an AsyncGenerator object");+        err = JS_GetException(ctx);+        res2 = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,+                       1, (JSValueConst *)&err);+        JS_FreeValue(ctx, err);+        JS_FreeValue(ctx, res2);+        JS_FreeValue(ctx, resolving_funcs[0]);+        JS_FreeValue(ctx, resolving_funcs[1]);+        return promise;+    }+    req = js_mallocz(ctx, sizeof(*req));+    if (!req)+        goto fail;+    req->completion_type = magic;+    req->result = JS_DupValue(ctx, argv[0]);+    req->promise = JS_DupValue(ctx, promise);+    req->resolving_funcs[0] = resolving_funcs[0];+    req->resolving_funcs[1] = resolving_funcs[1];+    list_add_tail(&req->link, &s->queue);+    if (s->state != JS_ASYNC_GENERATOR_STATE_EXECUTING) {+        js_async_generator_resume_next(ctx, s);+    }+    return promise;+ fail:+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    JS_FreeValue(ctx, promise);+    return JS_EXCEPTION;+}++static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj,+                                                JSValueConst this_obj,+                                                int argc, JSValueConst *argv,+                                                int flags)+{+    JSValue obj, func_ret;+    JSAsyncGeneratorData *s;++    s = js_mallocz(ctx, sizeof(*s));+    if (!s)+        return JS_EXCEPTION;+    s->state = JS_ASYNC_GENERATOR_STATE_SUSPENDED_START;+    init_list_head(&s->queue);+    if (async_func_init(ctx, &s->func_state, func_obj, this_obj, argc, argv)) {+        s->state = JS_ASYNC_GENERATOR_STATE_COMPLETED;+        goto fail;+    }++    /* execute the function up to 'OP_initial_yield' (no yield nor+       await are possible) */+    func_ret = async_func_resume(ctx, &s->func_state);+    if (JS_IsException(func_ret))+        goto fail;+    JS_FreeValue(ctx, func_ret);++    obj = js_create_from_ctor(ctx, func_obj, JS_CLASS_ASYNC_GENERATOR);+    if (JS_IsException(obj))+        goto fail;+    s->generator = JS_VALUE_GET_OBJ(obj);+    JS_SetOpaque(obj, s);+    return obj;+ fail:+    js_async_generator_free(ctx->rt, s);+    return JS_EXCEPTION;+}++/* JS parser */++enum {+    TOK_NUMBER = -128,+    TOK_STRING,+    TOK_TEMPLATE,+    TOK_IDENT,+    TOK_REGEXP,+    /* warning: order matters (see js_parse_assign_expr) */+    TOK_MUL_ASSIGN,+    TOK_DIV_ASSIGN,+    TOK_MOD_ASSIGN,+    TOK_PLUS_ASSIGN,+    TOK_MINUS_ASSIGN,+    TOK_SHL_ASSIGN,+    TOK_SAR_ASSIGN,+    TOK_SHR_ASSIGN,+    TOK_AND_ASSIGN,+    TOK_XOR_ASSIGN,+    TOK_OR_ASSIGN,+#ifdef CONFIG_BIGNUM+    TOK_MATH_POW_ASSIGN,+#endif+    TOK_POW_ASSIGN,+    TOK_LAND_ASSIGN,+    TOK_LOR_ASSIGN,+    TOK_DOUBLE_QUESTION_MARK_ASSIGN,+    TOK_DEC,+    TOK_INC,+    TOK_SHL,+    TOK_SAR,+    TOK_SHR,+    TOK_LT,+    TOK_LTE,+    TOK_GT,+    TOK_GTE,+    TOK_EQ,+    TOK_STRICT_EQ,+    TOK_NEQ,+    TOK_STRICT_NEQ,+    TOK_LAND,+    TOK_LOR,+#ifdef CONFIG_BIGNUM+    TOK_MATH_POW,+#endif+    TOK_POW,+    TOK_ARROW,+    TOK_ELLIPSIS,+    TOK_DOUBLE_QUESTION_MARK,+    TOK_QUESTION_MARK_DOT,+    TOK_ERROR,+    TOK_PRIVATE_NAME,+    TOK_EOF,+    /* keywords: WARNING: same order as atoms */+    TOK_NULL, /* must be first */+    TOK_FALSE,+    TOK_TRUE,+    TOK_IF,+    TOK_ELSE,+    TOK_RETURN,+    TOK_VAR,+    TOK_THIS,+    TOK_DELETE,+    TOK_VOID,+    TOK_TYPEOF,+    TOK_NEW,+    TOK_IN,+    TOK_INSTANCEOF,+    TOK_DO,+    TOK_WHILE,+    TOK_FOR,+    TOK_BREAK,+    TOK_CONTINUE,+    TOK_SWITCH,+    TOK_CASE,+    TOK_DEFAULT,+    TOK_THROW,+    TOK_TRY,+    TOK_CATCH,+    TOK_FINALLY,+    TOK_FUNCTION,+    TOK_DEBUGGER,+    TOK_WITH,+    /* FutureReservedWord */+    TOK_CLASS,+    TOK_CONST,+    TOK_ENUM,+    TOK_EXPORT,+    TOK_EXTENDS,+    TOK_IMPORT,+    TOK_SUPER,+    /* FutureReservedWords when parsing strict mode code */+    TOK_IMPLEMENTS,+    TOK_INTERFACE,+    TOK_LET,+    TOK_PACKAGE,+    TOK_PRIVATE,+    TOK_PROTECTED,+    TOK_PUBLIC,+    TOK_STATIC,+    TOK_YIELD,+    TOK_AWAIT, /* must be last */+    TOK_OF,     /* only used for js_parse_skip_parens_token() */+};++#define TOK_FIRST_KEYWORD   TOK_NULL+#define TOK_LAST_KEYWORD    TOK_AWAIT++/* unicode code points */+#define CP_NBSP 0x00a0+#define CP_BOM  0xfeff++#define CP_LS   0x2028+#define CP_PS   0x2029++typedef struct BlockEnv {+    struct BlockEnv *prev;+    JSAtom label_name; /* JS_ATOM_NULL if none */+    int label_break; /* -1 if none */+    int label_cont; /* -1 if none */+    int drop_count; /* number of stack elements to drop */+    int label_finally; /* -1 if none */+    int scope_level;+    int has_iterator;+} BlockEnv;++typedef struct JSGlobalVar {+    int cpool_idx; /* if >= 0, index in the constant pool for hoisted+                      function defintion*/+    uint8_t force_init : 1; /* force initialization to undefined */+    uint8_t is_lexical : 1; /* global let/const definition */+    uint8_t is_const   : 1; /* const definition */+    int scope_level;    /* scope of definition */+    JSAtom var_name;  /* variable name */+} JSGlobalVar;++typedef struct RelocEntry {+    struct RelocEntry *next;+    uint32_t addr; /* address to patch */+    int size;   /* address size: 1, 2 or 4 bytes */+} RelocEntry;++typedef struct JumpSlot {+    int op;+    int size;+    int pos;+    int label;+} JumpSlot;++typedef struct LabelSlot {+    int ref_count;+    int pos;    /* phase 1 address, -1 means not resolved yet */+    int pos2;   /* phase 2 address, -1 means not resolved yet */+    int addr;   /* phase 3 address, -1 means not resolved yet */+    RelocEntry *first_reloc;+} LabelSlot;++typedef struct LineNumberSlot {+    uint32_t pc;+    int line_num;+} LineNumberSlot;++typedef enum JSParseFunctionEnum {+    JS_PARSE_FUNC_STATEMENT,+    JS_PARSE_FUNC_VAR,+    JS_PARSE_FUNC_EXPR,+    JS_PARSE_FUNC_ARROW,+    JS_PARSE_FUNC_GETTER,+    JS_PARSE_FUNC_SETTER,+    JS_PARSE_FUNC_METHOD,+    JS_PARSE_FUNC_CLASS_CONSTRUCTOR,+    JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR,+} JSParseFunctionEnum;++typedef enum JSParseExportEnum {+    JS_PARSE_EXPORT_NONE,+    JS_PARSE_EXPORT_NAMED,+    JS_PARSE_EXPORT_DEFAULT,+} JSParseExportEnum;++typedef struct JSFunctionDef {+    JSContext *ctx;+    struct JSFunctionDef *parent;+    int parent_cpool_idx; /* index in the constant pool of the parent+                             or -1 if none */+    int parent_scope_level; /* scope level in parent at point of definition */+    struct list_head child_list; /* list of JSFunctionDef.link */+    struct list_head link;++    BOOL is_eval; /* TRUE if eval code */+    int eval_type; /* only valid if is_eval = TRUE */+    BOOL is_global_var; /* TRUE if variables are not defined locally:+                           eval global, eval module or non strict eval */+    BOOL is_func_expr; /* TRUE if function expression */+    BOOL has_home_object; /* TRUE if the home object is available */+    BOOL has_prototype; /* true if a prototype field is necessary */+    BOOL has_simple_parameter_list;+    BOOL has_parameter_expressions; /* if true, an argument scope is created */+    BOOL has_use_strict; /* to reject directive in special cases */+    BOOL has_eval_call; /* true if the function contains a call to eval() */+    BOOL has_arguments_binding; /* true if the 'arguments' binding is+                                   available in the function */+    BOOL has_this_binding; /* true if the 'this' and new.target binding are+                              available in the function */+    BOOL new_target_allowed; /* true if the 'new.target' does not+                                throw a syntax error */+    BOOL super_call_allowed; /* true if super() is allowed */+    BOOL super_allowed; /* true if super. or super[] is allowed */+    BOOL arguments_allowed; /* true if the 'arguments' identifier is allowed */+    BOOL is_derived_class_constructor;+    BOOL in_function_body;+    BOOL backtrace_barrier;+    JSFunctionKindEnum func_kind : 8;+    JSParseFunctionEnum func_type : 8;+    uint8_t js_mode; /* bitmap of JS_MODE_x */+    JSAtom func_name; /* JS_ATOM_NULL if no name */++    JSVarDef *vars;+    int var_size; /* allocated size for vars[] */+    int var_count;+    JSVarDef *args;+    int arg_size; /* allocated size for args[] */+    int arg_count; /* number of arguments */+    int defined_arg_count;+    int var_object_idx; /* -1 if none */+    int arg_var_object_idx; /* -1 if none (var object for the argument scope) */+    int arguments_var_idx; /* -1 if none */+    int arguments_arg_idx; /* argument variable definition in argument scope, +                              -1 if none */+    int func_var_idx; /* variable containing the current function (-1+                         if none, only used if is_func_expr is true) */+    int eval_ret_idx; /* variable containing the return value of the eval, -1 if none */+    int this_var_idx; /* variable containg the 'this' value, -1 if none */+    int new_target_var_idx; /* variable containg the 'new.target' value, -1 if none */+    int this_active_func_var_idx; /* variable containg the 'this.active_func' value, -1 if none */+    int home_object_var_idx;+    BOOL need_home_object;+    +    int scope_level;    /* index into fd->scopes if the current lexical scope */+    int scope_first;    /* index into vd->vars of first lexically scoped variable */+    int scope_size;     /* allocated size of fd->scopes array */+    int scope_count;    /* number of entries used in the fd->scopes array */+    JSVarScope *scopes;+    JSVarScope def_scope_array[4];+    int body_scope; /* scope of the body of the function or eval */++    int global_var_count;+    int global_var_size;+    JSGlobalVar *global_vars;++    DynBuf byte_code;+    int last_opcode_pos; /* -1 if no last opcode */+    int last_opcode_line_num;+    BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */+    +    LabelSlot *label_slots;+    int label_size; /* allocated size for label_slots[] */+    int label_count;+    BlockEnv *top_break; /* break/continue label stack */++    /* constant pool (strings, functions, numbers) */+    JSValue *cpool;+    int cpool_count;+    int cpool_size;++    /* list of variables in the closure */+    int closure_var_count;+    int closure_var_size;+    JSClosureVar *closure_var;++    JumpSlot *jump_slots;+    int jump_size;+    int jump_count;++    LineNumberSlot *line_number_slots;+    int line_number_size;+    int line_number_count;+    int line_number_last;+    int line_number_last_pc;++    /* pc2line table */+    JSAtom filename;+    int line_num;+    DynBuf pc2line;++    char *source;  /* raw source, utf-8 encoded */+    int source_len;++    JSModuleDef *module; /* != NULL when parsing a module */+} JSFunctionDef;++typedef struct JSToken {+    int val;+    int line_num;   /* line number of token start */+    const uint8_t *ptr;+    union {+        struct {+            JSValue str;+            int sep;+        } str;+        struct {+            JSValue val;+#ifdef CONFIG_BIGNUM+            slimb_t exponent; /* may be != 0 only if val is a float */+#endif+        } num;+        struct {+            JSAtom atom;+            BOOL has_escape;+            BOOL is_reserved;+        } ident;+        struct {+            JSValue body;+            JSValue flags;+        } regexp;+    } u;+} JSToken;++typedef struct JSParseState {+    JSContext *ctx;+    int last_line_num;  /* line number of last token */+    int line_num;       /* line number of current offset */+    const char *filename;+    JSToken token;+    BOOL got_lf; /* true if got line feed before the current token */+    const uint8_t *last_ptr;+    const uint8_t *buf_ptr;+    const uint8_t *buf_end;++    /* current function code */+    JSFunctionDef *cur_func;+    BOOL is_module; /* parsing a module */+    BOOL allow_html_comments;+    BOOL ext_json; /* true if accepting JSON superset */+} JSParseState;++typedef struct JSOpCode {+#ifdef DUMP_BYTECODE+    const char *name;+#endif+    uint8_t size; /* in bytes */+    /* the opcodes remove n_pop items from the top of the stack, then+       pushes n_push items */+    uint8_t n_pop;+    uint8_t n_push;+    uint8_t fmt;+} JSOpCode;++static const JSOpCode opcode_info[OP_COUNT + (OP_TEMP_END - OP_TEMP_START)] = {+#define FMT(f)+#ifdef DUMP_BYTECODE+#define DEF(id, size, n_pop, n_push, f) { #id, size, n_pop, n_push, OP_FMT_ ## f },+#else+#define DEF(id, size, n_pop, n_push, f) { size, n_pop, n_push, OP_FMT_ ## f },+#endif+#include "quickjs-opcode.h"+#undef DEF+#undef FMT+};++#if SHORT_OPCODES+/* After the final compilation pass, short opcodes are used. Their+   opcodes overlap with the temporary opcodes which cannot appear in+   the final bytecode. Their description is after the temporary+   opcodes in opcode_info[]. */+#define short_opcode_info(op)           \+    opcode_info[(op) >= OP_TEMP_START ? \+                (op) + (OP_TEMP_END - OP_TEMP_START) : (op)]+#else+#define short_opcode_info(op) opcode_info[op]+#endif++static __exception int next_token(JSParseState *s);++static void free_token(JSParseState *s, JSToken *token)+{+    switch(token->val) {+#ifdef CONFIG_BIGNUM+    case TOK_NUMBER:+        JS_FreeValue(s->ctx, token->u.num.val);+        break;+#endif+    case TOK_STRING:+    case TOK_TEMPLATE:+        JS_FreeValue(s->ctx, token->u.str.str);+        break;+    case TOK_REGEXP:+        JS_FreeValue(s->ctx, token->u.regexp.body);+        JS_FreeValue(s->ctx, token->u.regexp.flags);+        break;+    case TOK_IDENT:+    case TOK_PRIVATE_NAME:+        JS_FreeAtom(s->ctx, token->u.ident.atom);+        break;+    default:+        if (token->val >= TOK_FIRST_KEYWORD &&+            token->val <= TOK_LAST_KEYWORD) {+            JS_FreeAtom(s->ctx, token->u.ident.atom);+        }+        break;+    }+}++static void __attribute((unused)) dump_token(JSParseState *s,+                                             const JSToken *token)+{+    switch(token->val) {+    case TOK_NUMBER:+        {+            double d;+            JS_ToFloat64(s->ctx, &d, token->u.num.val);  /* no exception possible */+            printf("number: %.14g\n", d);+        }+        break;+    case TOK_IDENT:+    dump_atom:+        {+            char buf[ATOM_GET_STR_BUF_SIZE];+            printf("ident: '%s'\n",+                   JS_AtomGetStr(s->ctx, buf, sizeof(buf), token->u.ident.atom));+        }+        break;+    case TOK_STRING:+        {+            const char *str;+            /* XXX: quote the string */+            str = JS_ToCString(s->ctx, token->u.str.str);+            printf("string: '%s'\n", str);+            JS_FreeCString(s->ctx, str);+        }+        break;+    case TOK_TEMPLATE:+        {+            const char *str;+            str = JS_ToCString(s->ctx, token->u.str.str);+            printf("template: `%s`\n", str);+            JS_FreeCString(s->ctx, str);+        }+        break;+    case TOK_REGEXP:+        {+            const char *str, *str2;+            str = JS_ToCString(s->ctx, token->u.regexp.body);+            str2 = JS_ToCString(s->ctx, token->u.regexp.flags);+            printf("regexp: '%s' '%s'\n", str, str2);+            JS_FreeCString(s->ctx, str);+            JS_FreeCString(s->ctx, str2);+        }+        break;+    case TOK_EOF:+        printf("eof\n");+        break;+    default:+        if (s->token.val >= TOK_NULL && s->token.val <= TOK_LAST_KEYWORD) {+            goto dump_atom;+        } else if (s->token.val >= 256) {+            printf("token: %d\n", token->val);+        } else {+            printf("token: '%c'\n", token->val);+        }+        break;+    }+}++int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const char *fmt, ...)+{+    JSContext *ctx = s->ctx;+    va_list ap;+    int backtrace_flags;+    +    va_start(ap, fmt);+    JS_ThrowError2(ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);+    va_end(ap);+    backtrace_flags = 0;+    if (s->cur_func && s->cur_func->backtrace_barrier)+        backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;+    build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,+                    backtrace_flags);+    return -1;+}++static int js_parse_expect(JSParseState *s, int tok)+{+    if (s->token.val != tok) {+        /* XXX: dump token correctly in all cases */+        return js_parse_error(s, "expecting '%c'", tok);+    }+    return next_token(s);+}++static int js_parse_expect_semi(JSParseState *s)+{+    if (s->token.val != ';') {+        /* automatic insertion of ';' */+        if (s->token.val == TOK_EOF || s->token.val == '}' || s->got_lf) {+            return 0;+        }+        return js_parse_error(s, "expecting '%c'", ';');+    }+    return next_token(s);+}++static int js_parse_error_reserved_identifier(JSParseState *s)+{+    char buf1[ATOM_GET_STR_BUF_SIZE];+    return js_parse_error(s, "'%s' is a reserved identifier",+                          JS_AtomGetStr(s->ctx, buf1, sizeof(buf1),+                                        s->token.u.ident.atom));+}++static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)+{+    uint32_t c;+    StringBuffer b_s, *b = &b_s;++    /* p points to the first byte of the template part */+    if (string_buffer_init(s->ctx, b, 32))+        goto fail;+    for(;;) {+        if (p >= s->buf_end)+            goto unexpected_eof;+        c = *p++;+        if (c == '`') {+            /* template end part */+            break;+        }+        if (c == '$' && *p == '{') {+            /* template start or middle part */+            p++;+            break;+        }+        if (c == '\\') {+            if (string_buffer_putc8(b, c))+                goto fail;+            if (p >= s->buf_end)+                goto unexpected_eof;+            c = *p++;+        }+        /* newline sequences are normalized as single '\n' bytes */+        if (c == '\r') {+            if (*p == '\n')+                p++;+            c = '\n';+        }+        if (c == '\n') {+            s->line_num++;+        } else if (c >= 0x80) {+            const uint8_t *p_next;+            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);+            if (c > 0x10FFFF) {+                js_parse_error(s, "invalid UTF-8 sequence");+                goto fail;+            }+            p = p_next;+        }+        if (string_buffer_putc(b, c))+            goto fail;+    }+    s->token.val = TOK_TEMPLATE;+    s->token.u.str.sep = c;+    s->token.u.str.str = string_buffer_end(b);+    s->buf_ptr = p;+    return 0;++ unexpected_eof:+    js_parse_error(s, "unexpected end of string");+ fail:+    string_buffer_free(b);+    return -1;+}++static __exception int js_parse_string(JSParseState *s, int sep,+                                       BOOL do_throw, const uint8_t *p,+                                       JSToken *token, const uint8_t **pp)+{+    int ret;+    uint32_t c;+    StringBuffer b_s, *b = &b_s;++    /* string */+    if (string_buffer_init(s->ctx, b, 32))+        goto fail;+    for(;;) {+        if (p >= s->buf_end)+            goto invalid_char;+        c = *p;+        if (c < 0x20) {+            if (!s->cur_func) {+                if (do_throw)+                    js_parse_error(s, "invalid character in a JSON string");+                goto fail;+            }+            if (sep == '`') {+                if (c == '\r') {+                    if (p[1] == '\n')+                        p++;+                    c = '\n';+                }+                /* do not update s->line_num */+            } else if (c == '\n' || c == '\r')+                goto invalid_char;+        }+        p++;+        if (c == sep)+            break;+        if (c == '$' && *p == '{' && sep == '`') {+            /* template start or middle part */+            p++;+            break;+        }+        if (c == '\\') {+            c = *p;+            /* XXX: need a specific JSON case to avoid+               accepting invalid escapes */+            switch(c) {+            case '\0':+                if (p >= s->buf_end)+                    goto invalid_char;+                p++;+                break;+            case '\'':+            case '\"':+            case '\\':+                p++;+                break;+            case '\r':  /* accept DOS and MAC newline sequences */+                if (p[1] == '\n') {+                    p++;+                }+                /* fall thru */+            case '\n':+                /* ignore escaped newline sequence */+                p++;+                if (sep != '`')+                    s->line_num++;+                continue;+            default:+                if (c >= '0' && c <= '9') {+                    if (!s->cur_func)+                        goto invalid_escape; /* JSON case */+                    if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')+                        goto parse_escape;+                    if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {+                        p++;+                        c = '\0';+                    } else {+                        if (c >= '8' || sep == '`') {+                            /* Note: according to ES2021, \8 and \9 are not+                               accepted in strict mode or in templates. */+                            goto invalid_escape;+                        } else {+                            if (do_throw)+                                js_parse_error(s, "octal escape sequences are not allowed in strict mode");+                        }+                        goto fail;+                    }+                } else if (c >= 0x80) {+                    const uint8_t *p_next;+                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);+                    if (c > 0x10FFFF) {+                        goto invalid_utf8;+                    }+                    p = p_next;+                    /* LS or PS are skipped */+                    if (c == CP_LS || c == CP_PS)+                        continue;+                } else {+                parse_escape:+                    ret = lre_parse_escape(&p, TRUE);+                    if (ret == -1) {+                    invalid_escape:+                        if (do_throw)+                            js_parse_error(s, "malformed escape sequence in string literal");+                        goto fail;+                    } else if (ret < 0) {+                        /* ignore the '\' (could output a warning) */+                        p++;+                    } else {+                        c = ret;+                    }+                }+                break;+            }+        } else if (c >= 0x80) {+            const uint8_t *p_next;+            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);+            if (c > 0x10FFFF)+                goto invalid_utf8;+            p = p_next;+        }+        if (string_buffer_putc(b, c))+            goto fail;+    }+    token->val = TOK_STRING;+    token->u.str.sep = c;+    token->u.str.str = string_buffer_end(b);+    *pp = p;+    return 0;++ invalid_utf8:+    if (do_throw)+        js_parse_error(s, "invalid UTF-8 sequence");+    goto fail;+ invalid_char:+    if (do_throw)+        js_parse_error(s, "unexpected end of string");+ fail:+    string_buffer_free(b);+    return -1;+}++static inline BOOL token_is_pseudo_keyword(JSParseState *s, JSAtom atom) {+    return s->token.val == TOK_IDENT && s->token.u.ident.atom == atom &&+        !s->token.u.ident.has_escape;+}++static __exception int js_parse_regexp(JSParseState *s)+{+    const uint8_t *p;+    BOOL in_class;+    StringBuffer b_s, *b = &b_s;+    StringBuffer b2_s, *b2 = &b2_s;+    uint32_t c;++    p = s->buf_ptr;+    p++;+    in_class = FALSE;+    if (string_buffer_init(s->ctx, b, 32))+        return -1;+    if (string_buffer_init(s->ctx, b2, 1))+        goto fail;+    for(;;) {+        if (p >= s->buf_end) {+        eof_error:+            js_parse_error(s, "unexpected end of regexp");+            goto fail;+        }+        c = *p++;+        if (c == '\n' || c == '\r') {+            goto eol_error;+        } else if (c == '/') {+            if (!in_class)+                break;+        } else if (c == '[') {+            in_class = TRUE;+        } else if (c == ']') {+            /* XXX: incorrect as the first character in a class */+            in_class = FALSE;+        } else if (c == '\\') {+            if (string_buffer_putc8(b, c))+                goto fail;+            c = *p++;+            if (c == '\n' || c == '\r')+                goto eol_error;+            else if (c == '\0' && p >= s->buf_end)+                goto eof_error;+            else if (c >= 0x80) {+                const uint8_t *p_next;+                c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);+                if (c > 0x10FFFF) {+                    goto invalid_utf8;+                }+                p = p_next;+                if (c == CP_LS || c == CP_PS)+                    goto eol_error;+            }+        } else if (c >= 0x80) {+            const uint8_t *p_next;+            c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);+            if (c > 0x10FFFF) {+            invalid_utf8:+                js_parse_error(s, "invalid UTF-8 sequence");+                goto fail;+            }+            p = p_next;+            /* LS or PS are considered as line terminator */+            if (c == CP_LS || c == CP_PS) {+            eol_error:+                js_parse_error(s, "unexpected line terminator in regexp");+                goto fail;+            }+        }+        if (string_buffer_putc(b, c))+            goto fail;+    }++    /* flags */+    for(;;) {+        const uint8_t *p_next = p;+        c = *p_next++;+        if (c >= 0x80) {+            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p_next);+            if (c > 0x10FFFF) {+                goto invalid_utf8;+            }+        }+        if (!lre_js_is_ident_next(c))+            break;+        if (string_buffer_putc(b2, c))+            goto fail;+        p = p_next;+    }++    s->token.val = TOK_REGEXP;+    s->token.u.regexp.body = string_buffer_end(b);+    s->token.u.regexp.flags = string_buffer_end(b2);+    s->buf_ptr = p;+    return 0;+ fail:+    string_buffer_free(b);+    string_buffer_free(b2);+    return -1;+}++static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,+                                     char *static_buf)+{+    char *buf, *new_buf;+    size_t size, new_size;+    +    buf = *pbuf;+    size = *psize;+    if (size >= (SIZE_MAX / 3) * 2)+        new_size = SIZE_MAX;+    else+        new_size = size + (size >> 1);+    if (buf == static_buf) {+        new_buf = js_malloc(ctx, new_size);+        if (!new_buf)+            return -1;+        memcpy(new_buf, buf, size);+    } else {+        new_buf = js_realloc(ctx, buf, new_size);+        if (!new_buf)+            return -1;+    }+    *pbuf = new_buf;+    *psize = new_size;+    return 0;+}++/* 'c' is the first character. Return JS_ATOM_NULL in case of error */+static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,+                          BOOL *pident_has_escape, int c, BOOL is_private)+{+    const uint8_t *p, *p1;+    char ident_buf[128], *buf;+    size_t ident_size, ident_pos;+    JSAtom atom;+    +    p = *pp;+    buf = ident_buf;+    ident_size = sizeof(ident_buf);+    ident_pos = 0;+    if (is_private)+        buf[ident_pos++] = '#';+    for(;;) {+        p1 = p;+        +        if (c < 128) {+            buf[ident_pos++] = c;+        } else {+            ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c);+        }+        c = *p1++;+        if (c == '\\' && *p1 == 'u') {+            c = lre_parse_escape(&p1, TRUE);+            *pident_has_escape = TRUE;+        } else if (c >= 128) {+            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);+        }+        if (!lre_js_is_ident_next(c))+            break;+        p = p1;+        if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {+            if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {+                atom = JS_ATOM_NULL;+                goto done;+            }+        }+    }+    atom = JS_NewAtomLen(s->ctx, buf, ident_pos);+ done:+    if (unlikely(buf != ident_buf))+        js_free(s->ctx, buf);+    *pp = p;+    return atom;+}+++static __exception int next_token(JSParseState *s)+{+    const uint8_t *p;+    int c;+    BOOL ident_has_escape;+    JSAtom atom;+    +    if (js_check_stack_overflow(s->ctx->rt, 0)) {+        return js_parse_error(s, "stack overflow");+    }+    +    free_token(s, &s->token);++    p = s->last_ptr = s->buf_ptr;+    s->got_lf = FALSE;+    s->last_line_num = s->token.line_num;+ redo:+    s->token.line_num = s->line_num;+    s->token.ptr = p;+    c = *p;+    switch(c) {+    case 0:+        if (p >= s->buf_end) {+            s->token.val = TOK_EOF;+        } else {+            goto def_token;+        }+        break;+    case '`':+        if (js_parse_template_part(s, p + 1))+            goto fail;+        p = s->buf_ptr;+        break;+    case '\'':+    case '\"':+        if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))+            goto fail;+        break;+    case '\r':  /* accept DOS and MAC newline sequences */+        if (p[1] == '\n') {+            p++;+        }+        /* fall thru */+    case '\n':+        p++;+    line_terminator:+        s->got_lf = TRUE;+        s->line_num++;+        goto redo;+    case '\f':+    case '\v':+    case ' ':+    case '\t':+        p++;+        goto redo;+    case '/':+        if (p[1] == '*') {+            /* comment */+            p += 2;+            for(;;) {+                if (*p == '\0' && p >= s->buf_end) {+                    js_parse_error(s, "unexpected end of comment");+                    goto fail;+                }+                if (p[0] == '*' && p[1] == '/') {+                    p += 2;+                    break;+                }+                if (*p == '\n') {+                    s->line_num++;+                    s->got_lf = TRUE; /* considered as LF for ASI */+                    p++;+                } else if (*p == '\r') {+                    s->got_lf = TRUE; /* considered as LF for ASI */+                    p++;+                } else if (*p >= 0x80) {+                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+                    if (c == CP_LS || c == CP_PS) {+                        s->got_lf = TRUE; /* considered as LF for ASI */+                    } else if (c == -1) {+                        p++; /* skip invalid UTF-8 */+                    }+                } else {+                    p++;+                }+            }+            goto redo;+        } else if (p[1] == '/') {+            /* line comment */+            p += 2;+        skip_line_comment:+            for(;;) {+                if (*p == '\0' && p >= s->buf_end)+                    break;+                if (*p == '\r' || *p == '\n')+                    break;+                if (*p >= 0x80) {+                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+                    /* LS or PS are considered as line terminator */+                    if (c == CP_LS || c == CP_PS) {+                        break;+                    } else if (c == -1) {+                        p++; /* skip invalid UTF-8 */+                    }+                } else {+                    p++;+                }+            }+            goto redo;+        } else if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_DIV_ASSIGN;+        } else {+            p++;+            s->token.val = c;+        }+        break;+    case '\\':+        if (p[1] == 'u') {+            const uint8_t *p1 = p + 1;+            int c1 = lre_parse_escape(&p1, TRUE);+            if (c1 >= 0 && lre_js_is_ident_first(c1)) {+                c = c1;+                p = p1;+                ident_has_escape = TRUE;+                goto has_ident;+            } else {+                /* XXX: syntax error? */+            }+        }+        goto def_token;+    case 'a': case 'b': case 'c': case 'd':+    case 'e': case 'f': case 'g': case 'h':+    case 'i': case 'j': case 'k': case 'l':+    case 'm': case 'n': case 'o': case 'p':+    case 'q': case 'r': case 's': case 't':+    case 'u': case 'v': case 'w': case 'x':+    case 'y': case 'z': +    case 'A': case 'B': case 'C': case 'D':+    case 'E': case 'F': case 'G': case 'H':+    case 'I': case 'J': case 'K': case 'L':+    case 'M': case 'N': case 'O': case 'P':+    case 'Q': case 'R': case 'S': case 'T':+    case 'U': case 'V': case 'W': case 'X':+    case 'Y': case 'Z': +    case '_':+    case '$':+        /* identifier */+        p++;+        ident_has_escape = FALSE;+    has_ident:+        atom = parse_ident(s, &p, &ident_has_escape, c, FALSE);+        if (atom == JS_ATOM_NULL)+            goto fail;+        s->token.u.ident.atom = atom;+        s->token.u.ident.has_escape = ident_has_escape;+        s->token.u.ident.is_reserved = FALSE;+        if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||+            (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD &&+             (s->cur_func->js_mode & JS_MODE_STRICT)) ||+            (s->token.u.ident.atom == JS_ATOM_yield &&+             ((s->cur_func->func_kind & JS_FUNC_GENERATOR) ||+              (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&+               !s->cur_func->in_function_body && s->cur_func->parent &&+               (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) ||+            (s->token.u.ident.atom == JS_ATOM_await &&+             (s->is_module ||+              (((s->cur_func->func_kind & JS_FUNC_ASYNC) ||+                (s->cur_func->func_type == JS_PARSE_FUNC_ARROW &&+                 !s->cur_func->in_function_body && s->cur_func->parent &&+                 (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) {+                  if (ident_has_escape) {+                      s->token.u.ident.is_reserved = TRUE;+                      s->token.val = TOK_IDENT;+                  } else {+                      /* The keywords atoms are pre allocated */+                      s->token.val = s->token.u.ident.atom - 1 + TOK_FIRST_KEYWORD;+                  }+        } else {+            s->token.val = TOK_IDENT;+        }+        break;+    case '#':+        /* private name */+        {+            const uint8_t *p1;+            p++;+            p1 = p;+            c = *p1++;+            if (c == '\\' && *p1 == 'u') {+                c = lre_parse_escape(&p1, TRUE);+            } else if (c >= 128) {+                c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);+            }+            if (!lre_js_is_ident_first(c)) {+                js_parse_error(s, "invalid first character of private name");+                goto fail;+            }+            p = p1;+            ident_has_escape = FALSE; /* not used */+            atom = parse_ident(s, &p, &ident_has_escape, c, TRUE);+            if (atom == JS_ATOM_NULL)+                goto fail;+            s->token.u.ident.atom = atom;+            s->token.val = TOK_PRIVATE_NAME;+        }+        break;+    case '.':+        if (p[1] == '.' && p[2] == '.') {+            p += 3;+            s->token.val = TOK_ELLIPSIS;+            break;+        }+        if (p[1] >= '0' && p[1] <= '9') {+            goto parse_number;+        } else {+            goto def_token;+        }+        break;+    case '0':+        /* in strict mode, octal literals are not accepted */+        if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) {+            js_parse_error(s, "octal literals are deprecated in strict mode");+            goto fail;+        }+        goto parse_number;+    case '1': case '2': case '3': case '4':+    case '5': case '6': case '7': case '8':+    case '9': +        /* number */+    parse_number:+        {+            JSValue ret;+            const uint8_t *p1;+            int flags, radix;+            flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL |+                ATOD_ACCEPT_UNDERSCORES;+#ifdef CONFIG_BIGNUM+            flags |= ATOD_ACCEPT_SUFFIX;+            if (s->cur_func->js_mode & JS_MODE_MATH) {+                flags |= ATOD_MODE_BIGINT;+                if (s->cur_func->js_mode & JS_MODE_MATH)+                    flags |= ATOD_TYPE_BIG_FLOAT;+            }+#endif+            radix = 0;+#ifdef CONFIG_BIGNUM+            s->token.u.num.exponent = 0;+            ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix,+                           flags, &s->token.u.num.exponent);+#else+            ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,+                          flags);+#endif+            if (JS_IsException(ret))+                goto fail;+            /* reject `10instanceof Number` */+            if (JS_VALUE_IS_NAN(ret) ||+                lre_js_is_ident_next(unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1))) {+                JS_FreeValue(s->ctx, ret);+                js_parse_error(s, "invalid number literal");+                goto fail;+            }+            s->token.val = TOK_NUMBER;+            s->token.u.num.val = ret;+        }+        break;+    case '*':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_MUL_ASSIGN;+        } else if (p[1] == '*') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_POW_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_POW;+            }+        } else {+            goto def_token;+        }+        break;+    case '%':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_MOD_ASSIGN;+        } else {+            goto def_token;+        }+        break;+    case '+':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_PLUS_ASSIGN;+        } else if (p[1] == '+') {+            p += 2;+            s->token.val = TOK_INC;+        } else {+            goto def_token;+        }+        break;+    case '-':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_MINUS_ASSIGN;+        } else if (p[1] == '-') {+            if (s->allow_html_comments &&+                p[2] == '>' && s->last_line_num != s->line_num) {+                /* Annex B: `-->` at beginning of line is an html comment end.+                   It extends to the end of the line.+                 */+                goto skip_line_comment;+            }+            p += 2;+            s->token.val = TOK_DEC;+        } else {+            goto def_token;+        }+        break;+    case '<':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_LTE;+        } else if (p[1] == '<') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_SHL_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_SHL;+            }+        } else if (s->allow_html_comments &&+                   p[1] == '!' && p[2] == '-' && p[3] == '-') {+            /* Annex B: handle `<!--` single line html comments */+            goto skip_line_comment;+        } else {+            goto def_token;+        }+        break;+    case '>':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_GTE;+        } else if (p[1] == '>') {+            if (p[2] == '>') {+                if (p[3] == '=') {+                    p += 4;+                    s->token.val = TOK_SHR_ASSIGN;+                } else {+                    p += 3;+                    s->token.val = TOK_SHR;+                }+            } else if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_SAR_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_SAR;+            }+        } else {+            goto def_token;+        }+        break;+    case '=':+        if (p[1] == '=') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_STRICT_EQ;+            } else {+                p += 2;+                s->token.val = TOK_EQ;+            }+        } else if (p[1] == '>') {+            p += 2;+            s->token.val = TOK_ARROW;+        } else {+            goto def_token;+        }+        break;+    case '!':+        if (p[1] == '=') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_STRICT_NEQ;+            } else {+                p += 2;+                s->token.val = TOK_NEQ;+            }+        } else {+            goto def_token;+        }+        break;+    case '&':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_AND_ASSIGN;+        } else if (p[1] == '&') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_LAND_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_LAND;+            }+        } else {+            goto def_token;+        }+        break;+#ifdef CONFIG_BIGNUM+        /* in math mode, '^' is the power operator. '^^' is always the+           xor operator and '**' is always the power operator */+    case '^':+        if (p[1] == '=') {+            p += 2;+            if (s->cur_func->js_mode & JS_MODE_MATH)+                s->token.val = TOK_MATH_POW_ASSIGN;+            else+                s->token.val = TOK_XOR_ASSIGN;+        } else if (p[1] == '^') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_XOR_ASSIGN;+            } else {+                p += 2;+                s->token.val = '^';+            }+        } else {+            p++;+            if (s->cur_func->js_mode & JS_MODE_MATH)+                s->token.val = TOK_MATH_POW;+            else+                s->token.val = '^';+        }+        break;+#else+    case '^':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_XOR_ASSIGN;+        } else {+            goto def_token;+        }+        break;+#endif+    case '|':+        if (p[1] == '=') {+            p += 2;+            s->token.val = TOK_OR_ASSIGN;+        } else if (p[1] == '|') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_LOR_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_LOR;+            }+        } else {+            goto def_token;+        }+        break;+    case '?':+        if (p[1] == '?') {+            if (p[2] == '=') {+                p += 3;+                s->token.val = TOK_DOUBLE_QUESTION_MARK_ASSIGN;+            } else {+                p += 2;+                s->token.val = TOK_DOUBLE_QUESTION_MARK;+            }+        } else if (p[1] == '.' && !(p[2] >= '0' && p[2] <= '9')) {+            p += 2;+            s->token.val = TOK_QUESTION_MARK_DOT;+        } else {+            goto def_token;+        }+        break;+    default:+        if (c >= 128) {+            /* unicode value */+            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+            switch(c) {+            case CP_PS:+            case CP_LS:+                /* XXX: should avoid incrementing line_number, but+                   needed to handle HTML comments */+                goto line_terminator; +            default:+                if (lre_is_space(c)) {+                    goto redo;+                } else if (lre_js_is_ident_first(c)) {+                    ident_has_escape = FALSE;+                    goto has_ident;+                } else {+                    js_parse_error(s, "unexpected character");+                    goto fail;+                }+            }+        }+    def_token:+        s->token.val = c;+        p++;+        break;+    }+    s->buf_ptr = p;++    //    dump_token(s, &s->token);+    return 0;++ fail:+    s->token.val = TOK_ERROR;+    return -1;+}++/* 'c' is the first character. Return JS_ATOM_NULL in case of error */+static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)+{+    const uint8_t *p;+    char ident_buf[128], *buf;+    size_t ident_size, ident_pos;+    JSAtom atom;+    +    p = *pp;+    buf = ident_buf;+    ident_size = sizeof(ident_buf);+    ident_pos = 0;+    for(;;) {+        buf[ident_pos++] = c;+        c = *p;+        if (c >= 128 ||+            !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1))+            break;+        p++;+        if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {+            if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {+                atom = JS_ATOM_NULL;+                goto done;+            }+        }+    }+    atom = JS_NewAtomLen(s->ctx, buf, ident_pos);+ done:+    if (unlikely(buf != ident_buf))+        js_free(s->ctx, buf);+    *pp = p;+    return atom;+}++static __exception int json_next_token(JSParseState *s)+{+    const uint8_t *p;+    int c;+    JSAtom atom;+    +    if (js_check_stack_overflow(s->ctx->rt, 0)) {+        return js_parse_error(s, "stack overflow");+    }+    +    free_token(s, &s->token);++    p = s->last_ptr = s->buf_ptr;+    s->last_line_num = s->token.line_num;+ redo:+    s->token.line_num = s->line_num;+    s->token.ptr = p;+    c = *p;+    switch(c) {+    case 0:+        if (p >= s->buf_end) {+            s->token.val = TOK_EOF;+        } else {+            goto def_token;+        }+        break;+    case '\'':+        if (!s->ext_json) {+            /* JSON does not accept single quoted strings */+            goto def_token;+        }+        /* fall through */+    case '\"':+        if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))+            goto fail;+        break;+    case '\r':  /* accept DOS and MAC newline sequences */+        if (p[1] == '\n') {+            p++;+        }+        /* fall thru */+    case '\n':+        p++;+        s->line_num++;+        goto redo;+    case '\f':+    case '\v':+        if (!s->ext_json) {+            /* JSONWhitespace does not match <VT>, nor <FF> */+            goto def_token;+        }+        /* fall through */+    case ' ':+    case '\t':+        p++;+        goto redo;+    case '/':+        if (!s->ext_json) {+            /* JSON does not accept comments */+            goto def_token;+        }+        if (p[1] == '*') {+            /* comment */+            p += 2;+            for(;;) {+                if (*p == '\0' && p >= s->buf_end) {+                    js_parse_error(s, "unexpected end of comment");+                    goto fail;+                }+                if (p[0] == '*' && p[1] == '/') {+                    p += 2;+                    break;+                }+                if (*p == '\n') {+                    s->line_num++;+                    p++;+                } else if (*p == '\r') {+                    p++;+                } else if (*p >= 0x80) {+                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+                    if (c == -1) {+                        p++; /* skip invalid UTF-8 */+                    }+                } else {+                    p++;+                }+            }+            goto redo;+        } else if (p[1] == '/') {+            /* line comment */+            p += 2;+            for(;;) {+                if (*p == '\0' && p >= s->buf_end)+                    break;+                if (*p == '\r' || *p == '\n')+                    break;+                if (*p >= 0x80) {+                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+                    /* LS or PS are considered as line terminator */+                    if (c == CP_LS || c == CP_PS) {+                        break;+                    } else if (c == -1) {+                        p++; /* skip invalid UTF-8 */+                    }+                } else {+                    p++;+                }+            }+            goto redo;+        } else {+            goto def_token;+        }+        break;+    case 'a': case 'b': case 'c': case 'd':+    case 'e': case 'f': case 'g': case 'h':+    case 'i': case 'j': case 'k': case 'l':+    case 'm': case 'n': case 'o': case 'p':+    case 'q': case 'r': case 's': case 't':+    case 'u': case 'v': case 'w': case 'x':+    case 'y': case 'z': +    case 'A': case 'B': case 'C': case 'D':+    case 'E': case 'F': case 'G': case 'H':+    case 'I': case 'J': case 'K': case 'L':+    case 'M': case 'N': case 'O': case 'P':+    case 'Q': case 'R': case 'S': case 'T':+    case 'U': case 'V': case 'W': case 'X':+    case 'Y': case 'Z': +    case '_':+    case '$':+        /* identifier : only pure ascii characters are accepted */+        p++;+        atom = json_parse_ident(s, &p, c);+        if (atom == JS_ATOM_NULL)+            goto fail;+        s->token.u.ident.atom = atom;+        s->token.u.ident.has_escape = FALSE;+        s->token.u.ident.is_reserved = FALSE;+        s->token.val = TOK_IDENT;+        break;+    case '+':+        if (!s->ext_json || !is_digit(p[1]))+            goto def_token;+        goto parse_number;+    case '0':+        if (is_digit(p[1]))+            goto def_token;+        goto parse_number;+    case '-':+        if (!is_digit(p[1]))+            goto def_token;+        goto parse_number;+    case '1': case '2': case '3': case '4':+    case '5': case '6': case '7': case '8':+    case '9': +        /* number */+    parse_number:+        {+            JSValue ret;+            int flags, radix;+            if (!s->ext_json) {+                flags = 0;+                radix = 10;+            } else {+                flags = ATOD_ACCEPT_BIN_OCT;+                radix = 0;+            }+            ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,+                          flags);+            if (JS_IsException(ret))+                goto fail;+            s->token.val = TOK_NUMBER;+            s->token.u.num.val = ret;+        }+        break;+    default:+        if (c >= 128) {+            js_parse_error(s, "unexpected character");+            goto fail;+        }+    def_token:+        s->token.val = c;+        p++;+        break;+    }+    s->buf_ptr = p;++    //    dump_token(s, &s->token);+    return 0;++ fail:+    s->token.val = TOK_ERROR;+    return -1;+}++/* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is+   only set if TOK_IMPORT is returned */+/* XXX: handle all unicode cases */+static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator)+{+    const uint8_t *p;+    uint32_t c;+    +    /* skip spaces and comments */+    p = *pp;+    for (;;) {+        switch(c = *p++) {+        case '\r':+        case '\n':+            if (no_line_terminator)+                return '\n';+            continue;+        case ' ':+        case '\t':+        case '\v':+        case '\f':+            continue;+        case '/':+            if (*p == '/') {+                if (no_line_terminator)+                    return '\n';+                while (*p && *p != '\r' && *p != '\n')+                    p++;+                continue;+            }+            if (*p == '*') {+                while (*++p) {+                    if ((*p == '\r' || *p == '\n') && no_line_terminator)+                        return '\n';+                    if (*p == '*' && p[1] == '/') {+                        p += 2;+                        break;+                    }+                }+                continue;+            }+            break;+        case '=':+            if (*p == '>')+                return TOK_ARROW;+            break;+        default:+            if (lre_js_is_ident_first(c)) {+                if (c == 'i') {+                    if (p[0] == 'n' && !lre_js_is_ident_next(p[1])) {+                        return TOK_IN;+                    }+                    if (p[0] == 'm' && p[1] == 'p' && p[2] == 'o' &&+                        p[3] == 'r' && p[4] == 't' &&+                        !lre_js_is_ident_next(p[5])) {+                        *pp = p + 5;+                        return TOK_IMPORT;+                    }+                } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) {+                    return TOK_OF;+                } else if (c == 'e' &&+                           p[0] == 'x' && p[1] == 'p' && p[2] == 'o' &&+                           p[3] == 'r' && p[4] == 't' &&+                           !lre_js_is_ident_next(p[5])) {+                    *pp = p + 5;+                    return TOK_EXPORT;+                } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' &&+                         p[2] == 'c' && p[3] == 't' && p[4] == 'i' &&+                         p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) {+                    return TOK_FUNCTION;+                }+                return TOK_IDENT;+            }+            break;+        }+        return c;+    }+}++static int peek_token(JSParseState *s, BOOL no_line_terminator)+{+    const uint8_t *p = s->buf_ptr;+    return simple_next_token(&p, no_line_terminator);+}++/* return true if 'input' contains the source of a module+   (heuristic). 'input' must be a zero terminated.++   Heuristic: skip comments and expect 'import' keyword not followed+   by '(' or '.' or export keyword.+*/+BOOL JS_DetectModule(const char *input, size_t input_len)+{+    const uint8_t *p = (const uint8_t *)input;+    int tok;+    switch(simple_next_token(&p, FALSE)) {+    case TOK_IMPORT:+        tok = simple_next_token(&p, FALSE);+        return (tok != '.' && tok != '(');+    case TOK_EXPORT:+        return TRUE;+    default:+        return FALSE;+    }+}++static inline int get_prev_opcode(JSFunctionDef *fd) {+    if (fd->last_opcode_pos < 0)+        return OP_invalid;+    else+        return fd->byte_code.buf[fd->last_opcode_pos];+}++static BOOL js_is_live_code(JSParseState *s) {+    switch (get_prev_opcode(s->cur_func)) {+    case OP_tail_call:+    case OP_tail_call_method:+    case OP_return:+    case OP_return_undef:+    case OP_return_async:+    case OP_throw:+    case OP_throw_error:+    case OP_goto:+#if SHORT_OPCODES+    case OP_goto8:+    case OP_goto16:+#endif+    case OP_ret:+        return FALSE;+    default:+        return TRUE;+    }+}++static void emit_u8(JSParseState *s, uint8_t val)+{+    dbuf_putc(&s->cur_func->byte_code, val);+}++static void emit_u16(JSParseState *s, uint16_t val)+{+    dbuf_put_u16(&s->cur_func->byte_code, val);+}++static void emit_u32(JSParseState *s, uint32_t val)+{+    dbuf_put_u32(&s->cur_func->byte_code, val);+}++static void emit_op(JSParseState *s, uint8_t val)+{+    JSFunctionDef *fd = s->cur_func;+    DynBuf *bc = &fd->byte_code;++    /* Use the line number of the last token used, not the next token,+       nor the current offset in the source file.+     */+    if (unlikely(fd->last_opcode_line_num != s->last_line_num)) {+        dbuf_putc(bc, OP_line_num);+        dbuf_put_u32(bc, s->last_line_num);+        fd->last_opcode_line_num = s->last_line_num;+    }+    fd->last_opcode_pos = bc->size;+    dbuf_putc(bc, val);+}++static void emit_atom(JSParseState *s, JSAtom name)+{+    emit_u32(s, JS_DupAtom(s->ctx, name));+}++static int update_label(JSFunctionDef *s, int label, int delta)+{+    LabelSlot *ls;++    assert(label >= 0 && label < s->label_count);+    ls = &s->label_slots[label];+    ls->ref_count += delta;+    assert(ls->ref_count >= 0);+    return ls->ref_count;+}++static int new_label_fd(JSFunctionDef *fd, int label)+{+    LabelSlot *ls;++    if (label < 0) {+        if (js_resize_array(fd->ctx, (void *)&fd->label_slots,+                            sizeof(fd->label_slots[0]),+                            &fd->label_size, fd->label_count + 1))+            return -1;+        label = fd->label_count++;+        ls = &fd->label_slots[label];+        ls->ref_count = 0;+        ls->pos = -1;+        ls->pos2 = -1;+        ls->addr = -1;+        ls->first_reloc = NULL;+    }+    return label;+}++static int new_label(JSParseState *s)+{+    return new_label_fd(s->cur_func, -1);+}++/* return the label ID offset */+static int emit_label(JSParseState *s, int label)+{+    if (label >= 0) {+        emit_op(s, OP_label);+        emit_u32(s, label);+        s->cur_func->label_slots[label].pos = s->cur_func->byte_code.size;+        return s->cur_func->byte_code.size - 4;+    } else {+        return -1;+    }+}++/* return label or -1 if dead code */+static int emit_goto(JSParseState *s, int opcode, int label)+{+    if (js_is_live_code(s)) {+        if (label < 0)+            label = new_label(s);+        emit_op(s, opcode);+        emit_u32(s, label);+        s->cur_func->label_slots[label].ref_count++;+        return label;+    }+    return -1;+}++/* return the constant pool index. 'val' is not duplicated. */+static int cpool_add(JSParseState *s, JSValue val)+{+    JSFunctionDef *fd = s->cur_func;+    +    if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]),+                        &fd->cpool_size, fd->cpool_count + 1))+        return -1;+    fd->cpool[fd->cpool_count++] = val;+    return fd->cpool_count - 1;+}++static __exception int emit_push_const(JSParseState *s, JSValueConst val,+                                       BOOL as_atom)+{+    int idx;++    if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING && as_atom) {+        JSAtom atom;+        /* warning: JS_NewAtomStr frees the string value */+        JS_DupValue(s->ctx, val);+        atom = JS_NewAtomStr(s->ctx, JS_VALUE_GET_STRING(val));+        if (atom != JS_ATOM_NULL && !__JS_AtomIsTaggedInt(atom)) {+            emit_op(s, OP_push_atom_value);+            emit_u32(s, atom);+            return 0;+        }+    }++    idx = cpool_add(s, JS_DupValue(s->ctx, val));+    if (idx < 0)+        return -1;+    emit_op(s, OP_push_const);+    emit_u32(s, idx);+    return 0;+}++/* return the variable index or -1 if not found,+   add ARGUMENT_VAR_OFFSET for argument variables */+static int find_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)+{+    int i;+    for(i = fd->arg_count; i-- > 0;) {+        if (fd->args[i].var_name == name)+            return i | ARGUMENT_VAR_OFFSET;+    }+    return -1;+}++static int find_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)+{+    int i;+    for(i = fd->var_count; i-- > 0;) {+        if (fd->vars[i].var_name == name && fd->vars[i].scope_level == 0)+            return i;+    }+    return find_arg(ctx, fd, name);+}++/* find a variable declaration in a given scope */+static int find_var_in_scope(JSContext *ctx, JSFunctionDef *fd,+                             JSAtom name, int scope_level)+{+    int scope_idx;+    for(scope_idx = fd->scopes[scope_level].first; scope_idx >= 0;+        scope_idx = fd->vars[scope_idx].scope_next) {+        if (fd->vars[scope_idx].scope_level != scope_level)+            break;+        if (fd->vars[scope_idx].var_name == name)+            return scope_idx;+    }+    return -1;+}++/* return true if scope == parent_scope or if scope is a child of+   parent_scope */+static BOOL is_child_scope(JSContext *ctx, JSFunctionDef *fd,+                           int scope, int parent_scope)+{+    while (scope >= 0) {+        if (scope == parent_scope)+            return TRUE;+        scope = fd->scopes[scope].parent;+    }+    return FALSE;+}++/* find a 'var' declaration in the same scope or a child scope */+static int find_var_in_child_scope(JSContext *ctx, JSFunctionDef *fd,+                                   JSAtom name, int scope_level)+{+    int i;+    for(i = 0; i < fd->var_count; i++) {+        JSVarDef *vd = &fd->vars[i];+        if (vd->var_name == name && vd->scope_level == 0) {+            if (is_child_scope(ctx, fd, vd->scope_next,+                               scope_level))+                return i;+        }+    }+    return -1;+}+++static JSGlobalVar *find_global_var(JSFunctionDef *fd, JSAtom name)+{+    int i;+    for(i = 0; i < fd->global_var_count; i++) {+        JSGlobalVar *hf = &fd->global_vars[i];+        if (hf->var_name == name)+            return hf;+    }+    return NULL;++}++static JSGlobalVar *find_lexical_global_var(JSFunctionDef *fd, JSAtom name)+{+    JSGlobalVar *hf = find_global_var(fd, name);+    if (hf && hf->is_lexical)+        return hf;+    else+        return NULL;+}++static int find_lexical_decl(JSContext *ctx, JSFunctionDef *fd, JSAtom name,+                             int scope_idx, BOOL check_catch_var)+{+    while (scope_idx >= 0) {+        JSVarDef *vd = &fd->vars[scope_idx];+        if (vd->var_name == name &&+            (vd->is_lexical || (vd->var_kind == JS_VAR_CATCH &&+                                check_catch_var)))+            return scope_idx;+        scope_idx = vd->scope_next;+    }++    if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_GLOBAL) {+        if (find_lexical_global_var(fd, name))+            return GLOBAL_VAR_OFFSET;+    }+    return -1;+}++static int push_scope(JSParseState *s) {+    if (s->cur_func) {+        JSFunctionDef *fd = s->cur_func;+        int scope = fd->scope_count;+        /* XXX: should check for scope overflow */+        if ((fd->scope_count + 1) > fd->scope_size) {+            int new_size;+            size_t slack;+            JSVarScope *new_buf;+            /* XXX: potential arithmetic overflow */+            new_size = max_int(fd->scope_count + 1, fd->scope_size * 3 / 2);+            if (fd->scopes == fd->def_scope_array) {+                new_buf = js_realloc2(s->ctx, NULL, new_size * sizeof(*fd->scopes), &slack);+                if (!new_buf)+                    return -1;+                memcpy(new_buf, fd->scopes, fd->scope_count * sizeof(*fd->scopes));+            } else {+                new_buf = js_realloc2(s->ctx, fd->scopes, new_size * sizeof(*fd->scopes), &slack);+                if (!new_buf)+                    return -1;+            }+            new_size += slack / sizeof(*new_buf);+            fd->scopes = new_buf;+            fd->scope_size = new_size;+        }+        fd->scope_count++;+        fd->scopes[scope].parent = fd->scope_level;+        fd->scopes[scope].first = fd->scope_first;+        emit_op(s, OP_enter_scope);+        emit_u16(s, scope);+        return fd->scope_level = scope;+    }+    return 0;+}++static int get_first_lexical_var(JSFunctionDef *fd, int scope)+{+    while (scope >= 0) {+        int scope_idx = fd->scopes[scope].first;+        if (scope_idx >= 0)+            return scope_idx;+        scope = fd->scopes[scope].parent;+    }+    return -1;+}++static void pop_scope(JSParseState *s) {+    if (s->cur_func) {+        /* disable scoped variables */+        JSFunctionDef *fd = s->cur_func;+        int scope = fd->scope_level;+        emit_op(s, OP_leave_scope);+        emit_u16(s, scope);+        fd->scope_level = fd->scopes[scope].parent;+        fd->scope_first = get_first_lexical_var(fd, fd->scope_level);+    }+}++static void close_scopes(JSParseState *s, int scope, int scope_stop)+{+    while (scope > scope_stop) {+        emit_op(s, OP_leave_scope);+        emit_u16(s, scope);+        scope = s->cur_func->scopes[scope].parent;+    }+}++/* return the variable index or -1 if error */+static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)+{+    JSVarDef *vd;++    /* the local variable indexes are currently stored on 16 bits */+    if (fd->var_count >= JS_MAX_LOCAL_VARS) {+        JS_ThrowInternalError(ctx, "too many local variables");+        return -1;+    }+    if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]),+                        &fd->var_size, fd->var_count + 1))+        return -1;+    vd = &fd->vars[fd->var_count++];+    memset(vd, 0, sizeof(*vd));+    vd->var_name = JS_DupAtom(ctx, name);+    vd->func_pool_idx = -1;+    return fd->var_count - 1;+}++static int add_scope_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name,+                         JSVarKindEnum var_kind)+{+    int idx = add_var(ctx, fd, name);+    if (idx >= 0) {+        JSVarDef *vd = &fd->vars[idx];+        vd->var_kind = var_kind;+        vd->scope_level = fd->scope_level;+        vd->scope_next = fd->scope_first;+        fd->scopes[fd->scope_level].first = idx;+        fd->scope_first = idx;+    }+    return idx;+}++static int add_func_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name)+{+    int idx = fd->func_var_idx;+    if (idx < 0 && (idx = add_var(ctx, fd, name)) >= 0) {+        fd->func_var_idx = idx;+        fd->vars[idx].var_kind = JS_VAR_FUNCTION_NAME;+        if (fd->js_mode & JS_MODE_STRICT)+            fd->vars[idx].is_const = TRUE;+    }+    return idx;+}++static int add_arguments_var(JSContext *ctx, JSFunctionDef *fd)+{+    int idx = fd->arguments_var_idx;+    if (idx < 0 && (idx = add_var(ctx, fd, JS_ATOM_arguments)) >= 0) {+        fd->arguments_var_idx = idx;+    }+    return idx;+}++/* add an argument definition in the argument scope. Only needed when+   "eval()" may be called in the argument scope. Return 0 if OK. */+static int add_arguments_arg(JSContext *ctx, JSFunctionDef *fd)+{+    int idx;+    if (fd->arguments_arg_idx < 0) {+        idx = find_var_in_scope(ctx, fd, JS_ATOM_arguments, ARG_SCOPE_INDEX);+        if (idx < 0) {+            /* XXX: the scope links are not fully updated. May be an+               issue if there are child scopes of the argument+               scope */+            idx = add_var(ctx, fd, JS_ATOM_arguments);+            if (idx < 0)+                return -1;+            fd->vars[idx].scope_next = fd->scopes[ARG_SCOPE_INDEX].first;+            fd->scopes[ARG_SCOPE_INDEX].first = idx;+            fd->vars[idx].scope_level = ARG_SCOPE_INDEX;+            fd->vars[idx].is_lexical = TRUE;++            fd->arguments_arg_idx = idx;+        }+    }+    return 0;+}++static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name)+{+    JSVarDef *vd;++    /* the local variable indexes are currently stored on 16 bits */+    if (fd->arg_count >= JS_MAX_LOCAL_VARS) {+        JS_ThrowInternalError(ctx, "too many arguments");+        return -1;+    }+    if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]),+                        &fd->arg_size, fd->arg_count + 1))+        return -1;+    vd = &fd->args[fd->arg_count++];+    memset(vd, 0, sizeof(*vd));+    vd->var_name = JS_DupAtom(ctx, name);+    vd->func_pool_idx = -1;+    return fd->arg_count - 1;+}++/* add a global variable definition */+static JSGlobalVar *add_global_var(JSContext *ctx, JSFunctionDef *s,+                                     JSAtom name)+{+    JSGlobalVar *hf;++    if (js_resize_array(ctx, (void **)&s->global_vars,+                        sizeof(s->global_vars[0]),+                        &s->global_var_size, s->global_var_count + 1))+        return NULL;+    hf = &s->global_vars[s->global_var_count++];+    hf->cpool_idx = -1;+    hf->force_init = FALSE;+    hf->is_lexical = FALSE;+    hf->is_const = FALSE;+    hf->scope_level = s->scope_level;+    hf->var_name = JS_DupAtom(ctx, name);+    return hf;+}++typedef enum {+    JS_VAR_DEF_WITH,+    JS_VAR_DEF_LET,+    JS_VAR_DEF_CONST,+    JS_VAR_DEF_FUNCTION_DECL, /* function declaration */+    JS_VAR_DEF_NEW_FUNCTION_DECL, /* async/generator function declaration */+    JS_VAR_DEF_CATCH,+    JS_VAR_DEF_VAR,+} JSVarDefEnum;++static int define_var(JSParseState *s, JSFunctionDef *fd, JSAtom name,+                      JSVarDefEnum var_def_type)+{+    JSContext *ctx = s->ctx;+    JSVarDef *vd;+    int idx;++    switch (var_def_type) {+    case JS_VAR_DEF_WITH:+        idx = add_scope_var(ctx, fd, name, JS_VAR_NORMAL);+        break;++    case JS_VAR_DEF_LET:+    case JS_VAR_DEF_CONST:+    case JS_VAR_DEF_FUNCTION_DECL:+    case JS_VAR_DEF_NEW_FUNCTION_DECL:+        idx = find_lexical_decl(ctx, fd, name, fd->scope_first, TRUE);+        if (idx >= 0) {+            if (idx < GLOBAL_VAR_OFFSET) {+                if (fd->vars[idx].scope_level == fd->scope_level) {+                    /* same scope: in non strict mode, functions+                       can be redefined (annex B.3.3.4). */+                    if (!(!(fd->js_mode & JS_MODE_STRICT) &&+                          var_def_type == JS_VAR_DEF_FUNCTION_DECL &&+                          fd->vars[idx].var_kind == JS_VAR_FUNCTION_DECL)) {+                        goto redef_lex_error;+                    }+                } else if (fd->vars[idx].var_kind == JS_VAR_CATCH && (fd->vars[idx].scope_level + 2) == fd->scope_level) {+                    goto redef_lex_error;+                }+            } else {+                if (fd->scope_level == fd->body_scope) {+                redef_lex_error:+                    /* redefining a scoped var in the same scope: error */+                    return js_parse_error(s, "invalid redefinition of lexical identifier");+                }+            }+        }+        if (var_def_type != JS_VAR_DEF_FUNCTION_DECL &&+            var_def_type != JS_VAR_DEF_NEW_FUNCTION_DECL &&+            fd->scope_level == fd->body_scope &&+            find_arg(ctx, fd, name) >= 0) {+            /* lexical variable redefines a parameter name */+            return js_parse_error(s, "invalid redefinition of parameter name");+        }++        if (find_var_in_child_scope(ctx, fd, name, fd->scope_level) >= 0) {+            return js_parse_error(s, "invalid redefinition of a variable");+        }+        +        if (fd->is_global_var) {+            JSGlobalVar *hf;+            hf = find_global_var(fd, name);+            if (hf && is_child_scope(ctx, fd, hf->scope_level,+                                     fd->scope_level)) {+                return js_parse_error(s, "invalid redefinition of global identifier");+            }+        }+        +        if (fd->is_eval &&+            (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||+             fd->eval_type == JS_EVAL_TYPE_MODULE) &&+            fd->scope_level == fd->body_scope) {+            JSGlobalVar *hf;+            hf = add_global_var(s->ctx, fd, name);+            if (!hf)+                return -1;+            hf->is_lexical = TRUE;+            hf->is_const = (var_def_type == JS_VAR_DEF_CONST);+            idx = GLOBAL_VAR_OFFSET;+        } else {+            JSVarKindEnum var_kind;+            if (var_def_type == JS_VAR_DEF_FUNCTION_DECL)+                var_kind = JS_VAR_FUNCTION_DECL;+            else if (var_def_type == JS_VAR_DEF_NEW_FUNCTION_DECL)+                var_kind = JS_VAR_NEW_FUNCTION_DECL;+            else+                var_kind = JS_VAR_NORMAL;+            idx = add_scope_var(ctx, fd, name, var_kind);+            if (idx >= 0) {+                vd = &fd->vars[idx];+                vd->is_lexical = 1;+                vd->is_const = (var_def_type == JS_VAR_DEF_CONST);+            }+        }+        break;++    case JS_VAR_DEF_CATCH:+        idx = add_scope_var(ctx, fd, name, JS_VAR_CATCH);+        break;++    case JS_VAR_DEF_VAR:+        if (find_lexical_decl(ctx, fd, name, fd->scope_first,+                              FALSE) >= 0) {+       invalid_lexical_redefinition:+            /* error to redefine a var that inside a lexical scope */+            return js_parse_error(s, "invalid redefinition of lexical identifier");+        }+        if (fd->is_global_var) {+            JSGlobalVar *hf;+            hf = find_global_var(fd, name);+            if (hf && hf->is_lexical && hf->scope_level == fd->scope_level &&+                fd->eval_type == JS_EVAL_TYPE_MODULE) {+                goto invalid_lexical_redefinition;+            }+            hf = add_global_var(s->ctx, fd, name);+            if (!hf)+                return -1;+            idx = GLOBAL_VAR_OFFSET;+        } else {+            /* if the variable already exists, don't add it again  */+            idx = find_var(ctx, fd, name);+            if (idx >= 0)+                break;+            idx = add_var(ctx, fd, name);+            if (idx >= 0) {+                if (name == JS_ATOM_arguments && fd->has_arguments_binding)+                    fd->arguments_var_idx = idx;+                fd->vars[idx].scope_next = fd->scope_level;+            }+        }+        break;+    default:+        abort();+    }+    return idx;+}++/* add a private field variable in the current scope */+static int add_private_class_field(JSParseState *s, JSFunctionDef *fd,+                                   JSAtom name, JSVarKindEnum var_kind)+{+    JSContext *ctx = s->ctx;+    JSVarDef *vd;+    int idx;++    idx = add_scope_var(ctx, fd, name, var_kind);+    if (idx < 0)+        return idx;+    vd = &fd->vars[idx];+    vd->is_lexical = 1;+    vd->is_const = 1;+    return idx;+}++static __exception int js_parse_expr(JSParseState *s);+static __exception int js_parse_function_decl(JSParseState *s,+                                              JSParseFunctionEnum func_type,+                                              JSFunctionKindEnum func_kind,+                                              JSAtom func_name, const uint8_t *ptr,+                                              int start_line);+static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s);+static __exception int js_parse_function_decl2(JSParseState *s,+                                               JSParseFunctionEnum func_type,+                                               JSFunctionKindEnum func_kind,+                                               JSAtom func_name,+                                               const uint8_t *ptr,+                                               int function_line_num,+                                               JSParseExportEnum export_flag,+                                               JSFunctionDef **pfd);+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags);+static __exception int js_parse_assign_expr(JSParseState *s);+static __exception int js_parse_unary(JSParseState *s, int parse_flags);+static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,+                             JSAtom label_name,+                             int label_break, int label_cont,+                             int drop_count);+static void pop_break_entry(JSFunctionDef *fd);+static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m,+                                       JSAtom local_name, JSAtom export_name,+                                       JSExportTypeEnum export_type);++/* Note: all the fields are already sealed except length */+static int seal_template_obj(JSContext *ctx, JSValueConst obj)+{+    JSObject *p;+    JSShapeProperty *prs;++    p = JS_VALUE_GET_OBJ(obj);+    prs = find_own_property1(p, JS_ATOM_length);+    if (prs) {+        if (js_update_property_flags(ctx, p, &prs,+                                     prs->flags & ~(JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)))+            return -1;+    }+    p->extensible = FALSE;+    return 0;+}++static __exception int js_parse_template(JSParseState *s, int call, int *argc)+{+    JSContext *ctx = s->ctx;+    JSValue raw_array, template_object;+    JSToken cooked;+    int depth, ret;++    raw_array = JS_UNDEFINED; /* avoid warning */+    template_object = JS_UNDEFINED; /* avoid warning */+    if (call) {+        /* Create a template object: an array of cooked strings */+        /* Create an array of raw strings and store it to the raw property */+        template_object = JS_NewArray(ctx);+        if (JS_IsException(template_object))+            return -1;+        //        pool_idx = s->cur_func->cpool_count;+        ret = emit_push_const(s, template_object, 0);+        JS_FreeValue(ctx, template_object);+        if (ret)+            return -1;+        raw_array = JS_NewArray(ctx);+        if (JS_IsException(raw_array))+            return -1;+        if (JS_DefinePropertyValue(ctx, template_object, JS_ATOM_raw,+                                   raw_array, JS_PROP_THROW) < 0) {+            return -1;+        }+    }++    depth = 0;+    while (s->token.val == TOK_TEMPLATE) {+        const uint8_t *p = s->token.ptr + 1;+        cooked = s->token;+        if (call) {+            if (JS_DefinePropertyValueUint32(ctx, raw_array, depth,+                                             JS_DupValue(ctx, s->token.u.str.str),+                                             JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) {+                return -1;+            }+            /* re-parse the string with escape sequences but do not throw a+               syntax error if it contains invalid sequences+             */+            if (js_parse_string(s, '`', FALSE, p, &cooked, &p)) {+                cooked.u.str.str = JS_UNDEFINED;+            }+            if (JS_DefinePropertyValueUint32(ctx, template_object, depth,+                                             cooked.u.str.str,+                                             JS_PROP_ENUMERABLE | JS_PROP_THROW) < 0) {+                return -1;+            }+        } else {+            JSString *str;+            /* re-parse the string with escape sequences and throw a+               syntax error if it contains invalid sequences+             */+            JS_FreeValue(ctx, s->token.u.str.str);+            s->token.u.str.str = JS_UNDEFINED;+            if (js_parse_string(s, '`', TRUE, p, &cooked, &p))+                return -1;+            str = JS_VALUE_GET_STRING(cooked.u.str.str);+            if (str->len != 0 || depth == 0) {+                ret = emit_push_const(s, cooked.u.str.str, 1);+                JS_FreeValue(s->ctx, cooked.u.str.str);+                if (ret)+                    return -1;+                if (depth == 0) {+                    if (s->token.u.str.sep == '`')+                        goto done1;+                    emit_op(s, OP_get_field2);+                    emit_atom(s, JS_ATOM_concat);+                }+                depth++;+            } else {+                JS_FreeValue(s->ctx, cooked.u.str.str);+            }+        }+        if (s->token.u.str.sep == '`')+            goto done;+        if (next_token(s))+            return -1;+        if (js_parse_expr(s))+            return -1;+        depth++;+        if (s->token.val != '}') {+            return js_parse_error(s, "expected '}' after template expression");+        }+        /* XXX: should convert to string at this stage? */+        free_token(s, &s->token);+        /* Resume TOK_TEMPLATE parsing (s->token.line_num and+         * s->token.ptr are OK) */+        s->got_lf = FALSE;+        s->last_line_num = s->token.line_num;+        if (js_parse_template_part(s, s->buf_ptr))+            return -1;+    }+    return js_parse_expect(s, TOK_TEMPLATE);++ done:+    if (call) {+        /* Seal the objects */+        seal_template_obj(ctx, raw_array);+        seal_template_obj(ctx, template_object);+        *argc = depth + 1;+    } else {+        emit_op(s, OP_call_method);+        emit_u16(s, depth - 1);+    }+ done1:+    return next_token(s);+}+++#define PROP_TYPE_IDENT 0+#define PROP_TYPE_VAR   1+#define PROP_TYPE_GET   2+#define PROP_TYPE_SET   3+#define PROP_TYPE_STAR  4+#define PROP_TYPE_ASYNC 5+#define PROP_TYPE_ASYNC_STAR 6++#define PROP_TYPE_PRIVATE (1 << 4)++static BOOL token_is_ident(int tok)+{+    /* Accept keywords and reserved words as property names */+    return (tok == TOK_IDENT ||+            (tok >= TOK_FIRST_KEYWORD &&+             tok <= TOK_LAST_KEYWORD));+}++/* if the property is an expression, name = JS_ATOM_NULL */+static int __exception js_parse_property_name(JSParseState *s,+                                              JSAtom *pname,+                                              BOOL allow_method, BOOL allow_var,+                                              BOOL allow_private)+{+    int is_private = 0;+    BOOL is_non_reserved_ident;+    JSAtom name;+    int prop_type;+    +    prop_type = PROP_TYPE_IDENT;+    if (allow_method) {+        if (token_is_pseudo_keyword(s, JS_ATOM_get)+        ||  token_is_pseudo_keyword(s, JS_ATOM_set)) {+            /* get x(), set x() */+            name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+            if (next_token(s))+                goto fail1;+            if (s->token.val == ':' || s->token.val == ',' ||+                s->token.val == '}' || s->token.val == '(') {+                is_non_reserved_ident = TRUE;+                goto ident_found;+            }+            prop_type = PROP_TYPE_GET + (name == JS_ATOM_set);+            JS_FreeAtom(s->ctx, name);+        } else if (s->token.val == '*') {+            if (next_token(s))+                goto fail;+            prop_type = PROP_TYPE_STAR;+        } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&+                   peek_token(s, TRUE) != '\n') {+            name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+            if (next_token(s))+                goto fail1;+            if (s->token.val == ':' || s->token.val == ',' ||+                s->token.val == '}' || s->token.val == '(') {+                is_non_reserved_ident = TRUE;+                goto ident_found;+            }+            JS_FreeAtom(s->ctx, name);+            if (s->token.val == '*') {+                if (next_token(s))+                    goto fail;+                prop_type = PROP_TYPE_ASYNC_STAR;+            } else {+                prop_type = PROP_TYPE_ASYNC;+            }+        }+    }++    if (token_is_ident(s->token.val)) {+        /* variable can only be a non-reserved identifier */+        is_non_reserved_ident =+            (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved);+        /* keywords and reserved words have a valid atom */+        name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+        if (next_token(s))+            goto fail1;+    ident_found:+        if (is_non_reserved_ident &&+            prop_type == PROP_TYPE_IDENT && allow_var) {+            if (!(s->token.val == ':' ||+                  (s->token.val == '(' && allow_method))) {+                prop_type = PROP_TYPE_VAR;+            }+        }+    } else if (s->token.val == TOK_STRING) {+        name = JS_ValueToAtom(s->ctx, s->token.u.str.str);+        if (name == JS_ATOM_NULL)+            goto fail;+        if (next_token(s))+            goto fail1;+    } else if (s->token.val == TOK_NUMBER) {+        JSValue val;+        val = s->token.u.num.val;+#ifdef CONFIG_BIGNUM+        if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            val = s->ctx->rt->bigfloat_ops.+                mul_pow10_to_float64(s->ctx, &p->num,+                                     s->token.u.num.exponent);+            if (JS_IsException(val))+                goto fail;+            name = JS_ValueToAtom(s->ctx, val);+            JS_FreeValue(s->ctx, val);+        } else+#endif+        {+            name = JS_ValueToAtom(s->ctx, val);+        }+        if (name == JS_ATOM_NULL)+            goto fail;+        if (next_token(s))+            goto fail1;+    } else if (s->token.val == '[') {+        if (next_token(s))+            goto fail;+        if (js_parse_expr(s))+            goto fail;+        if (js_parse_expect(s, ']'))+            goto fail;+        name = JS_ATOM_NULL;+    } else if (s->token.val == TOK_PRIVATE_NAME && allow_private) {+        name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+        if (next_token(s))+            goto fail1;+        is_private = PROP_TYPE_PRIVATE;+    } else {+        goto invalid_prop;+    }+    if (prop_type != PROP_TYPE_IDENT && prop_type != PROP_TYPE_VAR &&+        s->token.val != '(') {+        JS_FreeAtom(s->ctx, name);+    invalid_prop:+        js_parse_error(s, "invalid property name");+        goto fail;+    }+    *pname = name;+    return prop_type | is_private;+ fail1:+    JS_FreeAtom(s->ctx, name);+ fail:+    *pname = JS_ATOM_NULL;+    return -1;+}++typedef struct JSParsePos {+    int last_line_num;+    int line_num;+    BOOL got_lf;+    const uint8_t *ptr;+} JSParsePos;++static int js_parse_get_pos(JSParseState *s, JSParsePos *sp)+{+    sp->last_line_num = s->last_line_num;+    sp->line_num = s->token.line_num;+    sp->ptr = s->token.ptr;+    sp->got_lf = s->got_lf;+    return 0;+}++static __exception int js_parse_seek_token(JSParseState *s, const JSParsePos *sp)+{+    s->token.line_num = sp->last_line_num;+    s->line_num = sp->line_num;+    s->buf_ptr = sp->ptr;+    s->got_lf = sp->got_lf;+    return next_token(s);+}++/* return TRUE if a regexp literal is allowed after this token */+static BOOL is_regexp_allowed(int tok)+{+    switch (tok) {+    case TOK_NUMBER:+    case TOK_STRING:+    case TOK_REGEXP:+    case TOK_DEC:+    case TOK_INC:+    case TOK_NULL:+    case TOK_FALSE:+    case TOK_TRUE:+    case TOK_THIS:+    case ')':+    case ']':+    case '}': /* XXX: regexp may occur after */+    case TOK_IDENT:+        return FALSE;+    default:+        return TRUE;+    }+}++#define SKIP_HAS_SEMI       (1 << 0)+#define SKIP_HAS_ELLIPSIS   (1 << 1)+#define SKIP_HAS_ASSIGNMENT (1 << 2)++/* XXX: improve speed with early bailout */+/* XXX: no longer works if regexps are present. Could use previous+   regexp parsing heuristics to handle most cases */+static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_terminator)+{+    char state[256];+    size_t level = 0;+    JSParsePos pos;+    int last_tok, tok = TOK_EOF;+    int c, tok_len, bits = 0;++    /* protect from underflow */+    state[level++] = 0;++    js_parse_get_pos(s, &pos);+    last_tok = 0;+    for (;;) {+        switch(s->token.val) {+        case '(':+        case '[':+        case '{':+            if (level >= sizeof(state))+                goto done;+            state[level++] = s->token.val;+            break;+        case ')':+            if (state[--level] != '(')+                goto done;+            break;+        case ']':+            if (state[--level] != '[')+                goto done;+            break;+        case '}':+            c = state[--level];+            if (c == '`') {+                /* continue the parsing of the template */+                free_token(s, &s->token);+                /* Resume TOK_TEMPLATE parsing (s->token.line_num and+                 * s->token.ptr are OK) */+                s->got_lf = FALSE;+                s->last_line_num = s->token.line_num;+                if (js_parse_template_part(s, s->buf_ptr))+                    goto done;+                goto handle_template;+            } else if (c != '{') {+                goto done;+            }+            break;+        case TOK_TEMPLATE:+        handle_template:+            if (s->token.u.str.sep != '`') {+                /* '${' inside the template : closing '}' and continue+                   parsing the template */+                if (level >= sizeof(state))+                    goto done;+                state[level++] = '`';+            } +            break;+        case TOK_EOF:+            goto done;+        case ';':+            if (level == 2) {+                bits |= SKIP_HAS_SEMI;+            }+            break;+        case TOK_ELLIPSIS:+            if (level == 2) {+                bits |= SKIP_HAS_ELLIPSIS;+            }+            break;+        case '=':+            bits |= SKIP_HAS_ASSIGNMENT;+            break;+            +        case TOK_DIV_ASSIGN:+            tok_len = 2;+            goto parse_regexp;+        case '/':+            tok_len = 1;+        parse_regexp:+            if (is_regexp_allowed(last_tok)) {+                s->buf_ptr -= tok_len;+                if (js_parse_regexp(s)) {+                    /* XXX: should clear the exception */+                    goto done;+                }+            }+            break;+        }+        /* last_tok is only used to recognize regexps */+        if (s->token.val == TOK_IDENT &&+            (token_is_pseudo_keyword(s, JS_ATOM_of) ||+             token_is_pseudo_keyword(s, JS_ATOM_yield))) {+            last_tok = TOK_OF;+        } else {+            last_tok = s->token.val;+        }+        if (next_token(s)) {+            /* XXX: should clear the exception generated by next_token() */+            break;+        }+        if (level <= 1) {+            tok = s->token.val;+            if (token_is_pseudo_keyword(s, JS_ATOM_of))+                tok = TOK_OF;+            if (no_line_terminator && s->last_line_num != s->token.line_num)+                tok = '\n';+            break;+        }+    }+ done:+    if (pbits) {+        *pbits = bits;+    }+    if (js_parse_seek_token(s, &pos))+        return -1;+    return tok;+}++static void set_object_name(JSParseState *s, JSAtom name)+{+    JSFunctionDef *fd = s->cur_func;+    int opcode;++    opcode = get_prev_opcode(fd);+    if (opcode == OP_set_name) {+        /* XXX: should free atom after OP_set_name? */+        fd->byte_code.size = fd->last_opcode_pos;+        fd->last_opcode_pos = -1;+        emit_op(s, OP_set_name);+        emit_atom(s, name);+    } else if (opcode == OP_set_class_name) {+        int define_class_pos;+        JSAtom atom;+        define_class_pos = fd->last_opcode_pos + 1 -+            get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        assert(fd->byte_code.buf[define_class_pos] == OP_define_class);+        /* for consistency we free the previous atom which is+           JS_ATOM_empty_string */+        atom = get_u32(fd->byte_code.buf + define_class_pos + 1);+        JS_FreeAtom(s->ctx, atom);+        put_u32(fd->byte_code.buf + define_class_pos + 1,+                JS_DupAtom(s->ctx, name));+        fd->last_opcode_pos = -1;+    }+}++static void set_object_name_computed(JSParseState *s)+{+    JSFunctionDef *fd = s->cur_func;+    int opcode;++    opcode = get_prev_opcode(fd);+    if (opcode == OP_set_name) {+        /* XXX: should free atom after OP_set_name? */+        fd->byte_code.size = fd->last_opcode_pos;+        fd->last_opcode_pos = -1;+        emit_op(s, OP_set_name_computed);+    } else if (opcode == OP_set_class_name) {+        int define_class_pos;+        define_class_pos = fd->last_opcode_pos + 1 -+            get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        assert(fd->byte_code.buf[define_class_pos] == OP_define_class);+        fd->byte_code.buf[define_class_pos] = OP_define_class_computed;+        fd->last_opcode_pos = -1;+    }+}++static __exception int js_parse_object_literal(JSParseState *s)+{+    JSAtom name = JS_ATOM_NULL;+    const uint8_t *start_ptr;+    int start_line, prop_type;+    BOOL has_proto;++    if (next_token(s))+        goto fail;+    /* XXX: add an initial length that will be patched back */+    emit_op(s, OP_object);+    has_proto = FALSE;+    while (s->token.val != '}') {+        /* specific case for getter/setter */+        start_ptr = s->token.ptr;+        start_line = s->token.line_num;++        if (s->token.val == TOK_ELLIPSIS) {+            if (next_token(s))+                return -1;+            if (js_parse_assign_expr(s))+                return -1;+            emit_op(s, OP_null);  /* dummy excludeList */+            emit_op(s, OP_copy_data_properties);+            emit_u8(s, 2 | (1 << 2) | (0 << 5));+            emit_op(s, OP_drop); /* pop excludeList */+            emit_op(s, OP_drop); /* pop src object */+            goto next;+        }++        prop_type = js_parse_property_name(s, &name, TRUE, TRUE, FALSE);+        if (prop_type < 0)+            goto fail;++        if (prop_type == PROP_TYPE_VAR) {+            /* shortcut for x: x */+            emit_op(s, OP_scope_get_var);+            emit_atom(s, name);+            emit_u16(s, s->cur_func->scope_level);+            emit_op(s, OP_define_field);+            emit_atom(s, name);+        } else if (s->token.val == '(') {+            BOOL is_getset = (prop_type == PROP_TYPE_GET ||+                              prop_type == PROP_TYPE_SET);+            JSParseFunctionEnum func_type;+            JSFunctionKindEnum func_kind;+            int op_flags;++            func_kind = JS_FUNC_NORMAL;+            if (is_getset) {+                func_type = JS_PARSE_FUNC_GETTER + prop_type - PROP_TYPE_GET;+            } else {+                func_type = JS_PARSE_FUNC_METHOD;+                if (prop_type == PROP_TYPE_STAR)+                    func_kind = JS_FUNC_GENERATOR;+                else if (prop_type == PROP_TYPE_ASYNC)+                    func_kind = JS_FUNC_ASYNC;+                else if (prop_type == PROP_TYPE_ASYNC_STAR)+                    func_kind = JS_FUNC_ASYNC_GENERATOR;+            }+            if (js_parse_function_decl(s, func_type, func_kind, JS_ATOM_NULL,+                                       start_ptr, start_line))+                goto fail;+            if (name == JS_ATOM_NULL) {+                emit_op(s, OP_define_method_computed);+            } else {+                emit_op(s, OP_define_method);+                emit_atom(s, name);+            }+            if (is_getset) {+                op_flags = OP_DEFINE_METHOD_GETTER ++                    prop_type - PROP_TYPE_GET;+            } else {+                op_flags = OP_DEFINE_METHOD_METHOD;+            }+            emit_u8(s, op_flags | OP_DEFINE_METHOD_ENUMERABLE);+        } else {+            if (js_parse_expect(s, ':'))+                goto fail;+            if (js_parse_assign_expr(s))+                goto fail;+            if (name == JS_ATOM_NULL) {+                set_object_name_computed(s);+                emit_op(s, OP_define_array_el);+                emit_op(s, OP_drop);+            } else if (name == JS_ATOM___proto__) {+                if (has_proto) {+                    js_parse_error(s, "duplicate __proto__ property name");+                    goto fail;+                }+                emit_op(s, OP_set_proto);+                has_proto = TRUE;+            } else {+                set_object_name(s, name);+                emit_op(s, OP_define_field);+                emit_atom(s, name);+            }+        }+        JS_FreeAtom(s->ctx, name);+    next:+        name = JS_ATOM_NULL;+        if (s->token.val != ',')+            break;+        if (next_token(s))+            goto fail;+    }+    if (js_parse_expect(s, '}'))+        goto fail;+    return 0;+ fail:+    JS_FreeAtom(s->ctx, name);+    return -1;+}++/* allow the 'in' binary operator */+#define PF_IN_ACCEPTED  (1 << 0) +/* allow function calls parsing in js_parse_postfix_expr() */+#define PF_POSTFIX_CALL (1 << 1) +/* allow arrow functions parsing in js_parse_postfix_expr() */+#define PF_ARROW_FUNC   (1 << 2) +/* allow the exponentiation operator in js_parse_unary() */+#define PF_POW_ALLOWED  (1 << 3) +/* forbid the exponentiation operator in js_parse_unary() */+#define PF_POW_FORBIDDEN (1 << 4) ++static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags);++static __exception int js_parse_left_hand_side_expr(JSParseState *s)+{+    return js_parse_postfix_expr(s, PF_POSTFIX_CALL);+}++/* XXX: is there is nicer solution ? */+static __exception int js_parse_class_default_ctor(JSParseState *s,+                                                   BOOL has_super,+                                                   JSFunctionDef **pfd)+{+    JSParsePos pos;+    const char *str;+    int ret, line_num;+    JSParseFunctionEnum func_type;+    const uint8_t *saved_buf_end;+    +    js_parse_get_pos(s, &pos);+    if (has_super) {+        str = "(...a){super(...a);}";+        func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;+    } else {+        str = "(){}";+        func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;+    }+    line_num = s->token.line_num;+    saved_buf_end = s->buf_end;+    s->buf_ptr = (uint8_t *)str;+    s->buf_end = (uint8_t *)(str + strlen(str));+    ret = next_token(s);+    if (!ret) {+        ret = js_parse_function_decl2(s, func_type, JS_FUNC_NORMAL,+                                      JS_ATOM_NULL, (uint8_t *)str,+                                      line_num, JS_PARSE_EXPORT_NONE, pfd);+    }+    s->buf_end = saved_buf_end;+    ret |= js_parse_seek_token(s, &pos);+    return ret;+}++/* find field in the current scope */+static int find_private_class_field(JSContext *ctx, JSFunctionDef *fd,+                                    JSAtom name, int scope_level)+{+    int idx;+    idx = fd->scopes[scope_level].first;+    while (idx != -1) {+        if (fd->vars[idx].scope_level != scope_level)+            break;+        if (fd->vars[idx].var_name == name)+            return idx;+        idx = fd->vars[idx].scope_next;+    }+    return -1;+}++/* initialize the class fields, called by the constructor. Note:+   super() can be called in an arrow function, so <this> and+   <class_fields_init> can be variable references */+static void emit_class_field_init(JSParseState *s)+{+    int label_next;+    +    emit_op(s, OP_scope_get_var);+    emit_atom(s, JS_ATOM_class_fields_init);+    emit_u16(s, s->cur_func->scope_level);++    /* no need to call the class field initializer if not defined */+    emit_op(s, OP_dup);+    label_next = emit_goto(s, OP_if_false, -1);+    +    emit_op(s, OP_scope_get_var);+    emit_atom(s, JS_ATOM_this);+    emit_u16(s, 0);+    +    emit_op(s, OP_swap);+    +    emit_op(s, OP_call_method);+    emit_u16(s, 0);++    emit_label(s, label_next);+    emit_op(s, OP_drop);+}++/* build a private setter function name from the private getter name */+static JSAtom get_private_setter_name(JSContext *ctx, JSAtom name)+{+    return js_atom_concat_str(ctx, name, "<set>");+}++typedef struct {+    JSFunctionDef *fields_init_fd;+    int computed_fields_count;+    BOOL has_brand;+    int brand_push_pos;+} ClassFieldsDef;++static __exception int emit_class_init_start(JSParseState *s,+                                             ClassFieldsDef *cf)+{+    int label_add_brand;+    +    cf->fields_init_fd = js_parse_function_class_fields_init(s);+    if (!cf->fields_init_fd)+        return -1;++    s->cur_func = cf->fields_init_fd;+    +    /* XXX: would be better to add the code only if needed, maybe in a+       later pass */+    emit_op(s, OP_push_false); /* will be patched later */+    cf->brand_push_pos = cf->fields_init_fd->last_opcode_pos;+    label_add_brand = emit_goto(s, OP_if_false, -1);+    +    emit_op(s, OP_scope_get_var);+    emit_atom(s, JS_ATOM_this);+    emit_u16(s, 0);+    +    emit_op(s, OP_scope_get_var);+    emit_atom(s, JS_ATOM_home_object);+    emit_u16(s, 0);+    +    emit_op(s, OP_add_brand);+    +    emit_label(s, label_add_brand);++    s->cur_func = s->cur_func->parent;+    return 0;+}++static __exception int add_brand(JSParseState *s, ClassFieldsDef *cf)+{+    if (!cf->has_brand) {+        /* define the brand field in 'this' of the initializer */+        if (!cf->fields_init_fd) {+            if (emit_class_init_start(s, cf))+                return -1;+        }+        /* patch the start of the function to enable the OP_add_brand code */+        cf->fields_init_fd->byte_code.buf[cf->brand_push_pos] = OP_push_true;+        +        cf->has_brand = TRUE;+    }+    return 0;+}++static void emit_class_init_end(JSParseState *s, ClassFieldsDef *cf)+{+    int cpool_idx;+        +    s->cur_func = cf->fields_init_fd;+    emit_op(s, OP_return_undef);+    s->cur_func = s->cur_func->parent;+    +    cpool_idx = cpool_add(s, JS_NULL);+    cf->fields_init_fd->parent_cpool_idx = cpool_idx;+    emit_op(s, OP_fclosure);+    emit_u32(s, cpool_idx);+    emit_op(s, OP_set_home_object);+}+++static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,+                                      JSParseExportEnum export_flag)+{+    JSContext *ctx = s->ctx;+    JSFunctionDef *fd = s->cur_func;+    JSAtom name = JS_ATOM_NULL, class_name = JS_ATOM_NULL, class_name1;+    JSAtom class_var_name = JS_ATOM_NULL;+    JSFunctionDef *method_fd, *ctor_fd;+    int saved_js_mode, class_name_var_idx, prop_type, ctor_cpool_offset;+    int class_flags = 0, i, define_class_offset;+    BOOL is_static, is_private;+    const uint8_t *class_start_ptr = s->token.ptr;+    const uint8_t *start_ptr;+    ClassFieldsDef class_fields[2];+        +    /* classes are parsed and executed in strict mode */+    saved_js_mode = fd->js_mode;+    fd->js_mode |= JS_MODE_STRICT;+    if (next_token(s))+        goto fail;+    if (s->token.val == TOK_IDENT) {+        if (s->token.u.ident.is_reserved) {+            js_parse_error_reserved_identifier(s);+            goto fail;+        }+        class_name = JS_DupAtom(ctx, s->token.u.ident.atom);+        if (next_token(s))+            goto fail;+    } else if (!is_class_expr && export_flag != JS_PARSE_EXPORT_DEFAULT) {+        js_parse_error(s, "class statement requires a name");+        goto fail;+    }+    if (!is_class_expr) {+        if (class_name == JS_ATOM_NULL)+            class_var_name = JS_ATOM__default_; /* export default */+        else+            class_var_name = class_name;+        class_var_name = JS_DupAtom(ctx, class_var_name);+    }++    push_scope(s);++    if (s->token.val == TOK_EXTENDS) {+        class_flags = JS_DEFINE_CLASS_HAS_HERITAGE;+        if (next_token(s))+            goto fail;+        if (js_parse_left_hand_side_expr(s))+            goto fail;+    } else {+        emit_op(s, OP_undefined);+    }++    /* add a 'const' definition for the class name */+    if (class_name != JS_ATOM_NULL) {+        class_name_var_idx = define_var(s, fd, class_name, JS_VAR_DEF_CONST);+        if (class_name_var_idx < 0)+            goto fail;+    }++    if (js_parse_expect(s, '{'))+        goto fail;++    /* this scope contains the private fields */+    push_scope(s);++    emit_op(s, OP_push_const);+    ctor_cpool_offset = fd->byte_code.size;+    emit_u32(s, 0); /* will be patched at the end of the class parsing */++    if (class_name == JS_ATOM_NULL) {+        if (class_var_name != JS_ATOM_NULL)+            class_name1 = JS_ATOM_default;+        else+            class_name1 = JS_ATOM_empty_string;+    } else {+        class_name1 = class_name;+    }+    +    emit_op(s, OP_define_class);+    emit_atom(s, class_name1);+    emit_u8(s, class_flags);+    define_class_offset = fd->last_opcode_pos;++    for(i = 0; i < 2; i++) {+        ClassFieldsDef *cf = &class_fields[i];+        cf->fields_init_fd = NULL;+        cf->computed_fields_count = 0;+        cf->has_brand = FALSE;+    }+    +    ctor_fd = NULL;+    while (s->token.val != '}') {+        if (s->token.val == ';') {+            if (next_token(s))+                goto fail;+            continue;+        }+        is_static = (s->token.val == TOK_STATIC);+        prop_type = -1;+        if (is_static) {+            if (next_token(s))+                goto fail;+            /* allow "static" field name */+            if (s->token.val == ';' || s->token.val == '=') {+                is_static = FALSE;+                name = JS_DupAtom(ctx, JS_ATOM_static);+                prop_type = PROP_TYPE_IDENT;+            }+        }+        if (is_static)+            emit_op(s, OP_swap);+        start_ptr = s->token.ptr;+        if (prop_type < 0) {+            prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE);+            if (prop_type < 0)+                goto fail;+        }+        is_private = prop_type & PROP_TYPE_PRIVATE;+        prop_type &= ~PROP_TYPE_PRIVATE;+        +        if ((name == JS_ATOM_constructor && !is_static &&+             prop_type != PROP_TYPE_IDENT) ||+            (name == JS_ATOM_prototype && is_static) ||+            name == JS_ATOM_hash_constructor) {+            js_parse_error(s, "invalid method name");+            goto fail;+        }+        if (prop_type == PROP_TYPE_GET || prop_type == PROP_TYPE_SET) {+            BOOL is_set = prop_type - PROP_TYPE_GET;+            JSFunctionDef *method_fd;++            if (is_private) {+                int idx, var_kind;+                idx = find_private_class_field(ctx, fd, name, fd->scope_level);+                if (idx >= 0) {+                    var_kind = fd->vars[idx].var_kind;+                    if (var_kind == JS_VAR_PRIVATE_FIELD ||+                        var_kind == JS_VAR_PRIVATE_METHOD ||+                        var_kind == JS_VAR_PRIVATE_GETTER_SETTER ||+                        var_kind == (JS_VAR_PRIVATE_GETTER + is_set)) {+                        goto private_field_already_defined;+                    }+                    fd->vars[idx].var_kind = JS_VAR_PRIVATE_GETTER_SETTER;+                } else {+                    if (add_private_class_field(s, fd, name,+                                                JS_VAR_PRIVATE_GETTER + is_set) < 0)+                        goto fail;+                }+                if (add_brand(s, &class_fields[is_static]) < 0)+                    goto fail;+            }++            if (js_parse_function_decl2(s, JS_PARSE_FUNC_GETTER + is_set,+                                        JS_FUNC_NORMAL, JS_ATOM_NULL,+                                        start_ptr, s->token.line_num,+                                        JS_PARSE_EXPORT_NONE, &method_fd))+                goto fail;+            if (is_private) {+                method_fd->need_home_object = TRUE; /* needed for brand check */+                emit_op(s, OP_set_home_object);+                /* XXX: missing function name */+                emit_op(s, OP_scope_put_var_init);+                if (is_set) {+                    JSAtom setter_name;+                    int ret;+                    +                    setter_name = get_private_setter_name(ctx, name);+                    if (setter_name == JS_ATOM_NULL)+                        goto fail;+                    emit_atom(s, setter_name);+                    ret = add_private_class_field(s, fd, setter_name,+                                                  JS_VAR_PRIVATE_SETTER);+                    JS_FreeAtom(ctx, setter_name);+                    if (ret < 0)+                        goto fail;+                } else {+                    emit_atom(s, name);+                }+                emit_u16(s, s->cur_func->scope_level);+            } else {+                if (name == JS_ATOM_NULL) {+                    emit_op(s, OP_define_method_computed);+                } else {+                    emit_op(s, OP_define_method);+                    emit_atom(s, name);+                }+                emit_u8(s, OP_DEFINE_METHOD_GETTER + is_set);+            }+        } else if (prop_type == PROP_TYPE_IDENT && s->token.val != '(') {+            ClassFieldsDef *cf = &class_fields[is_static];+            JSAtom field_var_name = JS_ATOM_NULL;+            +            /* class field */++            /* XXX: spec: not consistent with method name checks */+            if (name == JS_ATOM_constructor || name == JS_ATOM_prototype) {+                js_parse_error(s, "invalid field name");+                goto fail;+            }+            +            if (is_private) {+                if (find_private_class_field(ctx, fd, name,+                                             fd->scope_level) >= 0) {+                    goto private_field_already_defined;+                }+                if (add_private_class_field(s, fd, name,+                                            JS_VAR_PRIVATE_FIELD) < 0)+                    goto fail;+                emit_op(s, OP_private_symbol);+                emit_atom(s, name);+                emit_op(s, OP_scope_put_var_init);+                emit_atom(s, name);+                emit_u16(s, s->cur_func->scope_level);+            }++            if (!cf->fields_init_fd) {+                if (emit_class_init_start(s, cf))+                    goto fail;+            }+            if (name == JS_ATOM_NULL ) {+                /* save the computed field name into a variable */+                field_var_name = js_atom_concat_num(ctx, JS_ATOM_computed_field + is_static, cf->computed_fields_count);+                if (field_var_name == JS_ATOM_NULL)+                    goto fail;+                if (define_var(s, fd, field_var_name, JS_VAR_DEF_CONST) < 0) {+                    JS_FreeAtom(ctx, field_var_name);+                    goto fail;+                }+                emit_op(s, OP_to_propkey);+                emit_op(s, OP_scope_put_var_init);+                emit_atom(s, field_var_name);+                emit_u16(s, s->cur_func->scope_level);+            }+            s->cur_func = cf->fields_init_fd;+            emit_op(s, OP_scope_get_var);+            emit_atom(s, JS_ATOM_this);+            emit_u16(s, 0);++            if (name == JS_ATOM_NULL) {+                emit_op(s, OP_scope_get_var);+                emit_atom(s, field_var_name);+                emit_u16(s, s->cur_func->scope_level);+                cf->computed_fields_count++;+                JS_FreeAtom(ctx, field_var_name);+            } else if (is_private) {+                emit_op(s, OP_scope_get_var);+                emit_atom(s, name);+                emit_u16(s, s->cur_func->scope_level);+            }+            +            if (s->token.val == '=') {+                if (next_token(s))+                    goto fail;+                if (js_parse_assign_expr(s))+                    goto fail;+            } else {+                emit_op(s, OP_undefined);+            }+            if (is_private) {+                set_object_name_computed(s);+                emit_op(s, OP_define_private_field);+            } else if (name == JS_ATOM_NULL) {+                set_object_name_computed(s);+                emit_op(s, OP_define_array_el);+                emit_op(s, OP_drop);+            } else {+                set_object_name(s, name);+                emit_op(s, OP_define_field);+                emit_atom(s, name);+            }+            s->cur_func = s->cur_func->parent;+            if (js_parse_expect_semi(s))+                goto fail;+        } else {+            JSParseFunctionEnum func_type;+            JSFunctionKindEnum func_kind;+            +            func_type = JS_PARSE_FUNC_METHOD;+            func_kind = JS_FUNC_NORMAL;+            if (prop_type == PROP_TYPE_STAR) {+                func_kind = JS_FUNC_GENERATOR;+            } else if (prop_type == PROP_TYPE_ASYNC) {+                func_kind = JS_FUNC_ASYNC;+            } else if (prop_type == PROP_TYPE_ASYNC_STAR) {+                func_kind = JS_FUNC_ASYNC_GENERATOR;+            } else if (name == JS_ATOM_constructor && !is_static) {+                if (ctor_fd) {+                    js_parse_error(s, "property constructor appears more than once");+                    goto fail;+                }+                if (class_flags & JS_DEFINE_CLASS_HAS_HERITAGE)+                    func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;+                else+                    func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;+            }+            if (is_private) {+                if (add_brand(s, &class_fields[is_static]) < 0)+                    goto fail;+            }+            if (js_parse_function_decl2(s, func_type, func_kind, JS_ATOM_NULL, start_ptr, s->token.line_num, JS_PARSE_EXPORT_NONE, &method_fd))+                goto fail;+            if (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR ||+                func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {+                ctor_fd = method_fd;+            } else if (is_private) {+                method_fd->need_home_object = TRUE; /* needed for brand check */+                if (find_private_class_field(ctx, fd, name,+                                             fd->scope_level) >= 0) {+                private_field_already_defined:+                    js_parse_error(s, "private class field is already defined");+                    goto fail;+                }+                if (add_private_class_field(s, fd, name,+                                            JS_VAR_PRIVATE_METHOD) < 0)+                    goto fail;+                emit_op(s, OP_set_home_object);+                emit_op(s, OP_set_name);+                emit_atom(s, name);+                emit_op(s, OP_scope_put_var_init);+                emit_atom(s, name);+                emit_u16(s, s->cur_func->scope_level);+            } else {+                if (name == JS_ATOM_NULL) {+                    emit_op(s, OP_define_method_computed);+                } else {+                    emit_op(s, OP_define_method);+                    emit_atom(s, name);+                }+                emit_u8(s, OP_DEFINE_METHOD_METHOD);+            }+        }+        if (is_static)+            emit_op(s, OP_swap);+        JS_FreeAtom(ctx, name);+        name = JS_ATOM_NULL;+    }++    if (s->token.val != '}') {+        js_parse_error(s, "expecting '%c'", '}');+        goto fail;+    }++    if (!ctor_fd) {+        if (js_parse_class_default_ctor(s, class_flags & JS_DEFINE_CLASS_HAS_HERITAGE, &ctor_fd))+            goto fail;+    }+    /* patch the constant pool index for the constructor */+    put_u32(fd->byte_code.buf + ctor_cpool_offset, ctor_fd->parent_cpool_idx);++    /* store the class source code in the constructor. */+    if (!(fd->js_mode & JS_MODE_STRIP)) {+        js_free(ctx, ctor_fd->source);+        ctor_fd->source_len = s->buf_ptr - class_start_ptr;+        ctor_fd->source = js_strndup(ctx, (const char *)class_start_ptr,+                                     ctor_fd->source_len);+        if (!ctor_fd->source)+            goto fail;+    }++    /* consume the '}' */+    if (next_token(s))+        goto fail;++    /* store the function to initialize the fields to that it can be+       referenced by the constructor */+    {+        ClassFieldsDef *cf = &class_fields[0];+        int var_idx;+        +        var_idx = define_var(s, fd, JS_ATOM_class_fields_init,+                             JS_VAR_DEF_CONST);+        if (var_idx < 0)+            goto fail;+        if (cf->fields_init_fd) {+            emit_class_init_end(s, cf);+        } else {+            emit_op(s, OP_undefined);+        }+        emit_op(s, OP_scope_put_var_init);+        emit_atom(s, JS_ATOM_class_fields_init);+        emit_u16(s, s->cur_func->scope_level);+    }++    /* drop the prototype */+    emit_op(s, OP_drop);++    /* initialize the static fields */+    if (class_fields[1].fields_init_fd != NULL) {+        ClassFieldsDef *cf = &class_fields[1];+        emit_op(s, OP_dup);+        emit_class_init_end(s, cf);+        emit_op(s, OP_call_method);+        emit_u16(s, 0);+        emit_op(s, OP_drop);+    }+    +    if (class_name != JS_ATOM_NULL) {+        /* store the class name in the scoped class name variable (it+           is independent from the class statement variable+           definition) */+        emit_op(s, OP_dup);+        emit_op(s, OP_scope_put_var_init);+        emit_atom(s, class_name);+        emit_u16(s, fd->scope_level);+    }+    pop_scope(s);+    pop_scope(s);++    /* the class statements have a block level scope */+    if (class_var_name != JS_ATOM_NULL) {+        if (define_var(s, fd, class_var_name, JS_VAR_DEF_LET) < 0)+            goto fail;+        emit_op(s, OP_scope_put_var_init);+        emit_atom(s, class_var_name);+        emit_u16(s, fd->scope_level);+    } else {+        if (class_name == JS_ATOM_NULL) {+            /* cannot use OP_set_name because the name of the class+               must be defined before the static initializers are+               executed */+            emit_op(s, OP_set_class_name);+            emit_u32(s, fd->last_opcode_pos + 1 - define_class_offset);+        }+    }++    if (export_flag != JS_PARSE_EXPORT_NONE) {+        if (!add_export_entry(s, fd->module,+                              class_var_name,+                              export_flag == JS_PARSE_EXPORT_NAMED ? class_var_name : JS_ATOM_default,+                              JS_EXPORT_TYPE_LOCAL))+            goto fail;+    }++    JS_FreeAtom(ctx, class_name);+    JS_FreeAtom(ctx, class_var_name);+    fd->js_mode = saved_js_mode;+    return 0;+ fail:+    JS_FreeAtom(ctx, name);+    JS_FreeAtom(ctx, class_name);+    JS_FreeAtom(ctx, class_var_name);+    fd->js_mode = saved_js_mode;+    return -1;+}++static __exception int js_parse_array_literal(JSParseState *s)+{+    uint32_t idx;+    BOOL need_length;++    if (next_token(s))+        return -1;+    /* small regular arrays are created on the stack */+    idx = 0;+    while (s->token.val != ']' && idx < 32) {+        if (s->token.val == ',' || s->token.val == TOK_ELLIPSIS)+            break;+        if (js_parse_assign_expr(s))+            return -1;+        idx++;+        /* accept trailing comma */+        if (s->token.val == ',') {+            if (next_token(s))+                return -1;+        } else+        if (s->token.val != ']')+            goto done;+    }+    emit_op(s, OP_array_from);+    emit_u16(s, idx);++    /* larger arrays and holes are handled with explicit indices */+    need_length = FALSE;+    while (s->token.val != ']' && idx < 0x7fffffff) {+        if (s->token.val == TOK_ELLIPSIS)+            break;+        need_length = TRUE;+        if (s->token.val != ',') {+            if (js_parse_assign_expr(s))+                return -1;+            emit_op(s, OP_define_field);+            emit_u32(s, __JS_AtomFromUInt32(idx));+            need_length = FALSE;+        }+        idx++;+        /* accept trailing comma */+        if (s->token.val == ',') {+            if (next_token(s))+                return -1;+        }+    }+    if (s->token.val == ']') {+        if (need_length) {+            /* Set the length: Cannot use OP_define_field because+               length is not configurable */+            emit_op(s, OP_dup);+            emit_op(s, OP_push_i32);+            emit_u32(s, idx);+            emit_op(s, OP_put_field);+            emit_atom(s, JS_ATOM_length);+        }+        goto done;+    }++    /* huge arrays and spread elements require a dynamic index on the stack */+    emit_op(s, OP_push_i32);+    emit_u32(s, idx);++    /* stack has array, index */+    while (s->token.val != ']') {+        if (s->token.val == TOK_ELLIPSIS) {+            if (next_token(s))+                return -1;+            if (js_parse_assign_expr(s))+                return -1;+#if 1+            emit_op(s, OP_append);+#else+            int label_next, label_done;+            label_next = new_label(s);+            label_done = new_label(s);+            /* enumerate object */+            emit_op(s, OP_for_of_start);+            emit_op(s, OP_rot5l);+            emit_op(s, OP_rot5l);+            emit_label(s, label_next);+            /* on stack: enum_rec array idx */+            emit_op(s, OP_for_of_next);+            emit_u8(s, 2);+            emit_goto(s, OP_if_true, label_done);+            /* append element */+            /* enum_rec array idx val -> enum_rec array new_idx */+            emit_op(s, OP_define_array_el);+            emit_op(s, OP_inc);+            emit_goto(s, OP_goto, label_next);+            emit_label(s, label_done);+            /* close enumeration */+            emit_op(s, OP_drop); /* drop undef val */+            emit_op(s, OP_nip1); /* drop enum_rec */+            emit_op(s, OP_nip1);+            emit_op(s, OP_nip1);+#endif+        } else {+            need_length = TRUE;+            if (s->token.val != ',') {+                if (js_parse_assign_expr(s))+                    return -1;+                /* a idx val */+                emit_op(s, OP_define_array_el);+                need_length = FALSE;+            }+            emit_op(s, OP_inc);+        }+        if (s->token.val != ',')+            break;+        if (next_token(s))+            return -1;+    }+    if (need_length) {+        /* Set the length: cannot use OP_define_field because+           length is not configurable */+        emit_op(s, OP_dup1);    /* array length - array array length */+        emit_op(s, OP_put_field);+        emit_atom(s, JS_ATOM_length);+    } else {+        emit_op(s, OP_drop);    /* array length - array */+    }+done:+    return js_parse_expect(s, ']');+}++/* XXX: remove */+static BOOL has_with_scope(JSFunctionDef *s, int scope_level)+{+    /* check if scope chain contains a with statement */+    while (s) {+        int scope_idx = s->scopes[scope_level].first;+        while (scope_idx >= 0) {+            JSVarDef *vd = &s->vars[scope_idx];++            if (vd->var_name == JS_ATOM__with_)+                return TRUE;+            scope_idx = vd->scope_next;+        }+        /* check parent scopes */+        scope_level = s->parent_scope_level;+        s = s->parent;+    }+    return FALSE;+}++static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,+                                  JSAtom *pname, int *plabel, int *pdepth, BOOL keep,+                                  int tok)+{+    JSFunctionDef *fd;+    int opcode, scope, label, depth;+    JSAtom name;++    /* we check the last opcode to get the lvalue type */+    fd = s->cur_func;+    scope = 0;+    name = JS_ATOM_NULL;+    label = -1;+    depth = 0;+    switch(opcode = get_prev_opcode(fd)) {+    case OP_scope_get_var:+        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);+        if ((name == JS_ATOM_arguments || name == JS_ATOM_eval) &&+            (fd->js_mode & JS_MODE_STRICT)) {+            return js_parse_error(s, "invalid lvalue in strict mode");+        }+        if (name == JS_ATOM_this || name == JS_ATOM_new_target)+            goto invalid_lvalue;+        depth = 2;  /* will generate OP_get_ref_value */+        break;+    case OP_get_field:+        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        depth = 1;+        break;+    case OP_scope_get_private_field:+        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);+        depth = 1;+        break;+    case OP_get_array_el:+        depth = 2;+        break;+    case OP_get_super_value:+        depth = 3;+        break;+    default:+    invalid_lvalue:+        if (tok == TOK_FOR) {+            return js_parse_error(s, "invalid for in/of left hand-side");+        } else if (tok == TOK_INC || tok == TOK_DEC) {+            return js_parse_error(s, "invalid increment/decrement operand");+        } else if (tok == '[' || tok == '{') {+            return js_parse_error(s, "invalid destructuring target");+        } else {+            return js_parse_error(s, "invalid assignment left-hand side");+        }+    }+    /* remove the last opcode */+    fd->byte_code.size = fd->last_opcode_pos;+    fd->last_opcode_pos = -1;++    if (keep) {+        /* get the value but keep the object/fields on the stack */+        switch(opcode) {+        case OP_scope_get_var:+            label = new_label(s);+            emit_op(s, OP_scope_make_ref);+            emit_atom(s, name);+            emit_u32(s, label);+            emit_u16(s, scope);+            update_label(fd, label, 1);+            emit_op(s, OP_get_ref_value);+            opcode = OP_get_ref_value;+            break;+        case OP_get_field:+            emit_op(s, OP_get_field2);+            emit_atom(s, name);+            break;+        case OP_scope_get_private_field:+            emit_op(s, OP_scope_get_private_field2);+            emit_atom(s, name);+            emit_u16(s, scope);+            break;+        case OP_get_array_el:+            /* XXX: replace by a single opcode ? */+            emit_op(s, OP_to_propkey2);+            emit_op(s, OP_dup2);+            emit_op(s, OP_get_array_el);+            break;+        case OP_get_super_value:+            emit_op(s, OP_to_propkey);+            emit_op(s, OP_dup3);+            emit_op(s, OP_get_super_value);+            break;+        default:+            abort();+        }+    } else {+        switch(opcode) {+        case OP_scope_get_var:+            label = new_label(s);+            emit_op(s, OP_scope_make_ref);+            emit_atom(s, name);+            emit_u32(s, label);+            emit_u16(s, scope);+            update_label(fd, label, 1);+            opcode = OP_get_ref_value;+            break;+        case OP_get_array_el:+            emit_op(s, OP_to_propkey2);+            break;+        case OP_get_super_value:+            emit_op(s, OP_to_propkey);+            break;+        }+    }++    *popcode = opcode;+    *pscope = scope;+    /* name has refcount for OP_get_field and OP_get_ref_value,+       and JS_ATOM_NULL for other opcodes */+    *pname = name;+    *plabel = label;+    if (pdepth)+        *pdepth = depth;+    return 0;+}++typedef enum {+    PUT_LVALUE_NOKEEP, /* [depth] v -> */+    PUT_LVALUE_NOKEEP_DEPTH, /* [depth] v -> , keep depth (currently+                                just disable optimizations) */+    PUT_LVALUE_KEEP_TOP,  /* [depth] v -> v */+    PUT_LVALUE_KEEP_SECOND, /* [depth] v0 v -> v0 */+    PUT_LVALUE_NOKEEP_BOTTOM, /* v [depth] -> */+} PutLValueEnum;++/* name has a live reference. 'is_let' is only used with opcode =+   OP_scope_get_var which is never generated by get_lvalue(). */+static void put_lvalue(JSParseState *s, int opcode, int scope,+                       JSAtom name, int label, PutLValueEnum special,+                       BOOL is_let)+{+    switch(opcode) {+    case OP_get_field:+    case OP_scope_get_private_field:+        /* depth = 1 */+        switch(special) {+        case PUT_LVALUE_NOKEEP:+        case PUT_LVALUE_NOKEEP_DEPTH:+            break;+        case PUT_LVALUE_KEEP_TOP:+            emit_op(s, OP_insert2); /* obj v -> v obj v */+            break;+        case PUT_LVALUE_KEEP_SECOND:+            emit_op(s, OP_perm3); /* obj v0 v -> v0 obj v */+            break;+        case PUT_LVALUE_NOKEEP_BOTTOM:+            emit_op(s, OP_swap);+            break;+        default:+            abort();+        }+        break;+    case OP_get_array_el:+    case OP_get_ref_value:+        /* depth = 2 */+        if (opcode == OP_get_ref_value) {+            JS_FreeAtom(s->ctx, name);+            emit_label(s, label);+        }+        switch(special) {+        case PUT_LVALUE_NOKEEP:+            emit_op(s, OP_nop); /* will trigger optimization */+            break;+        case PUT_LVALUE_NOKEEP_DEPTH:+            break;+        case PUT_LVALUE_KEEP_TOP:+            emit_op(s, OP_insert3); /* obj prop v -> v obj prop v */+            break;+        case PUT_LVALUE_KEEP_SECOND:+            emit_op(s, OP_perm4); /* obj prop v0 v -> v0 obj prop v */+            break;+        case PUT_LVALUE_NOKEEP_BOTTOM:+            emit_op(s, OP_rot3l);+            break;+        default:+            abort();+        }+        break;+    case OP_get_super_value:+        /* depth = 3 */+        switch(special) {+        case PUT_LVALUE_NOKEEP:+        case PUT_LVALUE_NOKEEP_DEPTH:+            break;+        case PUT_LVALUE_KEEP_TOP:+            emit_op(s, OP_insert4); /* this obj prop v -> v this obj prop v */+            break;+        case PUT_LVALUE_KEEP_SECOND:+            emit_op(s, OP_perm5); /* this obj prop v0 v -> v0 this obj prop v */+            break;+        case PUT_LVALUE_NOKEEP_BOTTOM:+            emit_op(s, OP_rot4l);+            break;+        default:+            abort();+        }+        break;+    default:+        break;+    }+    +    switch(opcode) {+    case OP_scope_get_var:  /* val -- */+        assert(special == PUT_LVALUE_NOKEEP ||+               special == PUT_LVALUE_NOKEEP_DEPTH);+        emit_op(s, is_let ? OP_scope_put_var_init : OP_scope_put_var);+        emit_u32(s, name);  /* has refcount */+        emit_u16(s, scope);+        break;+    case OP_get_field:+        emit_op(s, OP_put_field);+        emit_u32(s, name);  /* name has refcount */+        break;+    case OP_scope_get_private_field:+        emit_op(s, OP_scope_put_private_field);+        emit_u32(s, name);  /* name has refcount */+        emit_u16(s, scope);+        break;+    case OP_get_array_el:+        emit_op(s, OP_put_array_el);+        break;+    case OP_get_ref_value:+        emit_op(s, OP_put_ref_value);+        break;+    case OP_get_super_value:+        emit_op(s, OP_put_super_value);+        break;+    default:+        abort();+    }+}++static __exception int js_parse_expr_paren(JSParseState *s)+{+    if (js_parse_expect(s, '('))+        return -1;+    if (js_parse_expr(s))+        return -1;+    if (js_parse_expect(s, ')'))+        return -1;+    return 0;+}++static int js_unsupported_keyword(JSParseState *s, JSAtom atom)+{+    char buf[ATOM_GET_STR_BUF_SIZE];+    return js_parse_error(s, "unsupported keyword: %s",+                          JS_AtomGetStr(s->ctx, buf, sizeof(buf), atom));+}++static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)+{+    JSFunctionDef *fd = s->cur_func;+    JSVarDefEnum var_def_type;+    +    if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {+        return js_parse_error(s, "yield is a reserved identifier");+    }+    if ((name == JS_ATOM_arguments || name == JS_ATOM_eval)+    &&  (fd->js_mode & JS_MODE_STRICT)) {+        return js_parse_error(s, "invalid variable name in strict mode");+    }+    if ((name == JS_ATOM_let || name == JS_ATOM_undefined)+    &&  (tok == TOK_LET || tok == TOK_CONST)) {+        return js_parse_error(s, "invalid lexical variable name");+    }+    switch(tok) {+    case TOK_LET:+        var_def_type = JS_VAR_DEF_LET;+        break;+    case TOK_CONST:+        var_def_type = JS_VAR_DEF_CONST;+        break;+    case TOK_VAR:+        var_def_type = JS_VAR_DEF_VAR;+        break;+    case TOK_CATCH:+        var_def_type = JS_VAR_DEF_CATCH;+        break;+    default:+        abort();+    }+    if (define_var(s, fd, name, var_def_type) < 0)+        return -1;+    return 0;+}++static void js_emit_spread_code(JSParseState *s, int depth)+{+    int label_rest_next, label_rest_done;++    /* XXX: could check if enum object is an actual array and optimize+       slice extraction. enumeration record and target array are in a+       different order from OP_append case. */+    /* enum_rec xxx -- enum_rec xxx array 0 */+    emit_op(s, OP_array_from);+    emit_u16(s, 0);+    emit_op(s, OP_push_i32);+    emit_u32(s, 0);+    emit_label(s, label_rest_next = new_label(s));+    emit_op(s, OP_for_of_next);+    emit_u8(s, 2 + depth);+    label_rest_done = emit_goto(s, OP_if_true, -1);+    /* array idx val -- array idx */+    emit_op(s, OP_define_array_el);+    emit_op(s, OP_inc);+    emit_goto(s, OP_goto, label_rest_next);+    emit_label(s, label_rest_done);+    /* enum_rec xxx array idx undef -- enum_rec xxx array */+    emit_op(s, OP_drop);+    emit_op(s, OP_drop);+}++static int js_parse_check_duplicate_parameter(JSParseState *s, JSAtom name)+{+    /* Check for duplicate parameter names */+    JSFunctionDef *fd = s->cur_func;+    int i;+    for (i = 0; i < fd->arg_count; i++) {+        if (fd->args[i].var_name == name)+            goto duplicate;+    }+    for (i = 0; i < fd->var_count; i++) {+        if (fd->vars[i].var_name == name)+            goto duplicate;+    }+    return 0;++duplicate:+    return js_parse_error(s, "duplicate parameter names not allowed in this context");+}++static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)+{+    JSAtom name;++    if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)+    ||  ((s->cur_func->js_mode & JS_MODE_STRICT) &&+         (s->token.u.ident.atom == JS_ATOM_eval || s->token.u.ident.atom == JS_ATOM_arguments))) {+        js_parse_error(s, "invalid destructuring target");+        return JS_ATOM_NULL;+    }+    name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+    if (is_arg && js_parse_check_duplicate_parameter(s, name))+        goto fail;+    if (next_token(s))+        goto fail;++    return name;+fail:+    JS_FreeAtom(s->ctx, name);+    return JS_ATOM_NULL;+}++/* Return -1 if error, 0 if no initializer, 1 if an initializer is+   present at the top level. */+static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,+                                        int hasval, int has_ellipsis,+                                        BOOL allow_initializer)+{+    int label_parse, label_assign, label_done, label_lvalue, depth_lvalue;+    int start_addr, assign_addr;+    JSAtom prop_name, var_name;+    int opcode, scope, tok1, skip_bits;+    BOOL has_initializer;+    +    if (has_ellipsis < 0) {+        /* pre-parse destructuration target for spread detection */+        js_parse_skip_parens_token(s, &skip_bits, FALSE);+        has_ellipsis = skip_bits & SKIP_HAS_ELLIPSIS;+    }++    label_parse = new_label(s);+    label_assign = new_label(s);++    start_addr = s->cur_func->byte_code.size;+    if (hasval) {+        /* consume value from the stack */+        emit_op(s, OP_dup);+        emit_op(s, OP_undefined);+        emit_op(s, OP_strict_eq);+        emit_goto(s, OP_if_true, label_parse);+        emit_label(s, label_assign);+    } else {+        emit_goto(s, OP_goto, label_parse);+        emit_label(s, label_assign);+        /* leave value on the stack */+        emit_op(s, OP_dup);+    }+    assign_addr = s->cur_func->byte_code.size;+    if (s->token.val == '{') {+        if (next_token(s))+            return -1;+        /* throw an exception if the value cannot be converted to an object */+        emit_op(s, OP_to_object);+        if (has_ellipsis) {+            /* add excludeList on stack just below src object */+            emit_op(s, OP_object);+            emit_op(s, OP_swap);+        }+        while (s->token.val != '}') {+            int prop_type;+            if (s->token.val == TOK_ELLIPSIS) {+                if (!has_ellipsis) {+                    JS_ThrowInternalError(s->ctx, "unexpected ellipsis token");+                    return -1;+                }+                if (next_token(s))+                    return -1;+                if (tok) {+                    var_name = js_parse_destructuring_var(s, tok, is_arg);+                    if (var_name == JS_ATOM_NULL)+                        return -1;+                    opcode = OP_scope_get_var;+                    scope = s->cur_func->scope_level;+                    label_lvalue = -1;+                    depth_lvalue = 0;+                } else {+                    if (js_parse_left_hand_side_expr(s))+                        return -1;++                    if (get_lvalue(s, &opcode, &scope, &var_name,+                                   &label_lvalue, &depth_lvalue, FALSE, '{'))+                        return -1;+                }+                if (s->token.val != '}') {+                    js_parse_error(s, "assignment rest property must be last");+                    goto var_error;+                }+                emit_op(s, OP_object);  /* target */+                emit_op(s, OP_copy_data_properties);+                emit_u8(s, 0 | ((depth_lvalue + 1) << 2) | ((depth_lvalue + 2) << 5));+                goto set_val;+            }+            prop_type = js_parse_property_name(s, &prop_name, FALSE, TRUE, FALSE);+            if (prop_type < 0)+                return -1;+            var_name = JS_ATOM_NULL;+            opcode = OP_scope_get_var;+            scope = s->cur_func->scope_level;+            label_lvalue = -1;+            depth_lvalue = 0;+            if (prop_type == PROP_TYPE_IDENT) {+                if (next_token(s))+                    goto prop_error;+                if ((s->token.val == '[' || s->token.val == '{')+                    &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||+                         tok1 == '=' || tok1 == '}')) {+                    if (prop_name == JS_ATOM_NULL) {+                        /* computed property name on stack */+                        if (has_ellipsis) {+                            /* define the property in excludeList */+                            emit_op(s, OP_to_propkey); /* avoid calling ToString twice */+                            emit_op(s, OP_perm3); /* TOS: src excludeList prop */+                            emit_op(s, OP_null); /* TOS: src excludeList prop null */+                            emit_op(s, OP_define_array_el); /* TOS: src excludeList prop */+                            emit_op(s, OP_perm3); /* TOS: excludeList src prop */+                        }+                        /* get the computed property from the source object */+                        emit_op(s, OP_get_array_el2);+                    } else {+                        /* named property */+                        if (has_ellipsis) {+                            /* define the property in excludeList */+                            emit_op(s, OP_swap); /* TOS: src excludeList */+                            emit_op(s, OP_null); /* TOS: src excludeList null */+                            emit_op(s, OP_define_field); /* TOS: src excludeList */+                            emit_atom(s, prop_name);+                            emit_op(s, OP_swap); /* TOS: excludeList src */+                        }+                        /* get the named property from the source object */+                        emit_op(s, OP_get_field2);+                        emit_u32(s, prop_name);+                    }+                    if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE) < 0)+                        return -1;+                    if (s->token.val == '}')+                        break;+                    /* accept a trailing comma before the '}' */+                    if (js_parse_expect(s, ','))+                        return -1;+                    continue;+                }+                if (prop_name == JS_ATOM_NULL) {+                    emit_op(s, OP_to_propkey2);+                    if (has_ellipsis) {+                        /* define the property in excludeList */+                        emit_op(s, OP_perm3);+                        emit_op(s, OP_null);+                        emit_op(s, OP_define_array_el);+                        emit_op(s, OP_perm3);+                    }+                    /* source prop -- source source prop */+                    emit_op(s, OP_dup1);+                } else {+                    if (has_ellipsis) {+                        /* define the property in excludeList */+                        emit_op(s, OP_swap);+                        emit_op(s, OP_null);+                        emit_op(s, OP_define_field);+                        emit_atom(s, prop_name);+                        emit_op(s, OP_swap);+                    }+                    /* source -- source source */+                    emit_op(s, OP_dup);+                }+                if (tok) {+                    var_name = js_parse_destructuring_var(s, tok, is_arg);+                    if (var_name == JS_ATOM_NULL)+                        goto prop_error;+                } else {+                    if (js_parse_left_hand_side_expr(s))+                        goto prop_error;+                lvalue:+                    if (get_lvalue(s, &opcode, &scope, &var_name,+                                   &label_lvalue, &depth_lvalue, FALSE, '{'))+                        goto prop_error;+                    /* swap ref and lvalue object if any */+                    if (prop_name == JS_ATOM_NULL) {+                        switch(depth_lvalue) {+                        case 1:+                            /* source prop x -> x source prop */+                            emit_op(s, OP_rot3r);+                            break;+                        case 2:+                            /* source prop x y -> x y source prop */+                            emit_op(s, OP_swap2);   /* t p2 s p1 */+                            break;+                        case 3:+                            /* source prop x y z -> x y z source prop */+                            emit_op(s, OP_rot5l);+                            emit_op(s, OP_rot5l);+                            break;+                        }+                    } else {+                        switch(depth_lvalue) {+                        case 1:+                            /* source x -> x source */+                            emit_op(s, OP_swap);+                            break;+                        case 2:+                            /* source x y -> x y source */+                            emit_op(s, OP_rot3l);+                            break;+                        case 3:+                            /* source x y z -> x y z source */+                            emit_op(s, OP_rot4l);+                            break;+                        }+                    }+                }+                if (prop_name == JS_ATOM_NULL) {+                    /* computed property name on stack */+                    /* XXX: should have OP_get_array_el2x with depth */+                    /* source prop -- val */+                    emit_op(s, OP_get_array_el);+                } else {+                    /* named property */+                    /* XXX: should have OP_get_field2x with depth */+                    /* source -- val */+                    emit_op(s, OP_get_field);+                    emit_u32(s, prop_name);+                }+            } else {+                /* prop_type = PROP_TYPE_VAR, cannot be a computed property */+                if (is_arg && js_parse_check_duplicate_parameter(s, prop_name))+                    goto prop_error;+                if ((s->cur_func->js_mode & JS_MODE_STRICT) &&+                    (prop_name == JS_ATOM_eval || prop_name == JS_ATOM_arguments)) {+                    js_parse_error(s, "invalid destructuring target");+                    goto prop_error;+                }+                if (has_ellipsis) {+                    /* define the property in excludeList */+                    emit_op(s, OP_swap);+                    emit_op(s, OP_null);+                    emit_op(s, OP_define_field);+                    emit_atom(s, prop_name);+                    emit_op(s, OP_swap);+                }+                if (!tok || tok == TOK_VAR) {+                    /* generate reference */+                    /* source -- source source */+                    emit_op(s, OP_dup);+                    emit_op(s, OP_scope_get_var);+                    emit_atom(s, prop_name);+                    emit_u16(s, s->cur_func->scope_level);+                    goto lvalue;+                }+                var_name = JS_DupAtom(s->ctx, prop_name);+                /* source -- source val */+                emit_op(s, OP_get_field2);+                emit_u32(s, prop_name);+            }+        set_val:+            if (tok) {+                if (js_define_var(s, var_name, tok))+                    goto var_error;+                scope = s->cur_func->scope_level;+            }+            if (s->token.val == '=') {  /* handle optional default value */+                int label_hasval;+                emit_op(s, OP_dup);+                emit_op(s, OP_undefined);+                emit_op(s, OP_strict_eq);+                label_hasval = emit_goto(s, OP_if_false, -1);+                if (next_token(s))+                    goto var_error;+                emit_op(s, OP_drop);+                if (js_parse_assign_expr(s))+                    goto var_error;+                if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)+                    set_object_name(s, var_name);+                emit_label(s, label_hasval);+            }+            /* store value into lvalue object */+            put_lvalue(s, opcode, scope, var_name, label_lvalue,+                       PUT_LVALUE_NOKEEP_DEPTH,+                       (tok == TOK_CONST || tok == TOK_LET));+            if (s->token.val == '}')+                break;+            /* accept a trailing comma before the '}' */+            if (js_parse_expect(s, ','))+                return -1;+        }+        /* drop the source object */+        emit_op(s, OP_drop);+        if (has_ellipsis) {+            emit_op(s, OP_drop); /* pop excludeList */+        }+        if (next_token(s))+            return -1;+    } else if (s->token.val == '[') {+        BOOL has_spread;+        int enum_depth;+        BlockEnv block_env;++        if (next_token(s))+            return -1;+        /* the block environment is only needed in generators in case+           'yield' triggers a 'return' */+        push_break_entry(s->cur_func, &block_env,+                         JS_ATOM_NULL, -1, -1, 2);+        block_env.has_iterator = TRUE;+        emit_op(s, OP_for_of_start);+        has_spread = FALSE;+        while (s->token.val != ']') {+            /* get the next value */+            if (s->token.val == TOK_ELLIPSIS) {+                if (next_token(s))+                    return -1;+                if (s->token.val == ',' || s->token.val == ']')+                    return js_parse_error(s, "missing binding pattern...");+                has_spread = TRUE;+            }+            if (s->token.val == ',') {+                /* do nothing, skip the value, has_spread is false */+                emit_op(s, OP_for_of_next);+                emit_u8(s, 0);+                emit_op(s, OP_drop);+                emit_op(s, OP_drop);+            } else if ((s->token.val == '[' || s->token.val == '{')+                   &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == ',' ||+                        tok1 == '=' || tok1 == ']')) {+                if (has_spread) {+                    if (tok1 == '=')+                        return js_parse_error(s, "rest element cannot have a default value");+                    js_emit_spread_code(s, 0);+                } else {+                    emit_op(s, OP_for_of_next);+                    emit_u8(s, 0);+                    emit_op(s, OP_drop);+                }+                if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)+                    return -1;+            } else {+                var_name = JS_ATOM_NULL;+                enum_depth = 0;+                if (tok) {+                    var_name = js_parse_destructuring_var(s, tok, is_arg);+                    if (var_name == JS_ATOM_NULL)+                        goto var_error;+                    if (js_define_var(s, var_name, tok))+                        goto var_error;+                    opcode = OP_scope_get_var;+                    scope = s->cur_func->scope_level;+                } else {+                    if (js_parse_left_hand_side_expr(s))+                        return -1;+                    if (get_lvalue(s, &opcode, &scope, &var_name,+                                   &label_lvalue, &enum_depth, FALSE, '[')) {+                        return -1;+                    }+                }+                if (has_spread) {+                    js_emit_spread_code(s, enum_depth);+                } else {+                    emit_op(s, OP_for_of_next);+                    emit_u8(s, enum_depth);+                    emit_op(s, OP_drop);+                }+                if (s->token.val == '=' && !has_spread) {+                    /* handle optional default value */+                    int label_hasval;+                    emit_op(s, OP_dup);+                    emit_op(s, OP_undefined);+                    emit_op(s, OP_strict_eq);+                    label_hasval = emit_goto(s, OP_if_false, -1);+                    if (next_token(s))+                        goto var_error;+                    emit_op(s, OP_drop);+                    if (js_parse_assign_expr(s))+                        goto var_error;+                    if (opcode == OP_scope_get_var || opcode == OP_get_ref_value)+                        set_object_name(s, var_name);+                    emit_label(s, label_hasval);+                }+                /* store value into lvalue object */+                put_lvalue(s, opcode, scope, var_name,+                           label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,+                           (tok == TOK_CONST || tok == TOK_LET));+            }+            if (s->token.val == ']')+                break;+            if (has_spread)+                return js_parse_error(s, "rest element must be the last one");+            /* accept a trailing comma before the ']' */+            if (js_parse_expect(s, ','))+                return -1;+        }+        /* close iterator object:+           if completed, enum_obj has been replaced by undefined */+        emit_op(s, OP_iterator_close);+        pop_break_entry(s->cur_func);+        if (next_token(s))+            return -1;+    } else {+        return js_parse_error(s, "invalid assignment syntax");+    }+    if (s->token.val == '=' && allow_initializer) {+        label_done = emit_goto(s, OP_goto, -1);+        if (next_token(s))+            return -1;+        emit_label(s, label_parse);+        if (hasval)+            emit_op(s, OP_drop);+        if (js_parse_assign_expr(s))+            return -1;+        emit_goto(s, OP_goto, label_assign);+        emit_label(s, label_done);+        has_initializer = TRUE;+    } else {+        /* normally hasval is true except if+           js_parse_skip_parens_token() was wrong in the parsing */+        //        assert(hasval);+        if (!hasval) {+            js_parse_error(s, "too complicated destructuring expression");+            return -1;+        }+        /* remove test and decrement label ref count */+        memset(s->cur_func->byte_code.buf + start_addr, OP_nop,+               assign_addr - start_addr);+        s->cur_func->label_slots[label_parse].ref_count--;+        has_initializer = FALSE;+    }+    return has_initializer;++ prop_error:+    JS_FreeAtom(s->ctx, prop_name);+ var_error:+    JS_FreeAtom(s->ctx, var_name);+    return -1;+}++typedef enum FuncCallType {+    FUNC_CALL_NORMAL,+    FUNC_CALL_NEW,+    FUNC_CALL_SUPER_CTOR,+    FUNC_CALL_TEMPLATE,+} FuncCallType;++static void optional_chain_test(JSParseState *s, int *poptional_chaining_label,+                                int drop_count)+{+    int label_next, i;+    if (*poptional_chaining_label < 0)+        *poptional_chaining_label = new_label(s);+   /* XXX: could be more efficient with a specific opcode */+    emit_op(s, OP_dup);+    emit_op(s, OP_is_undefined_or_null);+    label_next = emit_goto(s, OP_if_false, -1);+    for(i = 0; i < drop_count; i++)+        emit_op(s, OP_drop);+    emit_op(s, OP_undefined);+    emit_goto(s, OP_goto, *poptional_chaining_label);+    emit_label(s, label_next);+}++/* allowed parse_flags: PF_POSTFIX_CALL, PF_ARROW_FUNC */+static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)+{+    FuncCallType call_type;+    int optional_chaining_label;+    BOOL accept_lparen = (parse_flags & PF_POSTFIX_CALL) != 0;+    +    call_type = FUNC_CALL_NORMAL;+    switch(s->token.val) {+    case TOK_NUMBER:+        {+            JSValue val;+            val = s->token.u.num.val;++            if (JS_VALUE_GET_TAG(val) == JS_TAG_INT) {+                emit_op(s, OP_push_i32);+                emit_u32(s, JS_VALUE_GET_INT(val));+            } else+#ifdef CONFIG_BIGNUM+            if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_FLOAT) {+                slimb_t e;+                int ret;++                /* need a runtime conversion */+                /* XXX: could add a cache and/or do it once at+                   the start of the function */+                if (emit_push_const(s, val, 0) < 0)+                    return -1;+                e = s->token.u.num.exponent;+                if (e == (int32_t)e) {+                    emit_op(s, OP_push_i32);+                    emit_u32(s, e);+                } else {+                    val = JS_NewBigInt64_1(s->ctx, e);+                    if (JS_IsException(val))+                        return -1;+                    ret = emit_push_const(s, val, 0);+                    JS_FreeValue(s->ctx, val);+                    if (ret < 0)+                        return -1;+                }+                emit_op(s, OP_mul_pow10);+            } else+#endif+            {+                if (emit_push_const(s, val, 0) < 0)+                    return -1;+            }+        }+        if (next_token(s))+            return -1;+        break;+    case TOK_TEMPLATE:+        if (js_parse_template(s, 0, NULL))+            return -1;+        break;+    case TOK_STRING:+        if (emit_push_const(s, s->token.u.str.str, 1))+            return -1;+        if (next_token(s))+            return -1;+        break;+        +    case TOK_DIV_ASSIGN:+        s->buf_ptr -= 2;+        goto parse_regexp;+    case '/':+        s->buf_ptr--;+    parse_regexp:+        {+            JSValue str;+            int ret, backtrace_flags;+            if (!s->ctx->compile_regexp)+                return js_parse_error(s, "RegExp are not supported");+            /* the previous token is '/' or '/=', so no need to free */+            if (js_parse_regexp(s))+                return -1;+            ret = emit_push_const(s, s->token.u.regexp.body, 0);+            str = s->ctx->compile_regexp(s->ctx, s->token.u.regexp.body,+                                         s->token.u.regexp.flags);+            if (JS_IsException(str)) {+                /* add the line number info */+                backtrace_flags = 0;+                if (s->cur_func && s->cur_func->backtrace_barrier)+                    backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;+                build_backtrace(s->ctx, s->ctx->rt->current_exception,+                                s->filename, s->token.line_num,+                                backtrace_flags);+                return -1;+            }+            ret = emit_push_const(s, str, 0);+            JS_FreeValue(s->ctx, str);+            if (ret)+                return -1;+            /* we use a specific opcode to be sure the correct+               function is called (otherwise the bytecode would have+               to be verified by the RegExp constructor) */+            emit_op(s, OP_regexp);+            if (next_token(s))+                return -1;+        }+        break;+    case '(':+        if ((parse_flags & PF_ARROW_FUNC) &&+            js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) {+            if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,+                                       JS_FUNC_NORMAL, JS_ATOM_NULL,+                                       s->token.ptr, s->token.line_num))+                return -1;+        } else {+            if (js_parse_expr_paren(s))+                return -1;+        }+        break;+    case TOK_FUNCTION:+        if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,+                                   JS_FUNC_NORMAL, JS_ATOM_NULL,+                                   s->token.ptr, s->token.line_num))+            return -1;+        break;+    case TOK_CLASS:+        if (js_parse_class(s, TRUE, JS_PARSE_EXPORT_NONE))+            return -1;+        break;+    case TOK_NULL:+        if (next_token(s))+            return -1;+        emit_op(s, OP_null);+        break;+    case TOK_THIS:+        if (next_token(s))+            return -1;+        emit_op(s, OP_scope_get_var);+        emit_atom(s, JS_ATOM_this);+        emit_u16(s, 0);+        break;+    case TOK_FALSE:+        if (next_token(s))+            return -1;+        emit_op(s, OP_push_false);+        break;+    case TOK_TRUE:+        if (next_token(s))+            return -1;+        emit_op(s, OP_push_true);+        break;+    case TOK_IDENT:+        {+            JSAtom name;+            if (s->token.u.ident.is_reserved) {+                return js_parse_error_reserved_identifier(s);+            }+            if ((parse_flags & PF_ARROW_FUNC) &&+                peek_token(s, TRUE) == TOK_ARROW) {+                if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,+                                           JS_FUNC_NORMAL, JS_ATOM_NULL,+                                           s->token.ptr, s->token.line_num))+                    return -1;+            } else if (token_is_pseudo_keyword(s, JS_ATOM_async) &&+                       peek_token(s, TRUE) != '\n') {+                const uint8_t *source_ptr;+                int source_line_num;++                source_ptr = s->token.ptr;+                source_line_num = s->token.line_num;+                if (next_token(s))+                    return -1;+                if (s->token.val == TOK_FUNCTION) {+                    if (js_parse_function_decl(s, JS_PARSE_FUNC_EXPR,+                                               JS_FUNC_ASYNC, JS_ATOM_NULL,+                                               source_ptr, source_line_num))+                        return -1;+                } else if ((parse_flags & PF_ARROW_FUNC) &&+                           ((s->token.val == '(' &&+                             js_parse_skip_parens_token(s, NULL, TRUE) == TOK_ARROW) ||+                            (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&+                             peek_token(s, TRUE) == TOK_ARROW))) {+                    if (js_parse_function_decl(s, JS_PARSE_FUNC_ARROW,+                                               JS_FUNC_ASYNC, JS_ATOM_NULL,+                                               source_ptr, source_line_num))+                        return -1;+                } else {+                    name = JS_DupAtom(s->ctx, JS_ATOM_async);+                    goto do_get_var;+                }+            } else {+                if (s->token.u.ident.atom == JS_ATOM_arguments &&+                    !s->cur_func->arguments_allowed) {+                    js_parse_error(s, "'arguments' identifier is not allowed in class field initializer");+                    return -1;+                }+                name = JS_DupAtom(s->ctx, s->token.u.ident.atom);+                if (next_token(s))  /* update line number before emitting code */+                    return -1;+            do_get_var:+                emit_op(s, OP_scope_get_var);+                emit_u32(s, name);+                emit_u16(s, s->cur_func->scope_level);+            }+        }+        break;+    case '{':+    case '[':+        {+            int skip_bits;+            if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {+                if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)+                    return -1;+            } else {+                if (s->token.val == '{') {+                    if (js_parse_object_literal(s))+                        return -1;+                } else {+                    if (js_parse_array_literal(s))+                        return -1;+                }+            }+        }+        break;+    case TOK_NEW:+        if (next_token(s))+            return -1;+        if (s->token.val == '.') {+            if (next_token(s))+                return -1;+            if (!token_is_pseudo_keyword(s, JS_ATOM_target))+                return js_parse_error(s, "expecting target");+            if (!s->cur_func->new_target_allowed)+                return js_parse_error(s, "new.target only allowed within functions");+            if (next_token(s))+                return -1;+            emit_op(s, OP_scope_get_var);+            emit_atom(s, JS_ATOM_new_target);+            emit_u16(s, 0);+        } else {+            if (js_parse_postfix_expr(s, 0))+                return -1;+            accept_lparen = TRUE;+            if (s->token.val != '(') {+                /* new operator on an object */+                emit_op(s, OP_dup);+                emit_op(s, OP_call_constructor);+                emit_u16(s, 0);+            } else {+                call_type = FUNC_CALL_NEW;+            }+        }+        break;+    case TOK_SUPER:+        if (next_token(s))+            return -1;+        if (s->token.val == '(') {+            if (!s->cur_func->super_call_allowed)+                return js_parse_error(s, "super() is only valid in a derived class constructor");+            call_type = FUNC_CALL_SUPER_CTOR;+        } else if (s->token.val == '.' || s->token.val == '[') {+            if (!s->cur_func->super_allowed)+                return js_parse_error(s, "'super' is only valid in a method");+            emit_op(s, OP_scope_get_var);+            emit_atom(s, JS_ATOM_this);+            emit_u16(s, 0);+            emit_op(s, OP_scope_get_var);+            emit_atom(s, JS_ATOM_home_object);+            emit_u16(s, 0);+            emit_op(s, OP_get_super);+        } else {+            return js_parse_error(s, "invalid use of 'super'");+        }+        break;+    case TOK_IMPORT:+        if (next_token(s))+            return -1;+        if (s->token.val == '.') {+            if (next_token(s))+                return -1;+            if (!token_is_pseudo_keyword(s, JS_ATOM_meta))+                return js_parse_error(s, "meta expected");+            if (!s->is_module)+                return js_parse_error(s, "import.meta only valid in module code");+            if (next_token(s))+                return -1;+            emit_op(s, OP_special_object);+            emit_u8(s, OP_SPECIAL_OBJECT_IMPORT_META);+        } else {+            if (js_parse_expect(s, '('))+                return -1;+            if (!accept_lparen)+                return js_parse_error(s, "invalid use of 'import()'");+            if (js_parse_assign_expr(s))+                return -1;+            if (js_parse_expect(s, ')'))+                return -1;+            emit_op(s, OP_import);+        }+        break;+    default:+        return js_parse_error(s, "unexpected token in expression: '%.*s'",+                              (int)(s->buf_ptr - s->token.ptr), s->token.ptr);+    }++    optional_chaining_label = -1;+    for(;;) {+        JSFunctionDef *fd = s->cur_func;+        BOOL has_optional_chain = FALSE;+        +        if (s->token.val == TOK_QUESTION_MARK_DOT) {+            /* optional chaining */+            if (next_token(s))+                return -1;+            has_optional_chain = TRUE;+            if (s->token.val == '(' && accept_lparen) {+                goto parse_func_call;+            } else if (s->token.val == '[') {+                goto parse_array_access;+            } else {+                goto parse_property;+            }+        } else if (s->token.val == TOK_TEMPLATE &&+                   call_type == FUNC_CALL_NORMAL) {+            if (optional_chaining_label >= 0) {+                return js_parse_error(s, "template literal cannot appear in an optional chain");+            }+            call_type = FUNC_CALL_TEMPLATE;+            goto parse_func_call2;+        } else if (s->token.val == '(' && accept_lparen) {+            int opcode, arg_count, drop_count;++            /* function call */+        parse_func_call:+            if (next_token(s))+                return -1;++            if (call_type == FUNC_CALL_NORMAL) {+            parse_func_call2:+                switch(opcode = get_prev_opcode(fd)) {+                case OP_get_field:+                    /* keep the object on the stack */+                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_field2;+                    drop_count = 2;+                    break;+                case OP_scope_get_private_field:+                    /* keep the object on the stack */+                    fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_private_field2;+                    drop_count = 2;+                    break;+                case OP_get_array_el:+                    /* keep the object on the stack */+                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el2;+                    drop_count = 2;+                    break;+                case OP_scope_get_var:+                    {+                        JSAtom name;+                        int scope;+                        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+                        scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5);+                        if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL && !has_optional_chain) {+                            /* direct 'eval' */+                            opcode = OP_eval;+                        } else {+                            /* verify if function name resolves to a simple+                               get_loc/get_arg: a function call inside a `with`+                               statement can resolve to a method call of the+                               `with` context object+                             */+                            /* XXX: always generate the OP_scope_get_ref+                               and remove it in variable resolution+                               pass ? */+                            if (has_with_scope(fd, scope)) {+                                opcode = OP_scope_get_ref;+                                fd->byte_code.buf[fd->last_opcode_pos] = opcode;+                            }+                        }+                        drop_count = 1;+                    }+                    break;+                case OP_get_super_value:+                    fd->byte_code.buf[fd->last_opcode_pos] = OP_get_array_el;+                    /* on stack: this func_obj */+                    opcode = OP_get_array_el;+                    drop_count = 2;+                    break;+                default:+                    opcode = OP_invalid;+                    drop_count = 1;+                    break;+                }+                if (has_optional_chain) {+                    optional_chain_test(s, &optional_chaining_label,+                                        drop_count);+                }+            } else {+                opcode = OP_invalid;+            }++            if (call_type == FUNC_CALL_TEMPLATE) {+                if (js_parse_template(s, 1, &arg_count))+                    return -1;+                goto emit_func_call;+            } else if (call_type == FUNC_CALL_SUPER_CTOR) {+                emit_op(s, OP_scope_get_var);+                emit_atom(s, JS_ATOM_this_active_func);+                emit_u16(s, 0);++                emit_op(s, OP_get_super);++                emit_op(s, OP_scope_get_var);+                emit_atom(s, JS_ATOM_new_target);+                emit_u16(s, 0);+            } else if (call_type == FUNC_CALL_NEW) {+                emit_op(s, OP_dup); /* new.target = function */+            }++            /* parse arguments */+            arg_count = 0;+            while (s->token.val != ')') {+                if (arg_count >= 65535) {+                    return js_parse_error(s, "Too many call arguments");+                }+                if (s->token.val == TOK_ELLIPSIS)+                    break;+                if (js_parse_assign_expr(s))+                    return -1;+                arg_count++;+                if (s->token.val == ')')+                    break;+                /* accept a trailing comma before the ')' */+                if (js_parse_expect(s, ','))+                    return -1;+            }+            if (s->token.val == TOK_ELLIPSIS) {+                emit_op(s, OP_array_from);+                emit_u16(s, arg_count);+                emit_op(s, OP_push_i32);+                emit_u32(s, arg_count);++                /* on stack: array idx */+                while (s->token.val != ')') {+                    if (s->token.val == TOK_ELLIPSIS) {+                        if (next_token(s))+                            return -1;+                        if (js_parse_assign_expr(s))+                            return -1;+#if 1+                        /* XXX: could pass is_last indicator? */+                        emit_op(s, OP_append);+#else+                        int label_next, label_done;+                        label_next = new_label(s);+                        label_done = new_label(s);+                        /* push enumerate object below array/idx pair */+                        emit_op(s, OP_for_of_start);+                        emit_op(s, OP_rot5l);+                        emit_op(s, OP_rot5l);+                        emit_label(s, label_next);+                        /* on stack: enum_rec array idx */+                        emit_op(s, OP_for_of_next);+                        emit_u8(s, 2);+                        emit_goto(s, OP_if_true, label_done);+                        /* append element */+                        /* enum_rec array idx val -> enum_rec array new_idx */+                        emit_op(s, OP_define_array_el);+                        emit_op(s, OP_inc);+                        emit_goto(s, OP_goto, label_next);+                        emit_label(s, label_done);+                        /* close enumeration, drop enum_rec and idx */+                        emit_op(s, OP_drop); /* drop undef */+                        emit_op(s, OP_nip1); /* drop enum_rec */+                        emit_op(s, OP_nip1);+                        emit_op(s, OP_nip1);+#endif+                    } else {+                        if (js_parse_assign_expr(s))+                            return -1;+                        /* array idx val */+                        emit_op(s, OP_define_array_el);+                        emit_op(s, OP_inc);+                    }+                    if (s->token.val == ')')+                        break;+                    /* accept a trailing comma before the ')' */+                    if (js_parse_expect(s, ','))+                        return -1;+                }+                if (next_token(s))+                    return -1;+                /* drop the index */+                emit_op(s, OP_drop);++                /* apply function call */+                switch(opcode) {+                case OP_get_field:+                case OP_scope_get_private_field:+                case OP_get_array_el:+                case OP_scope_get_ref:+                    /* obj func array -> func obj array */+                    emit_op(s, OP_perm3);+                    emit_op(s, OP_apply);+                    emit_u16(s, call_type == FUNC_CALL_NEW);+                    break;+                case OP_eval:+                    emit_op(s, OP_apply_eval);+                    emit_u16(s, fd->scope_level);+                    fd->has_eval_call = TRUE;+                    break;+                default:+                    if (call_type == FUNC_CALL_SUPER_CTOR) {+                        emit_op(s, OP_apply);+                        emit_u16(s, 1);+                        /* set the 'this' value */+                        emit_op(s, OP_dup);+                        emit_op(s, OP_scope_put_var_init);+                        emit_atom(s, JS_ATOM_this);+                        emit_u16(s, 0);++                        emit_class_field_init(s);+                    } else if (call_type == FUNC_CALL_NEW) {+                        /* obj func array -> func obj array */+                        emit_op(s, OP_perm3);+                        emit_op(s, OP_apply);+                        emit_u16(s, 1);+                    } else {+                        /* func array -> func undef array */+                        emit_op(s, OP_undefined);+                        emit_op(s, OP_swap);+                        emit_op(s, OP_apply);+                        emit_u16(s, 0);+                    }+                    break;+                }+            } else {+                if (next_token(s))+                    return -1;+            emit_func_call:+                switch(opcode) {+                case OP_get_field:+                case OP_scope_get_private_field:+                case OP_get_array_el:+                case OP_scope_get_ref:+                    emit_op(s, OP_call_method);+                    emit_u16(s, arg_count);+                    break;+                case OP_eval:+                    emit_op(s, OP_eval);+                    emit_u16(s, arg_count);+                    emit_u16(s, fd->scope_level);+                    fd->has_eval_call = TRUE;+                    break;+                default:+                    if (call_type == FUNC_CALL_SUPER_CTOR) {+                        emit_op(s, OP_call_constructor);+                        emit_u16(s, arg_count);++                        /* set the 'this' value */+                        emit_op(s, OP_dup);+                        emit_op(s, OP_scope_put_var_init);+                        emit_atom(s, JS_ATOM_this);+                        emit_u16(s, 0);++                        emit_class_field_init(s);+                    } else if (call_type == FUNC_CALL_NEW) {+                        emit_op(s, OP_call_constructor);+                        emit_u16(s, arg_count);+                    } else {+                        emit_op(s, OP_call);+                        emit_u16(s, arg_count);+                    }+                    break;+                }+            }+            call_type = FUNC_CALL_NORMAL;+        } else if (s->token.val == '.') {+            if (next_token(s))+                return -1;+        parse_property:+            if (s->token.val == TOK_PRIVATE_NAME) {+                /* private class field */+                if (get_prev_opcode(fd) == OP_get_super) {+                    return js_parse_error(s, "private class field forbidden after super");+                }+                if (has_optional_chain) {+                    optional_chain_test(s, &optional_chaining_label, 1);+                }+                emit_op(s, OP_scope_get_private_field);+                emit_atom(s, s->token.u.ident.atom);+                emit_u16(s, s->cur_func->scope_level);+            } else {+                if (!token_is_ident(s->token.val)) {+                    return js_parse_error(s, "expecting field name");+                }+                if (get_prev_opcode(fd) == OP_get_super) {+                    JSValue val;+                    int ret;+                    val = JS_AtomToValue(s->ctx, s->token.u.ident.atom);+                    ret = emit_push_const(s, val, 1);+                    JS_FreeValue(s->ctx, val);+                    if (ret)+                        return -1;+                    emit_op(s, OP_get_super_value);+                } else {+                    if (has_optional_chain) {+                        optional_chain_test(s, &optional_chaining_label, 1);+                    }+                    emit_op(s, OP_get_field);+                    emit_atom(s, s->token.u.ident.atom);+                }+            }+            if (next_token(s))+                return -1;+        } else if (s->token.val == '[') {+            int prev_op;++        parse_array_access:+            prev_op = get_prev_opcode(fd);+            if (has_optional_chain) {+                optional_chain_test(s, &optional_chaining_label, 1);+            }+            if (next_token(s))+                return -1;+            if (js_parse_expr(s))+                return -1;+            if (js_parse_expect(s, ']'))+                return -1;+            if (prev_op == OP_get_super) {+                emit_op(s, OP_get_super_value);+            } else {+                emit_op(s, OP_get_array_el);+            }+        } else {+            break;+        }+    }+    if (optional_chaining_label >= 0)+        emit_label(s, optional_chaining_label);+    return 0;+}++static __exception int js_parse_delete(JSParseState *s)+{+    JSFunctionDef *fd = s->cur_func;+    JSAtom name;+    int opcode;++    if (next_token(s))+        return -1;+    if (js_parse_unary(s, PF_POW_FORBIDDEN))+        return -1;+    switch(opcode = get_prev_opcode(fd)) {+    case OP_get_field:+        {+            JSValue val;+            int ret;++            name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+            fd->byte_code.size = fd->last_opcode_pos;+            fd->last_opcode_pos = -1;+            val = JS_AtomToValue(s->ctx, name);+            ret = emit_push_const(s, val, 1);+            JS_FreeValue(s->ctx, val);+            JS_FreeAtom(s->ctx, name);+            if (ret)+                return ret;+        }+        goto do_delete;+    case OP_get_array_el:+        fd->byte_code.size = fd->last_opcode_pos;+        fd->last_opcode_pos = -1;+    do_delete:+        emit_op(s, OP_delete);+        break;+    case OP_scope_get_var:+        /* 'delete this': this is not a reference */+        name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1);+        if (name == JS_ATOM_this || name == JS_ATOM_new_target)+            goto ret_true;+        if (fd->js_mode & JS_MODE_STRICT) {+            return js_parse_error(s, "cannot delete a direct reference in strict mode");+        } else {+            fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_delete_var;+        }+        break;+    case OP_scope_get_private_field:+        return js_parse_error(s, "cannot delete a private class field");+    case OP_get_super_value:+        emit_op(s, OP_throw_error);+        emit_atom(s, JS_ATOM_NULL);+        emit_u8(s, JS_THROW_ERROR_DELETE_SUPER);+        break;+    default:+    ret_true:+        emit_op(s, OP_drop);+        emit_op(s, OP_push_true);+        break;+    }+    return 0;+}++/* allowed parse_flags: PF_ARROW_FUNC, PF_POW_ALLOWED, PF_POW_FORBIDDEN */+static __exception int js_parse_unary(JSParseState *s, int parse_flags)+{+    int op;++    switch(s->token.val) {+    case '+':+    case '-':+    case '!':+    case '~':+    case TOK_VOID:+        op = s->token.val;+        if (next_token(s))+            return -1;+        if (js_parse_unary(s, PF_POW_FORBIDDEN))+            return -1;+        switch(op) {+        case '-':+            emit_op(s, OP_neg);+            break;+        case '+':+            emit_op(s, OP_plus);+            break;+        case '!':+            emit_op(s, OP_lnot);+            break;+        case '~':+            emit_op(s, OP_not);+            break;+        case TOK_VOID:+            emit_op(s, OP_drop);+            emit_op(s, OP_undefined);+            break;+        default:+            abort();+        }+        parse_flags = 0;+        break;+    case TOK_DEC:+    case TOK_INC:+        {+            int opcode, op, scope, label;+            JSAtom name;+            op = s->token.val;+            if (next_token(s))+                return -1;+            if (js_parse_unary(s, 0))+                return -1;+            if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))+                return -1;+            emit_op(s, OP_dec + op - TOK_DEC);+            put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP,+                       FALSE);+        }+        break;+    case TOK_TYPEOF:+        {+            JSFunctionDef *fd;+            if (next_token(s))+                return -1;+            if (js_parse_unary(s, PF_POW_FORBIDDEN))+                return -1;+            /* reference access should not return an exception, so we+               patch the get_var */+            fd = s->cur_func;+            if (get_prev_opcode(fd) == OP_scope_get_var) {+                fd->byte_code.buf[fd->last_opcode_pos] = OP_scope_get_var_undef;+            }+            emit_op(s, OP_typeof);+            parse_flags = 0;+        }+        break;+    case TOK_DELETE:+        if (js_parse_delete(s))+            return -1;+        parse_flags = 0;+        break;+    case TOK_AWAIT:+        if (!(s->cur_func->func_kind & JS_FUNC_ASYNC))+            return js_parse_error(s, "unexpected 'await' keyword");+        if (!s->cur_func->in_function_body)+            return js_parse_error(s, "await in default expression");+        if (next_token(s))+            return -1;+        if (js_parse_unary(s, PF_POW_FORBIDDEN))+            return -1;+        emit_op(s, OP_await);+        parse_flags = 0;+        break;+    default:+        if (js_parse_postfix_expr(s, (parse_flags & PF_ARROW_FUNC) |+                                  PF_POSTFIX_CALL))+            return -1;+        if (!s->got_lf &&+            (s->token.val == TOK_DEC || s->token.val == TOK_INC)) {+            int opcode, op, scope, label;+            JSAtom name;+            op = s->token.val;+            if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, TRUE, op))+                return -1;+            emit_op(s, OP_post_dec + op - TOK_DEC);+            put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_SECOND,+                       FALSE);+            if (next_token(s))+                return -1;        +        }+        break;+    }+    if (parse_flags & (PF_POW_ALLOWED | PF_POW_FORBIDDEN)) {+#ifdef CONFIG_BIGNUM+        if (s->token.val == TOK_POW || s->token.val == TOK_MATH_POW) {+            /* Extended exponentiation syntax rules: we extend the ES7+               grammar in order to have more intuitive semantics:+               -2**2 evaluates to -4. */+            if (!(s->cur_func->js_mode & JS_MODE_MATH)) {+                if (parse_flags & PF_POW_FORBIDDEN) {+                    JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");+                    return -1;+                }+            }+            if (next_token(s))+                return -1;+            if (js_parse_unary(s, PF_POW_ALLOWED))+                return -1;+            emit_op(s, OP_pow);+        }+#else+        if (s->token.val == TOK_POW) {+            /* Strict ES7 exponentiation syntax rules: To solve+               conficting semantics between different implementations+               regarding the precedence of prefix operators and the+               postifx exponential, ES7 specifies that -2**2 is a+               syntax error. */+            if (parse_flags & PF_POW_FORBIDDEN) {+                JS_ThrowSyntaxError(s->ctx, "unparenthesized unary expression can't appear on the left-hand side of '**'");+                return -1;+            }+            if (next_token(s))+                return -1;+            if (js_parse_unary(s, PF_POW_ALLOWED))+                return -1;+            emit_op(s, OP_pow);+        }+#endif+    }+    return 0;+}++/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */+static __exception int js_parse_expr_binary(JSParseState *s, int level,+                                            int parse_flags)+{+    int op, opcode;++    if (level == 0) {+        return js_parse_unary(s, (parse_flags & PF_ARROW_FUNC) |+                              PF_POW_ALLOWED);+    }+    if (js_parse_expr_binary(s, level - 1, parse_flags))+        return -1;+    for(;;) {+        op = s->token.val;+        switch(level) {+        case 1:+            switch(op) {+            case '*':+                opcode = OP_mul;+                break;+            case '/':+                opcode = OP_div;+                break;+            case '%':+#ifdef CONFIG_BIGNUM+                if (s->cur_func->js_mode & JS_MODE_MATH)+                    opcode = OP_math_mod;+                else+#endif+                    opcode = OP_mod;+                break;+            default:+                return 0;+            }+            break;+        case 2:+            switch(op) {+            case '+':+                opcode = OP_add;+                break;+            case '-':+                opcode = OP_sub;+                break;+            default:+                return 0;+            }+            break;+        case 3:+            switch(op) {+            case TOK_SHL:+                opcode = OP_shl;+                break;+            case TOK_SAR:+                opcode = OP_sar;+                break;+            case TOK_SHR:+                opcode = OP_shr;+                break;+            default:+                return 0;+            }+            break;+        case 4:+            switch(op) {+            case '<':+                opcode = OP_lt;+                break;+            case '>':+                opcode = OP_gt;+                break;+            case TOK_LTE:+                opcode = OP_lte;+                break;+            case TOK_GTE:+                opcode = OP_gte;+                break;+            case TOK_INSTANCEOF:+                opcode = OP_instanceof;+                break;+            case TOK_IN:+                if (parse_flags & PF_IN_ACCEPTED) {+                    opcode = OP_in;+                } else {+                    return 0;+                }+                break;+            default:+                return 0;+            }+            break;+        case 5:+            switch(op) {+            case TOK_EQ:+                opcode = OP_eq;+                break;+            case TOK_NEQ:+                opcode = OP_neq;+                break;+            case TOK_STRICT_EQ:+                opcode = OP_strict_eq;+                break;+            case TOK_STRICT_NEQ:+                opcode = OP_strict_neq;+                break;+            default:+                return 0;+            }+            break;+        case 6:+            switch(op) {+            case '&':+                opcode = OP_and;+                break;+            default:+                return 0;+            }+            break;+        case 7:+            switch(op) {+            case '^':+                opcode = OP_xor;+                break;+            default:+                return 0;+            }+            break;+        case 8:+            switch(op) {+            case '|':+                opcode = OP_or;+                break;+            default:+                return 0;+            }+            break;+        default:+            abort();+        }+        if (next_token(s))+            return -1;+        if (js_parse_expr_binary(s, level - 1, parse_flags & ~PF_ARROW_FUNC))+            return -1;+        emit_op(s, opcode);+    }+    return 0;+}++/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */+static __exception int js_parse_logical_and_or(JSParseState *s, int op,+                                               int parse_flags)+{+    int label1;++    if (op == TOK_LAND) {+        if (js_parse_expr_binary(s, 8, parse_flags))+            return -1;+    } else {+        if (js_parse_logical_and_or(s, TOK_LAND, parse_flags))+            return -1;+    }+    if (s->token.val == op) {+        label1 = new_label(s);++        for(;;) {+            if (next_token(s))+                return -1;+            emit_op(s, OP_dup);+            emit_goto(s, op == TOK_LAND ? OP_if_false : OP_if_true, label1);+            emit_op(s, OP_drop);++            if (op == TOK_LAND) {+                if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))+                    return -1;+            } else {+                if (js_parse_logical_and_or(s, TOK_LAND,+                                            parse_flags & ~PF_ARROW_FUNC))+                    return -1;+            }+            if (s->token.val != op) {+                if (s->token.val == TOK_DOUBLE_QUESTION_MARK)+                    return js_parse_error(s, "cannot mix ?? with && or ||");+                break;+            }+        }++        emit_label(s, label1);+    }+    return 0;+}++static __exception int js_parse_coalesce_expr(JSParseState *s, int parse_flags)+{+    int label1;+    +    if (js_parse_logical_and_or(s, TOK_LOR, parse_flags))+        return -1;+    if (s->token.val == TOK_DOUBLE_QUESTION_MARK) {+        label1 = new_label(s);+        for(;;) {+            if (next_token(s))+                return -1;+            +            emit_op(s, OP_dup);+            emit_op(s, OP_is_undefined_or_null);+            emit_goto(s, OP_if_false, label1);+            emit_op(s, OP_drop);+            +            if (js_parse_expr_binary(s, 8, parse_flags & ~PF_ARROW_FUNC))+                return -1;+            if (s->token.val != TOK_DOUBLE_QUESTION_MARK)+                break;+        }+        emit_label(s, label1);+    }+    return 0;+}++/* allowed parse_flags: PF_ARROW_FUNC, PF_IN_ACCEPTED */+static __exception int js_parse_cond_expr(JSParseState *s, int parse_flags)+{+    int label1, label2;++    if (js_parse_coalesce_expr(s, parse_flags))+        return -1;+    if (s->token.val == '?') {+        if (next_token(s))+            return -1;+        label1 = emit_goto(s, OP_if_false, -1);++        if (js_parse_assign_expr(s))+            return -1;+        if (js_parse_expect(s, ':'))+            return -1;++        label2 = emit_goto(s, OP_goto, -1);++        emit_label(s, label1);++        if (js_parse_assign_expr2(s, parse_flags & PF_IN_ACCEPTED))+            return -1;++        emit_label(s, label2);+    }+    return 0;+}++static void emit_return(JSParseState *s, BOOL hasval);++/* allowed parse_flags: PF_IN_ACCEPTED */+static __exception int js_parse_assign_expr2(JSParseState *s, int parse_flags)+{+    int opcode, op, scope;+    JSAtom name0 = JS_ATOM_NULL;+    JSAtom name;++    if (s->token.val == TOK_YIELD) {+        BOOL is_star = FALSE, is_async;+        +        if (!(s->cur_func->func_kind & JS_FUNC_GENERATOR))+            return js_parse_error(s, "unexpected 'yield' keyword");+        if (!s->cur_func->in_function_body)+            return js_parse_error(s, "yield in default expression");+        if (next_token(s))+            return -1;+        /* XXX: is there a better method to detect 'yield' without+           parameters ? */+        if (s->token.val != ';' && s->token.val != ')' &&+            s->token.val != ']' && s->token.val != '}' &&+            s->token.val != ',' && s->token.val != ':' && !s->got_lf) {+            if (s->token.val == '*') {+                is_star = TRUE;+                if (next_token(s))+                    return -1;+            }+            if (js_parse_assign_expr2(s, parse_flags))+                return -1;+        } else {+            emit_op(s, OP_undefined);+        }+        is_async = (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR);++        if (is_star) {+            int label_loop, label_return, label_next;+            int label_return1, label_yield, label_throw, label_throw1;+            int label_throw2;++            label_loop = new_label(s);+            label_yield = new_label(s);++            emit_op(s, is_async ? OP_for_await_of_start : OP_for_of_start);++            /* remove the catch offset (XXX: could avoid pushing back+               undefined) */+            emit_op(s, OP_drop);+            emit_op(s, OP_undefined);+            +            emit_op(s, OP_undefined); /* initial value */+            +            emit_label(s, label_loop);+            emit_op(s, OP_iterator_next);+            if (is_async)+                emit_op(s, OP_await);+            emit_op(s, OP_iterator_check_object);+            emit_op(s, OP_get_field2);+            emit_atom(s, JS_ATOM_done);+            label_next = emit_goto(s, OP_if_true, -1); /* end of loop */+            emit_label(s, label_yield);+            if (is_async) {+                /* OP_async_yield_star takes the value as parameter */+                emit_op(s, OP_get_field);+                emit_atom(s, JS_ATOM_value);+                emit_op(s, OP_await);+                emit_op(s, OP_async_yield_star);+            } else {+                /* OP_yield_star takes (value, done) as parameter */+                emit_op(s, OP_yield_star);+            }+            emit_op(s, OP_dup);+            label_return = emit_goto(s, OP_if_true, -1);+            emit_op(s, OP_drop);+            emit_goto(s, OP_goto, label_loop);+            +            emit_label(s, label_return);+            emit_op(s, OP_push_i32);+            emit_u32(s, 2);+            emit_op(s, OP_strict_eq);+            label_throw = emit_goto(s, OP_if_true, -1);+            +            /* return handling */+            if (is_async)+                emit_op(s, OP_await);+            emit_op(s, OP_iterator_call);+            emit_u8(s, 0);+            label_return1 = emit_goto(s, OP_if_true, -1);+            if (is_async)+                emit_op(s, OP_await);+            emit_op(s, OP_iterator_check_object);+            emit_op(s, OP_get_field2);+            emit_atom(s, JS_ATOM_done);+            emit_goto(s, OP_if_false, label_yield);++            emit_op(s, OP_get_field);+            emit_atom(s, JS_ATOM_value);+            +            emit_label(s, label_return1);+            emit_op(s, OP_nip);+            emit_op(s, OP_nip);+            emit_op(s, OP_nip);+            emit_return(s, TRUE);+            +            /* throw handling */+            emit_label(s, label_throw);+            emit_op(s, OP_iterator_call);+            emit_u8(s, 1);+            label_throw1 = emit_goto(s, OP_if_true, -1);+            if (is_async)+                emit_op(s, OP_await);+            emit_op(s, OP_iterator_check_object);+            emit_op(s, OP_get_field2);+            emit_atom(s, JS_ATOM_done);+            emit_goto(s, OP_if_false, label_yield);+            emit_goto(s, OP_goto, label_next);+            /* close the iterator and throw a type error exception */+            emit_label(s, label_throw1);+            emit_op(s, OP_iterator_call);+            emit_u8(s, 2);+            label_throw2 = emit_goto(s, OP_if_true, -1);+            if (is_async)+                emit_op(s, OP_await);+            emit_label(s, label_throw2);++            emit_op(s, OP_throw_error);+            emit_atom(s, JS_ATOM_NULL);+            emit_u8(s, JS_THROW_ERROR_ITERATOR_THROW);+            +            emit_label(s, label_next);+            emit_op(s, OP_get_field);+            emit_atom(s, JS_ATOM_value);+            emit_op(s, OP_nip); /* keep the value associated with+                                   done = true */+            emit_op(s, OP_nip);+            emit_op(s, OP_nip);+        } else {+            int label_next;+            +            if (is_async)+                emit_op(s, OP_await);+            emit_op(s, OP_yield);+            label_next = emit_goto(s, OP_if_false, -1);+            emit_return(s, TRUE);+            emit_label(s, label_next);+        }+        return 0;+    }+    if (s->token.val == TOK_IDENT) {+        /* name0 is used to check for OP_set_name pattern, not duplicated */+        name0 = s->token.u.ident.atom;+    }+    if (js_parse_cond_expr(s, parse_flags | PF_ARROW_FUNC))+        return -1;++    op = s->token.val;+    if (op == '=' || (op >= TOK_MUL_ASSIGN && op <= TOK_POW_ASSIGN)) {+        int label;+        if (next_token(s))+            return -1;+        if (get_lvalue(s, &opcode, &scope, &name, &label, NULL, (op != '='), op) < 0)+            return -1;++        if (js_parse_assign_expr2(s, parse_flags)) {+            JS_FreeAtom(s->ctx, name);+            return -1;+        }++        if (op == '=') {+            if (opcode == OP_get_ref_value && name == name0) {+                set_object_name(s, name);+            }+        } else {+            static const uint8_t assign_opcodes[] = {+                OP_mul, OP_div, OP_mod, OP_add, OP_sub,+                OP_shl, OP_sar, OP_shr, OP_and, OP_xor, OP_or,+#ifdef CONFIG_BIGNUM+                OP_pow,+#endif+                OP_pow,+            };+            op = assign_opcodes[op - TOK_MUL_ASSIGN];+#ifdef CONFIG_BIGNUM+            if (s->cur_func->js_mode & JS_MODE_MATH) {+                if (op == OP_mod)+                    op = OP_math_mod;+            }+#endif+            emit_op(s, op);+        }+        put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_KEEP_TOP, FALSE);+    } else if (op >= TOK_LAND_ASSIGN && op <= TOK_DOUBLE_QUESTION_MARK_ASSIGN) {+        int label, label1, depth_lvalue, label2;+        +        if (next_token(s))+            return -1;+        if (get_lvalue(s, &opcode, &scope, &name, &label,+                       &depth_lvalue, TRUE, op) < 0)+            return -1;++        emit_op(s, OP_dup);+        if (op == TOK_DOUBLE_QUESTION_MARK_ASSIGN)+            emit_op(s, OP_is_undefined_or_null);+        label1 = emit_goto(s, op == TOK_LOR_ASSIGN ? OP_if_true : OP_if_false,+                           -1);+        emit_op(s, OP_drop);+        +        if (js_parse_assign_expr2(s, parse_flags)) {+            JS_FreeAtom(s->ctx, name);+            return -1;+        }++        if (opcode == OP_get_ref_value && name == name0) {+            set_object_name(s, name);+        }+        +        switch(depth_lvalue) {+        case 1:+            emit_op(s, OP_insert2);+            break;+        case 2:+            emit_op(s, OP_insert3);+            break;+        case 3:+            emit_op(s, OP_insert4);+            break;+        default:+            abort();+        }++        /* XXX: we disable the OP_put_ref_value optimization by not+           using put_lvalue() otherwise depth_lvalue is not correct */+        put_lvalue(s, opcode, scope, name, label, PUT_LVALUE_NOKEEP_DEPTH,+                   FALSE);+        label2 = emit_goto(s, OP_goto, -1);+        +        emit_label(s, label1);++        /* remove the lvalue stack entries */+        while (depth_lvalue != 0) {+            emit_op(s, OP_nip);+            depth_lvalue--;+        }++        emit_label(s, label2);+    }+    return 0;+}++static __exception int js_parse_assign_expr(JSParseState *s)+{+    return js_parse_assign_expr2(s, PF_IN_ACCEPTED);+}++/* allowed parse_flags: PF_IN_ACCEPTED */+static __exception int js_parse_expr2(JSParseState *s, int parse_flags)+{+    BOOL comma = FALSE;+    for(;;) {+        if (js_parse_assign_expr2(s, parse_flags))+            return -1;+        if (comma) {+            /* prevent get_lvalue from using the last expression+               as an lvalue. This also prevents the conversion of+               of get_var to get_ref for method lookup in function+               call inside `with` statement.+             */+            s->cur_func->last_opcode_pos = -1;+        }+        if (s->token.val != ',')+            break;+        comma = TRUE;+        if (next_token(s))+            return -1;+        emit_op(s, OP_drop);+    }+    return 0;+}++static __exception int js_parse_expr(JSParseState *s)+{+    return js_parse_expr2(s, PF_IN_ACCEPTED);+}++static void push_break_entry(JSFunctionDef *fd, BlockEnv *be,+                             JSAtom label_name,+                             int label_break, int label_cont,+                             int drop_count)+{+    be->prev = fd->top_break;+    fd->top_break = be;+    be->label_name = label_name;+    be->label_break = label_break;+    be->label_cont = label_cont;+    be->drop_count = drop_count;+    be->label_finally = -1;+    be->scope_level = fd->scope_level;+    be->has_iterator = FALSE;+}++static void pop_break_entry(JSFunctionDef *fd)+{+    BlockEnv *be;+    be = fd->top_break;+    fd->top_break = be->prev;+}++static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont)+{+    BlockEnv *top;+    int i, scope_level;++    scope_level = s->cur_func->scope_level;+    top = s->cur_func->top_break;+    while (top != NULL) {+        close_scopes(s, scope_level, top->scope_level);+        scope_level = top->scope_level;+        if (is_cont &&+            top->label_cont != -1 &&+            (name == JS_ATOM_NULL || top->label_name == name)) {+            /* continue stays inside the same block */+            emit_goto(s, OP_goto, top->label_cont);+            return 0;+        }+        if (!is_cont &&+            top->label_break != -1 &&+            (name == JS_ATOM_NULL || top->label_name == name)) {+            emit_goto(s, OP_goto, top->label_break);+            return 0;+        }+        i = 0;+        if (top->has_iterator) {+            emit_op(s, OP_iterator_close);+            i += 3;+        }+        for(; i < top->drop_count; i++)+            emit_op(s, OP_drop);+        if (top->label_finally != -1) {+            /* must push dummy value to keep same stack depth */+            emit_op(s, OP_undefined);+            emit_goto(s, OP_gosub, top->label_finally);+            emit_op(s, OP_drop);+        }+        top = top->prev;+    }+    if (name == JS_ATOM_NULL) {+        if (is_cont)+            return js_parse_error(s, "continue must be inside loop");+        else+            return js_parse_error(s, "break must be inside loop or switch");+    } else {+        return js_parse_error(s, "break/continue label not found");+    }+}++/* execute the finally blocks before return */+static void emit_return(JSParseState *s, BOOL hasval)+{+    BlockEnv *top;+    int drop_count;++    drop_count = 0;+    top = s->cur_func->top_break;+    while (top != NULL) {+        /* XXX: emit the appropriate OP_leave_scope opcodes? Probably not+           required as all local variables will be closed upon returning+           from JS_CallInternal, but not in the same order. */+        if (top->has_iterator) {+            /* with 'yield', the exact number of OP_drop to emit is+               unknown, so we use a specific operation to look for+               the catch offset */+            if (!hasval) {+                emit_op(s, OP_undefined);+                hasval = TRUE;+            }+            emit_op(s, OP_iterator_close_return);+            if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {+                int label_next, label_next2;++                emit_op(s, OP_drop); /* catch offset */+                emit_op(s, OP_drop); /* next */+                emit_op(s, OP_get_field2);+                emit_atom(s, JS_ATOM_return);+                /* stack: iter_obj return_func */+                emit_op(s, OP_dup);+                emit_op(s, OP_is_undefined_or_null);+                label_next = emit_goto(s, OP_if_true, -1);+                emit_op(s, OP_call_method);+                emit_u16(s, 0);+                emit_op(s, OP_iterator_check_object);+                emit_op(s, OP_await);+                label_next2 = emit_goto(s, OP_goto, -1);+                emit_label(s, label_next);+                emit_op(s, OP_drop);+                emit_label(s, label_next2);+                emit_op(s, OP_drop);+            } else {+                emit_op(s, OP_iterator_close);+            }+            drop_count = -3;+        }+        drop_count += top->drop_count;+        if (top->label_finally != -1) {+            while(drop_count) {+                /* must keep the stack top if hasval */+                emit_op(s, hasval ? OP_nip : OP_drop);+                drop_count--;+            }+            if (!hasval) {+                /* must push return value to keep same stack size */+                emit_op(s, OP_undefined);+                hasval = TRUE;+            }+            emit_goto(s, OP_gosub, top->label_finally);+        }+        top = top->prev;+    }+    if (s->cur_func->is_derived_class_constructor) {+        int label_return;++        /* 'this' can be uninitialized, so it may be accessed only if+           the derived class constructor does not return an object */+        if (hasval) {+            emit_op(s, OP_check_ctor_return);+            label_return = emit_goto(s, OP_if_false, -1);+            emit_op(s, OP_drop);+        } else {+            label_return = -1;+        }++        /* XXX: if this is not initialized, should throw the+           ReferenceError in the caller realm */+        emit_op(s, OP_scope_get_var);+        emit_atom(s, JS_ATOM_this);+        emit_u16(s, 0);++        emit_label(s, label_return);+        emit_op(s, OP_return);+    } else if (s->cur_func->func_kind != JS_FUNC_NORMAL) {+        if (!hasval) {+            emit_op(s, OP_undefined);+        } else if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) {+            emit_op(s, OP_await);+        }+        emit_op(s, OP_return_async);+    } else {+        emit_op(s, hasval ? OP_return : OP_return_undef);+    }+}++#define DECL_MASK_FUNC  (1 << 0) /* allow normal function declaration */+/* ored with DECL_MASK_FUNC if function declarations are allowed with a label */+#define DECL_MASK_FUNC_WITH_LABEL (1 << 1)+#define DECL_MASK_OTHER (1 << 2) /* all other declarations */+#define DECL_MASK_ALL   (DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL | DECL_MASK_OTHER)++static __exception int js_parse_statement_or_decl(JSParseState *s,+                                                  int decl_mask);++static __exception int js_parse_statement(JSParseState *s)+{+    return js_parse_statement_or_decl(s, 0);+}++static __exception int js_parse_block(JSParseState *s)+{+    if (js_parse_expect(s, '{'))+        return -1;+    if (s->token.val != '}') {+        push_scope(s);+        for(;;) {+            if (js_parse_statement_or_decl(s, DECL_MASK_ALL))+                return -1;+            if (s->token.val == '}')+                break;+        }+        pop_scope(s);+    }+    if (next_token(s))+        return -1;+    return 0;+}++/* allowed parse_flags: PF_IN_ACCEPTED */+static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,+                                    BOOL export_flag)+{+    JSContext *ctx = s->ctx;+    JSFunctionDef *fd = s->cur_func;+    JSAtom name = JS_ATOM_NULL;++    for (;;) {+        if (s->token.val == TOK_IDENT) {+            if (s->token.u.ident.is_reserved) {+                return js_parse_error_reserved_identifier(s);+            }+            name = JS_DupAtom(ctx, s->token.u.ident.atom);+            if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_CONST)) {+                js_parse_error(s, "'let' is not a valid lexical identifier");+                goto var_error;+            }+            if (next_token(s))+                goto var_error;+            if (js_define_var(s, name, tok))+                goto var_error;+            if (export_flag) {+                if (!add_export_entry(s, s->cur_func->module, name, name,+                                      JS_EXPORT_TYPE_LOCAL))+                    goto var_error;+            }++            if (s->token.val == '=') {+                if (next_token(s))+                    goto var_error;+                if (tok == TOK_VAR) {+                    /* Must make a reference for proper `with` semantics */+                    int opcode, scope, label;+                    JSAtom name1;++                    emit_op(s, OP_scope_get_var);+                    emit_atom(s, name);+                    emit_u16(s, fd->scope_level);+                    if (get_lvalue(s, &opcode, &scope, &name1, &label, NULL, FALSE, '=') < 0)+                        goto var_error;+                    if (js_parse_assign_expr2(s, parse_flags)) {+                        JS_FreeAtom(ctx, name1);+                        goto var_error;+                    }+                    set_object_name(s, name);+                    put_lvalue(s, opcode, scope, name1, label,+                               PUT_LVALUE_NOKEEP, FALSE);+                } else {+                    if (js_parse_assign_expr2(s, parse_flags))+                        goto var_error;+                    set_object_name(s, name);+                    emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?+                        OP_scope_put_var_init : OP_scope_put_var);+                    emit_atom(s, name);+                    emit_u16(s, fd->scope_level);+                }+            } else {+                if (tok == TOK_CONST) {+                    js_parse_error(s, "missing initializer for const variable");+                    goto var_error;+                }+                if (tok == TOK_LET) {+                    /* initialize lexical variable upon entering its scope */+                    emit_op(s, OP_undefined);+                    emit_op(s, OP_scope_put_var_init);+                    emit_atom(s, name);+                    emit_u16(s, fd->scope_level);+                }+            }+            JS_FreeAtom(ctx, name);+        } else {+            int skip_bits;+            if ((s->token.val == '[' || s->token.val == '{')+            &&  js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {+                emit_op(s, OP_undefined);+                if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)+                    return -1;+            } else {+                return js_parse_error(s, "variable name expected");+            }+        }+        if (s->token.val != ',')+            break;+        if (next_token(s))+            return -1;+    }+    return 0;++ var_error:+    JS_FreeAtom(ctx, name);+    return -1;+}++/* test if the current token is a label. Use simplistic look-ahead scanner */+static BOOL is_label(JSParseState *s)+{+    return (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved &&+            peek_token(s, FALSE) == ':');+}++/* test if the current token is a let keyword. Use simplistic look-ahead scanner */+static int is_let(JSParseState *s, int decl_mask)+{+    int res = FALSE;++    if (token_is_pseudo_keyword(s, JS_ATOM_let)) {+#if 1+        JSParsePos pos;+        js_parse_get_pos(s, &pos);+        for (;;) {+            if (next_token(s)) {+                res = -1;+                break;+            }+            if (s->token.val == '[') {+                /* let [ is a syntax restriction:+                   it never introduces an ExpressionStatement */+                res = TRUE;+                break;+            }+            if (s->token.val == '{' ||+                (s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved) ||+                s->token.val == TOK_LET ||+                s->token.val == TOK_YIELD ||+                s->token.val == TOK_AWAIT) {+                /* Check for possible ASI if not scanning for Declaration */+                /* XXX: should also check that `{` introduces a BindingPattern,+                   but Firefox does not and rejects eval("let=1;let\n{if(1)2;}") */+                if (s->last_line_num == s->token.line_num || (decl_mask & DECL_MASK_OTHER)) {+                    res = TRUE;+                    break;+                }+                break;+            }+            break;+        }+        if (js_parse_seek_token(s, &pos)) {+            res = -1;+        }+#else+        int tok = peek_token(s, TRUE);+        if (tok == '{' || tok == TOK_IDENT || peek_token(s, FALSE) == '[') {+            res = TRUE;+        }+#endif+    }+    return res;+}++/* XXX: handle IteratorClose when exiting the loop before the+   enumeration is done */+static __exception int js_parse_for_in_of(JSParseState *s, int label_name,+                                          BOOL is_async)+{+    JSContext *ctx = s->ctx;+    JSFunctionDef *fd = s->cur_func;+    JSAtom var_name;+    BOOL has_initializer, is_for_of, has_destructuring;+    int tok, tok1, opcode, scope, block_scope_level;+    int label_next, label_expr, label_cont, label_body, label_break;+    int pos_next, pos_expr;+    BlockEnv break_entry;++    has_initializer = FALSE;+    has_destructuring = FALSE;+    is_for_of = FALSE;+    block_scope_level = fd->scope_level;+    label_cont = new_label(s);+    label_body = new_label(s);+    label_break = new_label(s);+    label_next = new_label(s);++    /* create scope for the lexical variables declared in the enumeration+       expressions. XXX: Not completely correct because of weird capturing+       semantics in `for (i of o) a.push(function(){return i})` */+    push_scope(s);++    /* local for_in scope starts here so individual elements+       can be closed in statement. */+    push_break_entry(s->cur_func, &break_entry,+                     label_name, label_break, label_cont, 1);+    break_entry.scope_level = block_scope_level;++    label_expr = emit_goto(s, OP_goto, -1);++    pos_next = s->cur_func->byte_code.size;+    emit_label(s, label_next);++    tok = s->token.val;+    switch (is_let(s, DECL_MASK_OTHER)) {+    case TRUE:+        tok = TOK_LET;+        break;+    case FALSE:+        break;+    default:+        return -1;+    }+    if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {+        if (next_token(s))+            return -1;++        if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {+            if (s->token.val == '[' || s->token.val == '{') {+                if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE) < 0)+                    return -1;+                has_destructuring = TRUE;+            } else {+                return js_parse_error(s, "variable name expected");+            }+            var_name = JS_ATOM_NULL;+        } else {+            var_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            if (next_token(s)) {+                JS_FreeAtom(s->ctx, var_name);+                return -1;+            }+            if (js_define_var(s, var_name, tok)) {+                JS_FreeAtom(s->ctx, var_name);+                return -1;+            }+            emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?+                    OP_scope_put_var_init : OP_scope_put_var);+            emit_atom(s, var_name);+            emit_u16(s, fd->scope_level);+        }+    } else {+        int skip_bits;+        if ((s->token.val == '[' || s->token.val == '{')+        &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {+            if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE) < 0)+                return -1;+        } else {+            int lvalue_label;+            if (js_parse_left_hand_side_expr(s))+                return -1;+            if (get_lvalue(s, &opcode, &scope, &var_name, &lvalue_label,+                           NULL, FALSE, TOK_FOR))+                return -1;+            put_lvalue(s, opcode, scope, var_name, lvalue_label,+                       PUT_LVALUE_NOKEEP_BOTTOM, FALSE);+        }+        var_name = JS_ATOM_NULL;+    }+    emit_goto(s, OP_goto, label_body);++    pos_expr = s->cur_func->byte_code.size;+    emit_label(s, label_expr);+    if (s->token.val == '=') {+        /* XXX: potential scoping issue if inside `with` statement */+        has_initializer = TRUE;+        /* parse and evaluate initializer prior to evaluating the+           object (only used with "for in" with a non lexical variable+           in non strict mode */+        if (next_token(s) || js_parse_assign_expr2(s, 0)) {+            JS_FreeAtom(ctx, var_name);+            return -1;+        }+        if (var_name != JS_ATOM_NULL) {+            emit_op(s, OP_scope_put_var);+            emit_atom(s, var_name);+            emit_u16(s, fd->scope_level);+        }+    }+    JS_FreeAtom(ctx, var_name);++    if (token_is_pseudo_keyword(s, JS_ATOM_of)) {+        break_entry.has_iterator = is_for_of = TRUE;+        break_entry.drop_count += 2;+        if (has_initializer)+            goto initializer_error;+    } else if (s->token.val == TOK_IN) {+        if (is_async)+            return js_parse_error(s, "'for await' loop should be used with 'of'");+        if (has_initializer &&+            (tok != TOK_VAR || (fd->js_mode & JS_MODE_STRICT) ||+             has_destructuring)) {+        initializer_error:+            return js_parse_error(s, "a declaration in the head of a for-%s loop can't have an initializer",+                                  is_for_of ? "of" : "in");+        }+    } else {+        return js_parse_error(s, "expected 'of' or 'in' in for control expression");+    }+    if (next_token(s))+        return -1;+    if (is_for_of) {+        if (js_parse_assign_expr(s))+            return -1;+    } else {+        if (js_parse_expr(s))+            return -1;+    }+    /* close the scope after having evaluated the expression so that+       the TDZ values are in the closures */+    close_scopes(s, s->cur_func->scope_level, block_scope_level);+    if (is_for_of) {+        if (is_async)+            emit_op(s, OP_for_await_of_start);+        else+            emit_op(s, OP_for_of_start);+        /* on stack: enum_rec */+    } else {+        emit_op(s, OP_for_in_start);+        /* on stack: enum_obj */+    }+    emit_goto(s, OP_goto, label_cont);++    if (js_parse_expect(s, ')'))+        return -1;++    if (OPTIMIZE) {+        /* move the `next` code here */+        DynBuf *bc = &s->cur_func->byte_code;+        int chunk_size = pos_expr - pos_next;+        int offset = bc->size - pos_next;+        int i;+        dbuf_realloc(bc, bc->size + chunk_size);+        dbuf_put(bc, bc->buf + pos_next, chunk_size);+        memset(bc->buf + pos_next, OP_nop, chunk_size);+        /* `next` part ends with a goto */+        s->cur_func->last_opcode_pos = bc->size - 5;+        /* relocate labels */+        for (i = label_cont; i < s->cur_func->label_count; i++) {+            LabelSlot *ls = &s->cur_func->label_slots[i];+            if (ls->pos >= pos_next && ls->pos < pos_expr)+                ls->pos += offset;+        }+    }++    emit_label(s, label_body);+    if (js_parse_statement(s))+        return -1;++    close_scopes(s, s->cur_func->scope_level, block_scope_level);++    emit_label(s, label_cont);+    if (is_for_of) {+        if (is_async) {+            /* call the next method */+            /* stack: iter_obj next catch_offset */+            emit_op(s, OP_dup3);+            emit_op(s, OP_drop);+            emit_op(s, OP_call_method);+            emit_u16(s, 0);+            /* get the result of the promise */+            emit_op(s, OP_await);+            /* unwrap the value and done values */+            emit_op(s, OP_iterator_get_value_done);+        } else {+            emit_op(s, OP_for_of_next);+            emit_u8(s, 0);+        }+    } else {+        emit_op(s, OP_for_in_next);+    }+    /* on stack: enum_rec / enum_obj value bool */+    emit_goto(s, OP_if_false, label_next);+    /* drop the undefined value from for_xx_next */+    emit_op(s, OP_drop);++    emit_label(s, label_break);+    if (is_for_of) {+        /* close and drop enum_rec */+        emit_op(s, OP_iterator_close);+    } else {+        emit_op(s, OP_drop);+    }+    pop_break_entry(s->cur_func);+    pop_scope(s);+    return 0;+}++static void set_eval_ret_undefined(JSParseState *s)+{+    if (s->cur_func->eval_ret_idx >= 0) {+        emit_op(s, OP_undefined);+        emit_op(s, OP_put_loc);+        emit_u16(s, s->cur_func->eval_ret_idx);+    }+}++static __exception int js_parse_statement_or_decl(JSParseState *s,+                                                  int decl_mask)+{+    JSContext *ctx = s->ctx;+    JSAtom label_name;+    int tok;++    /* specific label handling */+    /* XXX: support multiple labels on loop statements */+    label_name = JS_ATOM_NULL;+    if (is_label(s)) {+        BlockEnv *be;++        label_name = JS_DupAtom(ctx, s->token.u.ident.atom);++        for (be = s->cur_func->top_break; be; be = be->prev) {+            if (be->label_name == label_name) {+                js_parse_error(s, "duplicate label name");+                goto fail;+            }+        }++        if (next_token(s))+            goto fail;+        if (js_parse_expect(s, ':'))+            goto fail;+        if (s->token.val != TOK_FOR+        &&  s->token.val != TOK_DO+        &&  s->token.val != TOK_WHILE) {+            /* labelled regular statement */+            int label_break, mask;+            BlockEnv break_entry;++            label_break = new_label(s);+            push_break_entry(s->cur_func, &break_entry,+                             label_name, label_break, -1, 0);+            if (!(s->cur_func->js_mode & JS_MODE_STRICT) &&+                (decl_mask & DECL_MASK_FUNC_WITH_LABEL)) {+                mask = DECL_MASK_FUNC | DECL_MASK_FUNC_WITH_LABEL;+            } else {+                mask = 0;+            }+            if (js_parse_statement_or_decl(s, mask))+                goto fail;+            emit_label(s, label_break);+            pop_break_entry(s->cur_func);+            goto done;+        }+    }++    switch(tok = s->token.val) {+    case '{':+        if (js_parse_block(s))+            goto fail;+        break;+    case TOK_RETURN:+        if (s->cur_func->is_eval) {+            js_parse_error(s, "return not in a function");+            goto fail;+        }+        if (next_token(s))+            goto fail;+        if (s->token.val != ';' && s->token.val != '}' && !s->got_lf) {+            if (js_parse_expr(s))+                goto fail;+            emit_return(s, TRUE);+        } else {+            emit_return(s, FALSE);+        }+        if (js_parse_expect_semi(s))+            goto fail;+        break;+    case TOK_THROW:+        if (next_token(s))+            goto fail;+        if (s->got_lf) {+            js_parse_error(s, "line terminator not allowed after throw");+            goto fail;+        }+        if (js_parse_expr(s))+            goto fail;+        emit_op(s, OP_throw);+        if (js_parse_expect_semi(s))+            goto fail;+        break;+    case TOK_LET:+    case TOK_CONST:+    haslet:+        if (!(decl_mask & DECL_MASK_OTHER)) {+            js_parse_error(s, "lexical declarations can't appear in single-statement context");+            goto fail;+        }+        /* fall thru */+    case TOK_VAR:+        if (next_token(s))+            goto fail;+        if (js_parse_var(s, TRUE, tok, FALSE))+            goto fail;+        if (js_parse_expect_semi(s))+            goto fail;+        break;+    case TOK_IF:+        {+            int label1, label2, mask;+            if (next_token(s))+                goto fail;+            /* create a new scope for `let f;if(1) function f(){}` */+            push_scope(s);+            set_eval_ret_undefined(s);+            if (js_parse_expr_paren(s))+                goto fail;+            label1 = emit_goto(s, OP_if_false, -1);+            if (s->cur_func->js_mode & JS_MODE_STRICT)+                mask = 0;+            else+                mask = DECL_MASK_FUNC; /* Annex B.3.4 */++            if (js_parse_statement_or_decl(s, mask))+                goto fail;++            if (s->token.val == TOK_ELSE) {+                label2 = emit_goto(s, OP_goto, -1);+                if (next_token(s))+                    goto fail;++                emit_label(s, label1);+                if (js_parse_statement_or_decl(s, mask))+                    goto fail;++                label1 = label2;+            }+            emit_label(s, label1);+            pop_scope(s);+        }+        break;+    case TOK_WHILE:+        {+            int label_cont, label_break;+            BlockEnv break_entry;++            label_cont = new_label(s);+            label_break = new_label(s);++            push_break_entry(s->cur_func, &break_entry,+                             label_name, label_break, label_cont, 0);++            if (next_token(s))+                goto fail;++            set_eval_ret_undefined(s);++            emit_label(s, label_cont);+            if (js_parse_expr_paren(s))+                goto fail;+            emit_goto(s, OP_if_false, label_break);++            if (js_parse_statement(s))+                goto fail;+            emit_goto(s, OP_goto, label_cont);++            emit_label(s, label_break);++            pop_break_entry(s->cur_func);+        }+        break;+    case TOK_DO:+        {+            int label_cont, label_break, label1;+            BlockEnv break_entry;++            label_cont = new_label(s);+            label_break = new_label(s);+            label1 = new_label(s);++            push_break_entry(s->cur_func, &break_entry,+                             label_name, label_break, label_cont, 0);++            if (next_token(s))+                goto fail;++            emit_label(s, label1);++            set_eval_ret_undefined(s);++            if (js_parse_statement(s))+                goto fail;++            emit_label(s, label_cont);+            if (js_parse_expect(s, TOK_WHILE))+                goto fail;+            if (js_parse_expr_paren(s))+                goto fail;+            /* Insert semicolon if missing */+            if (s->token.val == ';') {+                if (next_token(s))+                    goto fail;+            }+            emit_goto(s, OP_if_true, label1);++            emit_label(s, label_break);++            pop_break_entry(s->cur_func);+        }+        break;+    case TOK_FOR:+        {+            int label_cont, label_break, label_body, label_test;+            int pos_cont, pos_body, block_scope_level;+            BlockEnv break_entry;+            int tok, bits;+            BOOL is_async;++            if (next_token(s))+                goto fail;++            set_eval_ret_undefined(s);+            bits = 0;+            is_async = FALSE;+            if (s->token.val == '(') {+                js_parse_skip_parens_token(s, &bits, FALSE);+            } else if (s->token.val == TOK_AWAIT) {+                if (!(s->cur_func->func_kind & JS_FUNC_ASYNC)) {+                    js_parse_error(s, "for await is only valid in asynchronous functions");+                    goto fail;+                }+                is_async = TRUE;+                if (next_token(s))+                    goto fail;+            }+            if (js_parse_expect(s, '('))+                goto fail;++            if (!(bits & SKIP_HAS_SEMI)) {+                /* parse for/in or for/of */+                if (js_parse_for_in_of(s, label_name, is_async))+                    goto fail;+                break;+            }+            block_scope_level = s->cur_func->scope_level;++            /* create scope for the lexical variables declared in the initial,+               test and increment expressions */+            push_scope(s);+            /* initial expression */+            tok = s->token.val;+            if (tok != ';') {+                switch (is_let(s, DECL_MASK_OTHER)) {+                case TRUE:+                    tok = TOK_LET;+                    break;+                case FALSE:+                    break;+                default:+                    goto fail;+                }+                if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {+                    if (next_token(s))+                        goto fail;+                    if (js_parse_var(s, FALSE, tok, FALSE))+                        goto fail;+                } else {+                    if (js_parse_expr2(s, FALSE))+                        goto fail;+                    emit_op(s, OP_drop);+                }++                /* close the closures before the first iteration */+                close_scopes(s, s->cur_func->scope_level, block_scope_level);+            }+            if (js_parse_expect(s, ';'))+                goto fail;++            label_test = new_label(s);+            label_cont = new_label(s);+            label_body = new_label(s);+            label_break = new_label(s);++            push_break_entry(s->cur_func, &break_entry,+                             label_name, label_break, label_cont, 0);++            /* test expression */+            if (s->token.val == ';') {+                /* no test expression */+                label_test = label_body;+            } else {+                emit_label(s, label_test);+                if (js_parse_expr(s))+                    goto fail;+                emit_goto(s, OP_if_false, label_break);+            }+            if (js_parse_expect(s, ';'))+                goto fail;++            if (s->token.val == ')') {+                /* no end expression */+                break_entry.label_cont = label_cont = label_test;+                pos_cont = 0; /* avoid warning */+            } else {+                /* skip the end expression */+                emit_goto(s, OP_goto, label_body);++                pos_cont = s->cur_func->byte_code.size;+                emit_label(s, label_cont);+                if (js_parse_expr(s))+                    goto fail;+                emit_op(s, OP_drop);+                if (label_test != label_body)+                    emit_goto(s, OP_goto, label_test);+            }+            if (js_parse_expect(s, ')'))+                goto fail;++            pos_body = s->cur_func->byte_code.size;+            emit_label(s, label_body);+            if (js_parse_statement(s))+                goto fail;++            /* close the closures before the next iteration */+            /* XXX: check continue case */+            close_scopes(s, s->cur_func->scope_level, block_scope_level);++            if (OPTIMIZE && label_test != label_body && label_cont != label_test) {+                /* move the increment code here */+                DynBuf *bc = &s->cur_func->byte_code;+                int chunk_size = pos_body - pos_cont;+                int offset = bc->size - pos_cont;+                int i;+                dbuf_realloc(bc, bc->size + chunk_size);+                dbuf_put(bc, bc->buf + pos_cont, chunk_size);+                memset(bc->buf + pos_cont, OP_nop, chunk_size);+                /* increment part ends with a goto */+                s->cur_func->last_opcode_pos = bc->size - 5;+                /* relocate labels */+                for (i = label_cont; i < s->cur_func->label_count; i++) {+                    LabelSlot *ls = &s->cur_func->label_slots[i];+                    if (ls->pos >= pos_cont && ls->pos < pos_body)+                        ls->pos += offset;+                }+            } else {+                emit_goto(s, OP_goto, label_cont);+            }++            emit_label(s, label_break);++            pop_break_entry(s->cur_func);+            pop_scope(s);+        }+        break;+    case TOK_BREAK:+    case TOK_CONTINUE:+        {+            int is_cont = s->token.val - TOK_BREAK;+            int label;++            if (next_token(s))+                goto fail;+            if (!s->got_lf && s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)+                label = s->token.u.ident.atom;+            else+                label = JS_ATOM_NULL;+            if (emit_break(s, label, is_cont))+                goto fail;+            if (label != JS_ATOM_NULL) {+                if (next_token(s))+                    goto fail;+            }+            if (js_parse_expect_semi(s))+                goto fail;+        }+        break;+    case TOK_SWITCH:+        {+            int label_case, label_break, label1;+            int default_label_pos;+            BlockEnv break_entry;++            if (next_token(s))+                goto fail;++            set_eval_ret_undefined(s);+            if (js_parse_expr_paren(s))+                goto fail;++            push_scope(s);+            label_break = new_label(s);+            push_break_entry(s->cur_func, &break_entry,+                             label_name, label_break, -1, 1);++            if (js_parse_expect(s, '{'))+                goto fail;++            default_label_pos = -1;+            label_case = -1;+            while (s->token.val != '}') {+                if (s->token.val == TOK_CASE) {+                    label1 = -1;+                    if (label_case >= 0) {+                        /* skip the case if needed */+                        label1 = emit_goto(s, OP_goto, -1);+                    }+                    emit_label(s, label_case);+                    label_case = -1;+                    for (;;) {+                        /* parse a sequence of case clauses */+                        if (next_token(s))+                            goto fail;+                        emit_op(s, OP_dup);+                        if (js_parse_expr(s))+                            goto fail;+                        if (js_parse_expect(s, ':'))+                            goto fail;+                        emit_op(s, OP_strict_eq);+                        if (s->token.val == TOK_CASE) {+                            label1 = emit_goto(s, OP_if_true, label1);+                        } else {+                            label_case = emit_goto(s, OP_if_false, -1);+                            emit_label(s, label1);+                            break;+                        }+                    }+                } else if (s->token.val == TOK_DEFAULT) {+                    if (next_token(s))+                        goto fail;+                    if (js_parse_expect(s, ':'))+                        goto fail;+                    if (default_label_pos >= 0) {+                        js_parse_error(s, "duplicate default");+                        goto fail;+                    }+                    if (label_case < 0) {+                        /* falling thru direct from switch expression */+                        label_case = emit_goto(s, OP_goto, -1);+                    }+                    /* Emit a dummy label opcode. Label will be patched after+                       the end of the switch body. Do not use emit_label(s, 0)+                       because it would clobber label 0 address, preventing+                       proper optimizer operation.+                     */+                    emit_op(s, OP_label);+                    emit_u32(s, 0);+                    default_label_pos = s->cur_func->byte_code.size - 4;+                } else {+                    if (label_case < 0) {+                        /* falling thru direct from switch expression */+                        js_parse_error(s, "invalid switch statement");+                        goto fail;+                    }+                    if (js_parse_statement_or_decl(s, DECL_MASK_ALL))+                        goto fail;+                }+            }+            if (js_parse_expect(s, '}'))+                goto fail;+            if (default_label_pos >= 0) {+                /* Ugly patch for the the `default` label, shameful and risky */+                put_u32(s->cur_func->byte_code.buf + default_label_pos,+                        label_case);+                s->cur_func->label_slots[label_case].pos = default_label_pos + 4;+            } else {+                emit_label(s, label_case);+            }+            emit_label(s, label_break);+            emit_op(s, OP_drop); /* drop the switch expression */++            pop_break_entry(s->cur_func);+            pop_scope(s);+        }+        break;+    case TOK_TRY:+        {+            int label_catch, label_catch2, label_finally, label_end;+            JSAtom name;+            BlockEnv block_env;++            set_eval_ret_undefined(s);+            if (next_token(s))+                goto fail;+            label_catch = new_label(s);+            label_catch2 = new_label(s);+            label_finally = new_label(s);+            label_end = new_label(s);++            emit_goto(s, OP_catch, label_catch);++            push_break_entry(s->cur_func, &block_env,+                             JS_ATOM_NULL, -1, -1, 1);+            block_env.label_finally = label_finally;++            if (js_parse_block(s))+                goto fail;++            pop_break_entry(s->cur_func);++            if (js_is_live_code(s)) {+                /* drop the catch offset */+                emit_op(s, OP_drop);+                /* must push dummy value to keep same stack size */+                emit_op(s, OP_undefined);+                emit_goto(s, OP_gosub, label_finally);+                emit_op(s, OP_drop);++                emit_goto(s, OP_goto, label_end);+            }++            if (s->token.val == TOK_CATCH) {+                if (next_token(s))+                    goto fail;++                push_scope(s);  /* catch variable */+                emit_label(s, label_catch);++                if (s->token.val == '{') {+                    /* support optional-catch-binding feature */+                    emit_op(s, OP_drop);    /* pop the exception object */+                } else {+                    if (js_parse_expect(s, '('))+                        goto fail;+                    if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {+                        if (s->token.val == '[' || s->token.val == '{') {+                            /* XXX: TOK_LET is not completely correct */+                            if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE) < 0)+                                goto fail;+                        } else {+                            js_parse_error(s, "identifier expected");+                            goto fail;+                        }+                    } else {+                        name = JS_DupAtom(ctx, s->token.u.ident.atom);+                        if (next_token(s)+                        ||  js_define_var(s, name, TOK_CATCH) < 0) {+                            JS_FreeAtom(ctx, name);+                            goto fail;+                        }+                        /* store the exception value in the catch variable */+                        emit_op(s, OP_scope_put_var);+                        emit_u32(s, name);+                        emit_u16(s, s->cur_func->scope_level);+                    }+                    if (js_parse_expect(s, ')'))+                        goto fail;+                }+                /* XXX: should keep the address to nop it out if there is no finally block */+                emit_goto(s, OP_catch, label_catch2);++                push_scope(s);  /* catch block */+                push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL,+                                 -1, -1, 1);+                block_env.label_finally = label_finally;++                if (js_parse_block(s))+                    goto fail;++                pop_break_entry(s->cur_func);+                pop_scope(s);  /* catch block */+                pop_scope(s);  /* catch variable */++                if (js_is_live_code(s)) {+                    /* drop the catch2 offset */+                    emit_op(s, OP_drop);+                    /* XXX: should keep the address to nop it out if there is no finally block */+                    /* must push dummy value to keep same stack size */+                    emit_op(s, OP_undefined);+                    emit_goto(s, OP_gosub, label_finally);+                    emit_op(s, OP_drop);+                    emit_goto(s, OP_goto, label_end);+                }+                /* catch exceptions thrown in the catch block to execute the+                 * finally clause and rethrow the exception */+                emit_label(s, label_catch2);+                /* catch value is at TOS, no need to push undefined */+                emit_goto(s, OP_gosub, label_finally);+                emit_op(s, OP_throw);++            } else if (s->token.val == TOK_FINALLY) {+                /* finally without catch : execute the finally clause+                 * and rethrow the exception */+                emit_label(s, label_catch);+                /* catch value is at TOS, no need to push undefined */+                emit_goto(s, OP_gosub, label_finally);+                emit_op(s, OP_throw);+            } else {+                js_parse_error(s, "expecting catch or finally");+                goto fail;+            }+            emit_label(s, label_finally);+            if (s->token.val == TOK_FINALLY) {+                int saved_eval_ret_idx = 0; /* avoid warning */+                +                if (next_token(s))+                    goto fail;+                /* on the stack: ret_value gosub_ret_value */+                push_break_entry(s->cur_func, &block_env, JS_ATOM_NULL,+                                 -1, -1, 2);++                if (s->cur_func->eval_ret_idx >= 0) {+                    /* 'finally' updates eval_ret only if not a normal+                       termination */+                    saved_eval_ret_idx =+                        add_var(s->ctx, s->cur_func, JS_ATOM__ret_);+                    if (saved_eval_ret_idx < 0)+                        goto fail;+                    emit_op(s, OP_get_loc);+                    emit_u16(s, s->cur_func->eval_ret_idx);+                    emit_op(s, OP_put_loc);+                    emit_u16(s, saved_eval_ret_idx);+                    set_eval_ret_undefined(s);+                }+                +                if (js_parse_block(s))+                    goto fail;++                if (s->cur_func->eval_ret_idx >= 0) {+                    emit_op(s, OP_get_loc);+                    emit_u16(s, saved_eval_ret_idx);+                    emit_op(s, OP_put_loc);+                    emit_u16(s, s->cur_func->eval_ret_idx);+                }+                pop_break_entry(s->cur_func);+            }+            emit_op(s, OP_ret);+            emit_label(s, label_end);+        }+        break;+    case ';':+        /* empty statement */+        if (next_token(s))+            goto fail;+        break;+    case TOK_WITH:+        if (s->cur_func->js_mode & JS_MODE_STRICT) {+            js_parse_error(s, "invalid keyword: with");+            goto fail;+        } else {+            int with_idx;++            if (next_token(s))+                goto fail;++            if (js_parse_expr_paren(s))+                goto fail;++            push_scope(s);+            with_idx = define_var(s, s->cur_func, JS_ATOM__with_,+                                  JS_VAR_DEF_WITH);+            if (with_idx < 0)+                goto fail;+            emit_op(s, OP_to_object);+            emit_op(s, OP_put_loc);+            emit_u16(s, with_idx);++            set_eval_ret_undefined(s);+            if (js_parse_statement(s))+                goto fail;++            /* Popping scope drops lexical context for the with object variable */+            pop_scope(s);+        }+        break;+    case TOK_FUNCTION:+        /* ES6 Annex B.3.2 and B.3.3 semantics */+        if (!(decl_mask & DECL_MASK_FUNC))+            goto func_decl_error;+        if (!(decl_mask & DECL_MASK_OTHER) && peek_token(s, FALSE) == '*')+            goto func_decl_error;+        goto parse_func_var;+    case TOK_IDENT:+        if (s->token.u.ident.is_reserved) {+            js_parse_error_reserved_identifier(s);+            goto fail;+        }+        /* Determine if `let` introduces a Declaration or an ExpressionStatement */+        switch (is_let(s, decl_mask)) {+        case TRUE:+            tok = TOK_LET;+            goto haslet;+        case FALSE:+            break;+        default:+            goto fail;+        }+        if (token_is_pseudo_keyword(s, JS_ATOM_async) &&+            peek_token(s, TRUE) == TOK_FUNCTION) {+            if (!(decl_mask & DECL_MASK_OTHER)) {+            func_decl_error:+                js_parse_error(s, "function declarations can't appear in single-statement context");+                goto fail;+            }+        parse_func_var:+            if (js_parse_function_decl(s, JS_PARSE_FUNC_VAR,+                                       JS_FUNC_NORMAL, JS_ATOM_NULL,+                                       s->token.ptr, s->token.line_num))+                goto fail;+            break;+        }+        goto hasexpr;++    case TOK_CLASS:+        if (!(decl_mask & DECL_MASK_OTHER)) {+            js_parse_error(s, "class declarations can't appear in single-statement context");+            goto fail;+        }+        if (js_parse_class(s, FALSE, JS_PARSE_EXPORT_NONE))+            return -1;+        break;++    case TOK_DEBUGGER:+        /* currently no debugger, so just skip the keyword */+        if (next_token(s))+            goto fail;+        if (js_parse_expect_semi(s))+            goto fail;+        break;+        +    case TOK_ENUM:+    case TOK_EXPORT:+    case TOK_EXTENDS:+        js_unsupported_keyword(s, s->token.u.ident.atom);+        goto fail;++    default:+    hasexpr:+        if (js_parse_expr(s))+            goto fail;+        if (s->cur_func->eval_ret_idx >= 0) {+            /* store the expression value so that it can be returned+               by eval() */+            emit_op(s, OP_put_loc);+            emit_u16(s, s->cur_func->eval_ret_idx);+        } else {+            emit_op(s, OP_drop); /* drop the result */+        }+        if (js_parse_expect_semi(s))+            goto fail;+        break;+    }+done:+    JS_FreeAtom(ctx, label_name);+    return 0;+fail:+    JS_FreeAtom(ctx, label_name);+    return -1;+}++/* 'name' is freed */+static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)+{+    JSModuleDef *m;+    m = js_mallocz(ctx, sizeof(*m));+    if (!m) {+        JS_FreeAtom(ctx, name);+        return NULL;+    }+    m->header.ref_count = 1;+    m->module_name = name;+    m->module_ns = JS_UNDEFINED;+    m->func_obj = JS_UNDEFINED;+    m->eval_exception = JS_UNDEFINED;+    m->meta_obj = JS_UNDEFINED;+    list_add_tail(&m->link, &ctx->loaded_modules);+    return m;+}++static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,+                               JS_MarkFunc *mark_func)+{+    int i;++    for(i = 0; i < m->export_entries_count; i++) {+        JSExportEntry *me = &m->export_entries[i];+        if (me->export_type == JS_EXPORT_TYPE_LOCAL &&+            me->u.local.var_ref) {+            mark_func(rt, &me->u.local.var_ref->header);+        }+    }++    JS_MarkValue(rt, m->module_ns, mark_func);+    JS_MarkValue(rt, m->func_obj, mark_func);+    JS_MarkValue(rt, m->eval_exception, mark_func);+    JS_MarkValue(rt, m->meta_obj, mark_func);+}++static void js_free_module_def(JSContext *ctx, JSModuleDef *m)+{+    int i;++    JS_FreeAtom(ctx, m->module_name);++    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        JS_FreeAtom(ctx, rme->module_name);+    }+    js_free(ctx, m->req_module_entries);++    for(i = 0; i < m->export_entries_count; i++) {+        JSExportEntry *me = &m->export_entries[i];+        if (me->export_type == JS_EXPORT_TYPE_LOCAL)+            free_var_ref(ctx->rt, me->u.local.var_ref);+        JS_FreeAtom(ctx, me->export_name);+        JS_FreeAtom(ctx, me->local_name);+    }+    js_free(ctx, m->export_entries);++    js_free(ctx, m->star_export_entries);++    for(i = 0; i < m->import_entries_count; i++) {+        JSImportEntry *mi = &m->import_entries[i];+        JS_FreeAtom(ctx, mi->import_name);+    }+    js_free(ctx, m->import_entries);++    JS_FreeValue(ctx, m->module_ns);+    JS_FreeValue(ctx, m->func_obj);+    JS_FreeValue(ctx, m->eval_exception);+    JS_FreeValue(ctx, m->meta_obj);+    list_del(&m->link);+    js_free(ctx, m);+}++static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,+                                JSAtom module_name)+{+    JSReqModuleEntry *rme;+    int i;++    /* no need to add the module request if it is already present */+    for(i = 0; i < m->req_module_entries_count; i++) {+        rme = &m->req_module_entries[i];+        if (rme->module_name == module_name)+            return i;+    }++    if (js_resize_array(ctx, (void **)&m->req_module_entries,+                        sizeof(JSReqModuleEntry),+                        &m->req_module_entries_size,+                        m->req_module_entries_count + 1))+        return -1;+    rme = &m->req_module_entries[m->req_module_entries_count++];+    rme->module_name = JS_DupAtom(ctx, module_name);+    rme->module = NULL;+    return i;+}++static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,+                                        JSAtom export_name)+{+    JSExportEntry *me;+    int i;+    for(i = 0; i < m->export_entries_count; i++) {+        me = &m->export_entries[i];+        if (me->export_name == export_name)+            return me;+    }+    return NULL;+}++static JSExportEntry *add_export_entry2(JSContext *ctx,+                                        JSParseState *s, JSModuleDef *m,+                                       JSAtom local_name, JSAtom export_name,+                                       JSExportTypeEnum export_type)+{+    JSExportEntry *me;++    if (find_export_entry(ctx, m, export_name)) {+        char buf1[ATOM_GET_STR_BUF_SIZE];+        if (s) {+            js_parse_error(s, "duplicate exported name '%s'",+                           JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name));+        } else {+            JS_ThrowSyntaxErrorAtom(ctx, "duplicate exported name '%s'", export_name);+        }+        return NULL;+    }++    if (js_resize_array(ctx, (void **)&m->export_entries,+                        sizeof(JSExportEntry),+                        &m->export_entries_size,+                        m->export_entries_count + 1))+        return NULL;+    me = &m->export_entries[m->export_entries_count++];+    memset(me, 0, sizeof(*me));+    me->local_name = JS_DupAtom(ctx, local_name);+    me->export_name = JS_DupAtom(ctx, export_name);+    me->export_type = export_type;+    return me;+}++static JSExportEntry *add_export_entry(JSParseState *s, JSModuleDef *m,+                                       JSAtom local_name, JSAtom export_name,+                                       JSExportTypeEnum export_type)+{+    return add_export_entry2(s->ctx, s, m, local_name, export_name,+                             export_type);+}++static int add_star_export_entry(JSContext *ctx, JSModuleDef *m,+                                 int req_module_idx)+{+    JSStarExportEntry *se;++    if (js_resize_array(ctx, (void **)&m->star_export_entries,+                        sizeof(JSStarExportEntry),+                        &m->star_export_entries_size,+                        m->star_export_entries_count + 1))+        return -1;+    se = &m->star_export_entries[m->star_export_entries_count++];+    se->req_module_idx = req_module_idx;+    return 0;+}++/* create a C module */+JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,+                           JSModuleInitFunc *func)+{+    JSModuleDef *m;+    JSAtom name;+    name = JS_NewAtom(ctx, name_str);+    if (name == JS_ATOM_NULL)+        return NULL;+    m = js_new_module_def(ctx, name);+    m->init_func = func;+    return m;+}++int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name)+{+    JSExportEntry *me;+    JSAtom name;+    name = JS_NewAtom(ctx, export_name);+    if (name == JS_ATOM_NULL)+        return -1;+    me = add_export_entry2(ctx, NULL, m, JS_ATOM_NULL, name,+                           JS_EXPORT_TYPE_LOCAL);+    JS_FreeAtom(ctx, name);+    if (!me)+        return -1;+    else+        return 0;+}++int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,+                       JSValue val)+{+    JSExportEntry *me;+    JSAtom name;+    name = JS_NewAtom(ctx, export_name);+    if (name == JS_ATOM_NULL)+        goto fail;+    me = find_export_entry(ctx, m, name);+    JS_FreeAtom(ctx, name);+    if (!me)+        goto fail;+    set_value(ctx, me->u.local.var_ref->pvalue, val);+    return 0;+ fail:+    JS_FreeValue(ctx, val);+    return -1;+}++void JS_SetModuleLoaderFunc(JSRuntime *rt,+                            JSModuleNormalizeFunc *module_normalize,+                            JSModuleLoaderFunc *module_loader, void *opaque)+{+    rt->module_normalize_func = module_normalize;+    rt->module_loader_func = module_loader;+    rt->module_loader_opaque = opaque;+}++/* default module filename normalizer */+static char *js_default_module_normalize_name(JSContext *ctx,+                                              const char *base_name,+                                              const char *name)+{+    char *filename, *p;+    const char *r;+    int len;++    if (name[0] != '.') {+        /* if no initial dot, the module name is not modified */+        return js_strdup(ctx, name);+    }++    p = strrchr(base_name, '/');+    if (p)+        len = p - base_name;+    else+        len = 0;++    filename = js_malloc(ctx, len + strlen(name) + 1 + 1);+    if (!filename)+        return NULL;+    memcpy(filename, base_name, len);+    filename[len] = '\0';++    /* we only normalize the leading '..' or '.' */+    r = name;+    for(;;) {+        if (r[0] == '.' && r[1] == '/') {+            r += 2;+        } else if (r[0] == '.' && r[1] == '.' && r[2] == '/') {+            /* remove the last path element of filename, except if "."+               or ".." */+            if (filename[0] == '\0')+                break;+            p = strrchr(filename, '/');+            if (!p)+                p = filename;+            else+                p++;+            if (!strcmp(p, ".") || !strcmp(p, ".."))+                break;+            if (p > filename)+                p--;+            *p = '\0';+            r += 3;+        } else {+            break;+        }+    }+    if (filename[0] != '\0')+        strcat(filename, "/");+    strcat(filename, r);+    //    printf("normalize: %s %s -> %s\n", base_name, name, filename);+    return filename;+}++static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name)+{+    struct list_head *el;+    JSModuleDef *m;+    +    /* first look at the loaded modules */+    list_for_each(el, &ctx->loaded_modules) {+        m = list_entry(el, JSModuleDef, link);+        if (m->module_name == name)+            return m;+    }+    return NULL;+}++/* return NULL in case of exception (e.g. module could not be loaded) */+static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,+                                                    const char *base_cname,+                                                    const char *cname1)+{+    JSRuntime *rt = ctx->rt;+    JSModuleDef *m;+    char *cname;+    JSAtom module_name;++    if (!rt->module_normalize_func) {+        cname = js_default_module_normalize_name(ctx, base_cname, cname1);+    } else {+        cname = rt->module_normalize_func(ctx, base_cname, cname1,+                                          rt->module_loader_opaque);+    }+    if (!cname)+        return NULL;++    module_name = JS_NewAtom(ctx, cname);+    if (module_name == JS_ATOM_NULL) {+        js_free(ctx, cname);+        return NULL;+    }++    /* first look at the loaded modules */+    m = js_find_loaded_module(ctx, module_name);+    if (m) {+        js_free(ctx, cname);+        JS_FreeAtom(ctx, module_name);+        return m;+    }++    JS_FreeAtom(ctx, module_name);++    /* load the module */+    if (!rt->module_loader_func) {+        /* XXX: use a syntax error ? */+        JS_ThrowReferenceError(ctx, "could not load module '%s'",+                               cname);+        js_free(ctx, cname);+        return NULL;+    }++    m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque);+    js_free(ctx, cname);+    return m;+}++static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,+                                                    JSAtom base_module_name,+                                                    JSAtom module_name1)+{+    const char *base_cname, *cname;+    JSModuleDef *m;+    +    base_cname = JS_AtomToCString(ctx, base_module_name);+    if (!base_cname)+        return NULL;+    cname = JS_AtomToCString(ctx, module_name1);+    if (!cname) {+        JS_FreeCString(ctx, base_cname);+        return NULL;+    }+    m = js_host_resolve_imported_module(ctx, base_cname, cname);+    JS_FreeCString(ctx, base_cname);+    JS_FreeCString(ctx, cname);+    return m;+}++typedef struct JSResolveEntry {+    JSModuleDef *module;+    JSAtom name;+} JSResolveEntry;++typedef struct JSResolveState {+    JSResolveEntry *array;+    int size;+    int count;+} JSResolveState;++static int find_resolve_entry(JSResolveState *s,+                              JSModuleDef *m, JSAtom name)+{+    int i;+    for(i = 0; i < s->count; i++) {+        JSResolveEntry *re = &s->array[i];+        if (re->module == m && re->name == name)+            return i;+    }+    return -1;+}++static int add_resolve_entry(JSContext *ctx, JSResolveState *s,+                             JSModuleDef *m, JSAtom name)+{+    JSResolveEntry *re;++    if (js_resize_array(ctx, (void **)&s->array,+                        sizeof(JSResolveEntry),+                        &s->size, s->count + 1))+        return -1;+    re = &s->array[s->count++];+    re->module = m;+    re->name = JS_DupAtom(ctx, name);+    return 0;+}++typedef enum JSResolveResultEnum {+    JS_RESOLVE_RES_EXCEPTION = -1, /* memory alloc error */+    JS_RESOLVE_RES_FOUND = 0,+    JS_RESOLVE_RES_NOT_FOUND,+    JS_RESOLVE_RES_CIRCULAR,+    JS_RESOLVE_RES_AMBIGUOUS,+} JSResolveResultEnum;++static JSResolveResultEnum js_resolve_export1(JSContext *ctx,+                                              JSModuleDef **pmodule,+                                              JSExportEntry **pme,+                                              JSModuleDef *m,+                                              JSAtom export_name,+                                              JSResolveState *s)+{+    JSExportEntry *me;++    *pmodule = NULL;+    *pme = NULL;+    if (find_resolve_entry(s, m, export_name) >= 0)+        return JS_RESOLVE_RES_CIRCULAR;+    if (add_resolve_entry(ctx, s, m, export_name) < 0)+        return JS_RESOLVE_RES_EXCEPTION;+    me = find_export_entry(ctx, m, export_name);+    if (me) {+        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+            /* local export */+            *pmodule = m;+            *pme = me;+            return JS_RESOLVE_RES_FOUND;+        } else {+            /* indirect export */+            JSModuleDef *m1;+            m1 = m->req_module_entries[me->u.req_module_idx].module;+            if (me->local_name == JS_ATOM__star_) {+                /* export ns from */+                *pmodule = m;+                *pme = me;+                return JS_RESOLVE_RES_FOUND;+            } else {+                return js_resolve_export1(ctx, pmodule, pme, m1,+                                          me->local_name, s);+            }+        }+    } else {+        if (export_name != JS_ATOM_default) {+            /* not found in direct or indirect exports: try star exports */+            int i;++            for(i = 0; i < m->star_export_entries_count; i++) {+                JSStarExportEntry *se = &m->star_export_entries[i];+                JSModuleDef *m1, *res_m;+                JSExportEntry *res_me;+                JSResolveResultEnum ret;++                m1 = m->req_module_entries[se->req_module_idx].module;+                ret = js_resolve_export1(ctx, &res_m, &res_me, m1,+                                         export_name, s);+                if (ret == JS_RESOLVE_RES_AMBIGUOUS ||+                    ret == JS_RESOLVE_RES_EXCEPTION) {+                    return ret;+                } else if (ret == JS_RESOLVE_RES_FOUND) {+                    if (*pme != NULL) {+                        if (*pmodule != res_m ||+                            res_me->local_name != (*pme)->local_name) {+                            *pmodule = NULL;+                            *pme = NULL;+                            return JS_RESOLVE_RES_AMBIGUOUS;+                        }+                    } else {+                        *pmodule = res_m;+                        *pme = res_me;+                    }+                }+            }+            if (*pme != NULL)+                return JS_RESOLVE_RES_FOUND;+        }+        return JS_RESOLVE_RES_NOT_FOUND;+    }+}++/* If the return value is JS_RESOLVE_RES_FOUND, return the module+  (*pmodule) and the corresponding local export entry+  (*pme). Otherwise return (NULL, NULL) */+static JSResolveResultEnum js_resolve_export(JSContext *ctx,+                                             JSModuleDef **pmodule,+                                             JSExportEntry **pme,+                                             JSModuleDef *m,+                                             JSAtom export_name)+{+    JSResolveState ss, *s = &ss;+    int i;+    JSResolveResultEnum ret;++    s->array = NULL;+    s->size = 0;+    s->count = 0;++    ret = js_resolve_export1(ctx, pmodule, pme, m, export_name, s);++    for(i = 0; i < s->count; i++)+        JS_FreeAtom(ctx, s->array[i].name);+    js_free(ctx, s->array);++    return ret;+}++static void js_resolve_export_throw_error(JSContext *ctx,+                                          JSResolveResultEnum res,+                                          JSModuleDef *m, JSAtom export_name)+{+    char buf1[ATOM_GET_STR_BUF_SIZE];+    char buf2[ATOM_GET_STR_BUF_SIZE];+    switch(res) {+    case JS_RESOLVE_RES_EXCEPTION:+        break;+    default:+    case JS_RESOLVE_RES_NOT_FOUND:+        JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'",+                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),+                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));+        break;+    case JS_RESOLVE_RES_CIRCULAR:+        JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'",+                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),+                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));+        break;+    case JS_RESOLVE_RES_AMBIGUOUS:+        JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous",+                            JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name),+                            JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name));+        break;+    }+}+++typedef enum {+    EXPORTED_NAME_AMBIGUOUS,+    EXPORTED_NAME_NORMAL,+    EXPORTED_NAME_NS,+} ExportedNameEntryEnum;++typedef struct ExportedNameEntry {+    JSAtom export_name;+    ExportedNameEntryEnum export_type;+    union {+        JSExportEntry *me; /* using when the list is built */+        JSVarRef *var_ref; /* EXPORTED_NAME_NORMAL */+        JSModuleDef *module; /* for EXPORTED_NAME_NS */+    } u;+} ExportedNameEntry;++typedef struct GetExportNamesState {+    JSModuleDef **modules;+    int modules_size;+    int modules_count;++    ExportedNameEntry *exported_names;+    int exported_names_size;+    int exported_names_count;+} GetExportNamesState;++static int find_exported_name(GetExportNamesState *s, JSAtom name)+{+    int i;+    for(i = 0; i < s->exported_names_count; i++) {+        if (s->exported_names[i].export_name == name)+            return i;+    }+    return -1;+}++static __exception int get_exported_names(JSContext *ctx,+                                          GetExportNamesState *s,+                                          JSModuleDef *m, BOOL from_star)+{+    ExportedNameEntry *en;+    int i, j;++    /* check circular reference */+    for(i = 0; i < s->modules_count; i++) {+        if (s->modules[i] == m)+            return 0;+    }+    if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]),+                        &s->modules_size, s->modules_count + 1))+        return -1;+    s->modules[s->modules_count++] = m;++    for(i = 0; i < m->export_entries_count; i++) {+        JSExportEntry *me = &m->export_entries[i];+        if (from_star && me->export_name == JS_ATOM_default)+            continue;+        j = find_exported_name(s, me->export_name);+        if (j < 0) {+            if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]),+                                &s->exported_names_size,+                                s->exported_names_count + 1))+                return -1;+            en = &s->exported_names[s->exported_names_count++];+            en->export_name = me->export_name;+            /* avoid a second lookup for simple module exports */+            if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL)+                en->u.me = NULL;+            else+                en->u.me = me;+        } else {+            en = &s->exported_names[j];+            en->u.me = NULL;+        }+    }+    for(i = 0; i < m->star_export_entries_count; i++) {+        JSStarExportEntry *se = &m->star_export_entries[i];+        JSModuleDef *m1;+        m1 = m->req_module_entries[se->req_module_idx].module;+        if (get_exported_names(ctx, s, m1, TRUE))+            return -1;+    }+    return 0;+}++/* Unfortunately, the spec gives a different behavior from GetOwnProperty ! */+static int js_module_ns_has(JSContext *ctx, JSValueConst obj, JSAtom atom)+{+    return (find_own_property1(JS_VALUE_GET_OBJ(obj), atom) != NULL);+}++static const JSClassExoticMethods js_module_ns_exotic_methods = {+    .has_property = js_module_ns_has,+};++static int exported_names_cmp(const void *p1, const void *p2, void *opaque)+{+    JSContext *ctx = opaque;+    const ExportedNameEntry *me1 = p1;+    const ExportedNameEntry *me2 = p2;+    JSValue str1, str2;+    int ret;++    /* XXX: should avoid allocation memory in atom comparison */+    str1 = JS_AtomToString(ctx, me1->export_name);+    str2 = JS_AtomToString(ctx, me2->export_name);+    if (JS_IsException(str1) || JS_IsException(str2)) {+        /* XXX: raise an error ? */+        ret = 0;+    } else {+        ret = js_string_compare(ctx, JS_VALUE_GET_STRING(str1),+                                JS_VALUE_GET_STRING(str2));+    }+    JS_FreeValue(ctx, str1);+    JS_FreeValue(ctx, str2);+    return ret;+}++static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m);++static JSValue js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,+                                     void *opaque)+{+    JSModuleDef *m = opaque;+    return js_get_module_ns(ctx, m);+}++static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)+{+    JSValue obj;+    JSObject *p;+    GetExportNamesState s_s, *s = &s_s;+    int i, ret;+    JSProperty *pr;++    obj = JS_NewObjectClass(ctx, JS_CLASS_MODULE_NS);+    if (JS_IsException(obj))+        return obj;+    p = JS_VALUE_GET_OBJ(obj);++    memset(s, 0, sizeof(*s));+    ret = get_exported_names(ctx, s, m, FALSE);+    js_free(ctx, s->modules);+    if (ret)+        goto fail;++    /* Resolve the exported names. The ambiguous exports are removed */+    for(i = 0; i < s->exported_names_count; i++) {+        ExportedNameEntry *en = &s->exported_names[i];+        JSResolveResultEnum res;+        JSExportEntry *res_me;+        JSModuleDef *res_m;++        if (en->u.me) {+            res_me = en->u.me; /* fast case: no resolution needed */+            res_m = m;+            res = JS_RESOLVE_RES_FOUND;+        } else {+            res = js_resolve_export(ctx, &res_m, &res_me, m,+                                    en->export_name);+        }+        if (res != JS_RESOLVE_RES_FOUND) {+            if (res != JS_RESOLVE_RES_AMBIGUOUS) {+                js_resolve_export_throw_error(ctx, res, m, en->export_name);+                goto fail;+            }+            en->export_type = EXPORTED_NAME_AMBIGUOUS;+        } else {+            if (res_me->local_name == JS_ATOM__star_) {+                en->export_type = EXPORTED_NAME_NS;+                en->u.module = res_m->req_module_entries[res_me->u.req_module_idx].module;+            } else {+                en->export_type = EXPORTED_NAME_NORMAL;+                if (res_me->u.local.var_ref) {+                    en->u.var_ref = res_me->u.local.var_ref;+                } else {+                    JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj);+                    p1 = JS_VALUE_GET_OBJ(res_m->func_obj);+                    en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];+                }+            }+        }+    }++    /* sort the exported names */+    rqsort(s->exported_names, s->exported_names_count,+           sizeof(s->exported_names[0]), exported_names_cmp, ctx);++    for(i = 0; i < s->exported_names_count; i++) {+        ExportedNameEntry *en = &s->exported_names[i];+        switch(en->export_type) {+        case EXPORTED_NAME_NORMAL:+            {+                JSVarRef *var_ref = en->u.var_ref;+                pr = add_property(ctx, p, en->export_name,+                                  JS_PROP_ENUMERABLE | JS_PROP_WRITABLE |+                                  JS_PROP_VARREF);+                if (!pr)+                    goto fail;+                var_ref->header.ref_count++;+                pr->u.var_ref = var_ref;+            }+            break;+        case EXPORTED_NAME_NS:+            /* the exported namespace must be created on demand */+            if (JS_DefineAutoInitProperty(ctx, obj,+                                          en->export_name,+                                          JS_AUTOINIT_ID_MODULE_NS,+                                          en->u.module, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)+                goto fail;+            break;+        default:+            break;+        }+    }++    js_free(ctx, s->exported_names);++    JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_toStringTag,+                           JS_AtomToString(ctx, JS_ATOM_Module),+                           0);++    p->extensible = FALSE;+    return obj;+ fail:+    js_free(ctx, s->exported_names);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_get_module_ns(JSContext *ctx, JSModuleDef *m)+{+    if (JS_IsUndefined(m->module_ns)) {+        JSValue val;+        val = js_build_module_ns(ctx, m);+        if (JS_IsException(val))+            return JS_EXCEPTION;+        m->module_ns = val;+    }+    return JS_DupValue(ctx, m->module_ns);+}++/* Load all the required modules for module 'm' */+static int js_resolve_module(JSContext *ctx, JSModuleDef *m)+{+    int i;+    JSModuleDef *m1;++    if (m->resolved)+        return 0;+#ifdef DUMP_MODULE_RESOLVE+    {+        char buf1[ATOM_GET_STR_BUF_SIZE];+        printf("resolving module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));+    }+#endif+    m->resolved = TRUE;+    /* resolve each requested module */+    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,+                                                  rme->module_name);+        if (!m1)+            return -1;+        rme->module = m1;+        /* already done in js_host_resolve_imported_module() except if+           the module was loaded with JS_EvalBinary() */+        if (js_resolve_module(ctx, m1) < 0)+            return -1;+    }+    return 0;+}++static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical)+{+    JSVarRef *var_ref;+    var_ref = js_malloc(ctx, sizeof(JSVarRef));+    if (!var_ref)+        return NULL;+    var_ref->header.ref_count = 1;+    if (is_lexical)+        var_ref->value = JS_UNINITIALIZED;+    else+        var_ref->value = JS_UNDEFINED;+    var_ref->pvalue = &var_ref->value;+    var_ref->is_detached = TRUE;+    add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF);+    return var_ref;+}++/* Create the <eval> function associated with the module */+static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m)+{+    JSFunctionBytecode *b;+    int i;+    JSVarRef **var_refs;+    JSValue func_obj, bfunc;+    JSObject *p;++    bfunc = m->func_obj;+    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,+                                      JS_CLASS_BYTECODE_FUNCTION);++    if (JS_IsException(func_obj))+        return -1;+    b = JS_VALUE_GET_PTR(bfunc);++    p = JS_VALUE_GET_OBJ(func_obj);+    p->u.func.function_bytecode = b;+    b->header.ref_count++;+    p->u.func.home_object = NULL;+    p->u.func.var_refs = NULL;+    if (b->closure_var_count) {+        var_refs = js_mallocz(ctx, sizeof(var_refs[0]) * b->closure_var_count);+        if (!var_refs)+            goto fail;+        p->u.func.var_refs = var_refs;++        /* create the global variables. The other variables are+           imported from other modules */+        for(i = 0; i < b->closure_var_count; i++) {+            JSClosureVar *cv = &b->closure_var[i];+            JSVarRef *var_ref;+            if (cv->is_local) {+                var_ref = js_create_module_var(ctx, cv->is_lexical);+                if (!var_ref)+                    goto fail;+#ifdef DUMP_MODULE_RESOLVE+                printf("local %d: %p\n", i, var_ref);+#endif+                var_refs[i] = var_ref;+            }+        }+    }+    m->func_obj = func_obj;+    JS_FreeValue(ctx, bfunc);+    return 0;+ fail:+    JS_FreeValue(ctx, func_obj);+    return -1;+}++/* must be done before js_link_module() because of cyclic references */+static int js_create_module_function(JSContext *ctx, JSModuleDef *m)+{+    BOOL is_c_module;+    int i;+    JSVarRef *var_ref;+    +    if (m->func_created)+        return 0;++    is_c_module = (m->init_func != NULL);++    if (is_c_module) {+        /* initialize the exported variables */+        for(i = 0; i < m->export_entries_count; i++) {+            JSExportEntry *me = &m->export_entries[i];+            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+                var_ref = js_create_module_var(ctx, FALSE);+                if (!var_ref)+                    return -1;+                me->u.local.var_ref = var_ref;+            }+        }+    } else {+        if (js_create_module_bytecode_function(ctx, m))+            return -1;+    }+    m->func_created = TRUE;++    /* do it on the dependencies */+    +    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        if (js_create_module_function(ctx, rme->module) < 0)+            return -1;+    }++    return 0;+}    ++    +/* Prepare a module to be executed by resolving all the imported+   variables. */+static int js_link_module(JSContext *ctx, JSModuleDef *m)+{+    int i;+    JSImportEntry *mi;+    JSModuleDef *m1;+    JSVarRef **var_refs, *var_ref;+    JSObject *p;+    BOOL is_c_module;+    JSValue ret_val;+    +    if (m->instantiated)+        return 0;+    m->instantiated = TRUE;++#ifdef DUMP_MODULE_RESOLVE+    {+        char buf1[ATOM_GET_STR_BUF_SIZE];+        printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));+    }+#endif++    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        if (js_link_module(ctx, rme->module) < 0)+            goto fail;+    }++#ifdef DUMP_MODULE_RESOLVE+    {+        char buf1[ATOM_GET_STR_BUF_SIZE];+        printf("instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));+    }+#endif+    /* check the indirect exports */+    for(i = 0; i < m->export_entries_count; i++) {+        JSExportEntry *me = &m->export_entries[i];+        if (me->export_type == JS_EXPORT_TYPE_INDIRECT &&+            me->local_name != JS_ATOM__star_) {+            JSResolveResultEnum ret;+            JSExportEntry *res_me;+            JSModuleDef *res_m, *m1;+            m1 = m->req_module_entries[me->u.req_module_idx].module;+            ret = js_resolve_export(ctx, &res_m, &res_me, m1, me->local_name);+            if (ret != JS_RESOLVE_RES_FOUND) {+                js_resolve_export_throw_error(ctx, ret, m, me->export_name);+                goto fail;+            }+        }+    }++#ifdef DUMP_MODULE_RESOLVE+    {+        printf("exported bindings:\n");+        for(i = 0; i < m->export_entries_count; i++) {+            JSExportEntry *me = &m->export_entries[i];+            printf(" name="); print_atom(ctx, me->export_name);+            printf(" local="); print_atom(ctx, me->local_name);+            printf(" type=%d idx=%d\n", me->export_type, me->u.local.var_idx);+        }+    }+#endif++    is_c_module = (m->init_func != NULL);++    if (!is_c_module) {+        p = JS_VALUE_GET_OBJ(m->func_obj);+        var_refs = p->u.func.var_refs;++        for(i = 0; i < m->import_entries_count; i++) {+            mi = &m->import_entries[i];+#ifdef DUMP_MODULE_RESOLVE+            printf("import var_idx=%d name=", mi->var_idx);+            print_atom(ctx, mi->import_name);+            printf(": ");+#endif+            m1 = m->req_module_entries[mi->req_module_idx].module;+            if (mi->import_name == JS_ATOM__star_) {+                JSValue val;+                /* name space import */+                val = js_get_module_ns(ctx, m1);+                if (JS_IsException(val))+                    goto fail;+                set_value(ctx, &var_refs[mi->var_idx]->value, val);+#ifdef DUMP_MODULE_RESOLVE+                printf("namespace\n");+#endif+            } else {+                JSResolveResultEnum ret;+                JSExportEntry *res_me;+                JSModuleDef *res_m;+                JSObject *p1;++                ret = js_resolve_export(ctx, &res_m,+                                        &res_me, m1, mi->import_name);+                if (ret != JS_RESOLVE_RES_FOUND) {+                    js_resolve_export_throw_error(ctx, ret, m1, mi->import_name);+                    goto fail;+                }+                if (res_me->local_name == JS_ATOM__star_) {+                    JSValue val;+                    JSModuleDef *m2;+                    /* name space import from */+                    m2 = res_m->req_module_entries[res_me->u.req_module_idx].module;+                    val = js_get_module_ns(ctx, m2);+                    if (JS_IsException(val))+                        goto fail;+                    var_ref = js_create_module_var(ctx, TRUE);+                    if (!var_ref) {+                        JS_FreeValue(ctx, val);+                        goto fail;+                    }+                    set_value(ctx, &var_ref->value, val);+                    var_refs[mi->var_idx] = var_ref;+#ifdef DUMP_MODULE_RESOLVE+                    printf("namespace from\n");+#endif+                } else {+                    var_ref = res_me->u.local.var_ref;+                    if (!var_ref) {+                        p1 = JS_VALUE_GET_OBJ(res_m->func_obj);+                        var_ref = p1->u.func.var_refs[res_me->u.local.var_idx];+                    }+                    var_ref->header.ref_count++;+                    var_refs[mi->var_idx] = var_ref;+#ifdef DUMP_MODULE_RESOLVE+                    printf("local export (var_ref=%p)\n", var_ref);+#endif+                }+            }+        }++        /* keep the exported variables in the module export entries (they+           are used when the eval function is deleted and cannot be+           initialized before in case imports are exported) */+        for(i = 0; i < m->export_entries_count; i++) {+            JSExportEntry *me = &m->export_entries[i];+            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+                var_ref = var_refs[me->u.local.var_idx];+                var_ref->header.ref_count++;+                me->u.local.var_ref = var_ref;+            }+        }++        /* initialize the global variables */+        ret_val = JS_Call(ctx, m->func_obj, JS_TRUE, 0, NULL);+        if (JS_IsException(ret_val))+            goto fail;+        JS_FreeValue(ctx, ret_val);+    }++#ifdef DUMP_MODULE_RESOLVE+    printf("done instantiate\n");+#endif+    return 0;+ fail:+    return -1;+}++/* return JS_ATOM_NULL if the name cannot be found. Only works with+   not striped bytecode functions. */+JSAtom JS_GetScriptOrModuleName(JSContext *ctx, int n_stack_levels)+{+    JSStackFrame *sf;+    JSFunctionBytecode *b;+    JSObject *p;+    /* XXX: currently we just use the filename of the englobing+       function. It does not work for eval(). Need to add a+       ScriptOrModule info in JSFunctionBytecode */+    sf = ctx->rt->current_stack_frame;+    if (!sf)+        return JS_ATOM_NULL;+    while (n_stack_levels-- > 0) {+        sf = sf->prev_frame;+        if (!sf)+            return JS_ATOM_NULL;+    }+    if (JS_VALUE_GET_TAG(sf->cur_func) != JS_TAG_OBJECT)+        return JS_ATOM_NULL;+    p = JS_VALUE_GET_OBJ(sf->cur_func);+    if (!js_class_has_bytecode(p->class_id))+        return JS_ATOM_NULL;+    b = p->u.func.function_bytecode;+    if (!b->has_debug)+        return JS_ATOM_NULL;+    return JS_DupAtom(ctx, b->debug.filename);+}++JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m)+{+    return JS_DupAtom(ctx, m->module_name);+}++JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m)+{+    JSValue obj;+    /* allocate meta_obj only if requested to save memory */+    obj = m->meta_obj;+    if (JS_IsUndefined(obj)) {+        obj = JS_NewObjectProto(ctx, JS_NULL);+        if (JS_IsException(obj))+            return JS_EXCEPTION;+        m->meta_obj = obj;+    }+    return JS_DupValue(ctx, obj);+}++static JSValue js_import_meta(JSContext *ctx)+{+    JSAtom filename;+    JSModuleDef *m;+    +    filename = JS_GetScriptOrModuleName(ctx, 0);+    if (filename == JS_ATOM_NULL)+        goto fail;++    /* XXX: inefficient, need to add a module or script pointer in+       JSFunctionBytecode */+    m = js_find_loaded_module(ctx, filename);+    JS_FreeAtom(ctx, filename);+    if (!m) {+    fail:+        JS_ThrowTypeError(ctx, "import.meta not supported in this context");+        return JS_EXCEPTION;+    }+    return JS_GetImportMeta(ctx, m);+}++/* used by os.Worker() and import() */+JSModuleDef *JS_RunModule(JSContext *ctx, const char *basename,+                          const char *filename)+{+    JSModuleDef *m;+    JSValue ret, func_obj;+    +    m = js_host_resolve_imported_module(ctx, basename, filename);+    if (!m)+        return NULL;+    +    if (js_resolve_module(ctx, m) < 0) {+        js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);+        return NULL;+    }++    /* Evaluate the module code */+    func_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));+    ret = JS_EvalFunction(ctx, func_obj);+    if (JS_IsException(ret))+        return NULL;+    JS_FreeValue(ctx, ret);+    return m;+}++static JSValue js_dynamic_import_job(JSContext *ctx,+                                     int argc, JSValueConst *argv)+{+    JSValueConst *resolving_funcs = argv;+    JSValueConst basename_val = argv[2];+    JSValueConst specifier = argv[3];+    JSModuleDef *m;+    const char *basename = NULL, *filename;+    JSValue ret, err, ns;++    if (!JS_IsString(basename_val)) {+        JS_ThrowTypeError(ctx, "no function filename for import()");+        goto exception;+    }+    basename = JS_ToCString(ctx, basename_val);+    if (!basename)+        goto exception;++    filename = JS_ToCString(ctx, specifier);+    if (!filename)+        goto exception;+                     +    m = JS_RunModule(ctx, basename, filename);+    JS_FreeCString(ctx, filename);+    if (!m)+        goto exception;++    /* return the module namespace */+    ns = js_get_module_ns(ctx, m);+    if (JS_IsException(ns))+        goto exception;++    ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,+                   1, (JSValueConst *)&ns);+    JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */+    JS_FreeValue(ctx, ns);+    JS_FreeCString(ctx, basename);+    return JS_UNDEFINED;+ exception:++    err = JS_GetException(ctx);+    ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,+                   1, (JSValueConst *)&err);+    JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */+    JS_FreeValue(ctx, err);+    JS_FreeCString(ctx, basename);+    return JS_UNDEFINED;+}++static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)+{+    JSAtom basename;+    JSValue promise, resolving_funcs[2], basename_val;+    JSValueConst args[4];++    basename = JS_GetScriptOrModuleName(ctx, 0);+    if (basename == JS_ATOM_NULL)+        basename_val = JS_NULL;+    else+        basename_val = JS_AtomToValue(ctx, basename);+    JS_FreeAtom(ctx, basename);+    if (JS_IsException(basename_val))+        return basename_val;+    +    promise = JS_NewPromiseCapability(ctx, resolving_funcs);+    if (JS_IsException(promise)) {+        JS_FreeValue(ctx, basename_val);+        return promise;+    }++    args[0] = resolving_funcs[0];+    args[1] = resolving_funcs[1];+    args[2] = basename_val;+    args[3] = specifier;+    +    JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);++    JS_FreeValue(ctx, basename_val);+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    return promise;+}++/* Run the <eval> function of the module and of all its requested+   modules. */+static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)+{+    JSModuleDef *m1;+    int i;+    JSValue ret_val;++    if (m->eval_mark)+        return JS_UNDEFINED; /* avoid cycles */++    if (m->evaluated) {+        /* if the module was already evaluated, rethrow the exception+           it raised */+        if (m->eval_has_exception) {+            return JS_Throw(ctx, JS_DupValue(ctx, m->eval_exception));+        } else {+            return JS_UNDEFINED;+        }+    }++    m->eval_mark = TRUE;++    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        m1 = rme->module;+        if (!m1->eval_mark) {+            ret_val = js_evaluate_module(ctx, m1);+            if (JS_IsException(ret_val)) {+                m->eval_mark = FALSE;+                return ret_val;+            }+            JS_FreeValue(ctx, ret_val);+        }+    }++    if (m->init_func) {+        /* C module init */+        if (m->init_func(ctx, m) < 0)+            ret_val = JS_EXCEPTION;+        else+            ret_val = JS_UNDEFINED;+    } else {+        ret_val = JS_CallFree(ctx, m->func_obj, JS_UNDEFINED, 0, NULL);+        m->func_obj = JS_UNDEFINED;+    }+    if (JS_IsException(ret_val)) {+        /* save the thrown exception value */+        m->eval_has_exception = TRUE;+        m->eval_exception = JS_DupValue(ctx, ctx->rt->current_exception);+    }+    m->eval_mark = FALSE;+    m->evaluated = TRUE;+    return ret_val;+}++static __exception JSAtom js_parse_from_clause(JSParseState *s)+{+    JSAtom module_name;+    if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {+        js_parse_error(s, "from clause expected");+        return JS_ATOM_NULL;+    }+    if (next_token(s))+        return JS_ATOM_NULL;+    if (s->token.val != TOK_STRING) {+        js_parse_error(s, "string expected");+        return JS_ATOM_NULL;+    }+    module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);+    if (module_name == JS_ATOM_NULL)+        return JS_ATOM_NULL;+    if (next_token(s)) {+        JS_FreeAtom(s->ctx, module_name);+        return JS_ATOM_NULL;+    }+    return module_name;+}++static __exception int js_parse_export(JSParseState *s)+{+    JSContext *ctx = s->ctx;+    JSModuleDef *m = s->cur_func->module;+    JSAtom local_name, export_name;+    int first_export, idx, i, tok;+    JSAtom module_name;+    JSExportEntry *me;++    if (next_token(s))+        return -1;++    tok = s->token.val;+    if (tok == TOK_CLASS) {+        return js_parse_class(s, FALSE, JS_PARSE_EXPORT_NAMED);+    } else if (tok == TOK_FUNCTION ||+               (token_is_pseudo_keyword(s, JS_ATOM_async) &&+                peek_token(s, TRUE) == TOK_FUNCTION)) {+        return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,+                                       JS_FUNC_NORMAL, JS_ATOM_NULL,+                                       s->token.ptr, s->token.line_num,+                                       JS_PARSE_EXPORT_NAMED, NULL);+    }++    if (next_token(s))+        return -1;++    switch(tok) {+    case '{':+        first_export = m->export_entries_count;+        while (s->token.val != '}') {+            if (!token_is_ident(s->token.val)) {+                js_parse_error(s, "identifier expected");+                return -1;+            }+            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            export_name = JS_ATOM_NULL;+            if (next_token(s))+                goto fail;+            if (token_is_pseudo_keyword(s, JS_ATOM_as)) {+                if (next_token(s))+                    goto fail;+                if (!token_is_ident(s->token.val)) {+                    js_parse_error(s, "identifier expected");+                    goto fail;+                }+                export_name = JS_DupAtom(ctx, s->token.u.ident.atom);+                if (next_token(s)) {+                fail:+                    JS_FreeAtom(ctx, local_name);+                fail1:+                    JS_FreeAtom(ctx, export_name);+                    return -1;+                }+            } else {+                export_name = JS_DupAtom(ctx, local_name);+            }+            me = add_export_entry(s, m, local_name, export_name,+                                  JS_EXPORT_TYPE_LOCAL);+            JS_FreeAtom(ctx, local_name);+            JS_FreeAtom(ctx, export_name);+            if (!me)+                return -1;+            if (s->token.val != ',')+                break;+            if (next_token(s))+                return -1;+        }+        if (js_parse_expect(s, '}'))+            return -1;+        if (token_is_pseudo_keyword(s, JS_ATOM_from)) {+            module_name = js_parse_from_clause(s);+            if (module_name == JS_ATOM_NULL)+                return -1;+            idx = add_req_module_entry(ctx, m, module_name);+            JS_FreeAtom(ctx, module_name);+            if (idx < 0)+                return -1;+            for(i = first_export; i < m->export_entries_count; i++) {+                me = &m->export_entries[i];+                me->export_type = JS_EXPORT_TYPE_INDIRECT;+                me->u.req_module_idx = idx;+            }+        }+        break;+    case '*':+        if (token_is_pseudo_keyword(s, JS_ATOM_as)) {+            /* export ns from */+            if (next_token(s))+                return -1;+            if (!token_is_ident(s->token.val)) {+                js_parse_error(s, "identifier expected");+                return -1;+            }+            export_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            if (next_token(s))+                goto fail1;+            module_name = js_parse_from_clause(s);+            if (module_name == JS_ATOM_NULL)+                goto fail1;+            idx = add_req_module_entry(ctx, m, module_name);+            JS_FreeAtom(ctx, module_name);+            if (idx < 0)+                goto fail1;+            me = add_export_entry(s, m, JS_ATOM__star_, export_name,+                                  JS_EXPORT_TYPE_INDIRECT);+            JS_FreeAtom(ctx, export_name);+            if (!me)+                return -1;+            me->u.req_module_idx = idx;+        } else {+            module_name = js_parse_from_clause(s);+            if (module_name == JS_ATOM_NULL)+                return -1;+            idx = add_req_module_entry(ctx, m, module_name);+            JS_FreeAtom(ctx, module_name);+            if (idx < 0)+                return -1;+            if (add_star_export_entry(ctx, m, idx) < 0)+                return -1;+        }+        break;+    case TOK_DEFAULT:+        if (s->token.val == TOK_CLASS) {+            return js_parse_class(s, FALSE, JS_PARSE_EXPORT_DEFAULT);+        } else if (s->token.val == TOK_FUNCTION ||+                   (token_is_pseudo_keyword(s, JS_ATOM_async) &&+                    peek_token(s, TRUE) == TOK_FUNCTION)) {+            return js_parse_function_decl2(s, JS_PARSE_FUNC_STATEMENT,+                                           JS_FUNC_NORMAL, JS_ATOM_NULL,+                                           s->token.ptr, s->token.line_num,+                                           JS_PARSE_EXPORT_DEFAULT, NULL);+        } else {+            if (js_parse_assign_expr(s))+                return -1;+        }+        /* set the name of anonymous functions */+        set_object_name(s, JS_ATOM_default);++        /* store the value in the _default_ global variable and export+           it */+        local_name = JS_ATOM__default_;+        if (define_var(s, s->cur_func, local_name, JS_VAR_DEF_LET) < 0)+            return -1;+        emit_op(s, OP_scope_put_var_init);+        emit_atom(s, local_name);+        emit_u16(s, 0);++        if (!add_export_entry(s, m, local_name, JS_ATOM_default,+                              JS_EXPORT_TYPE_LOCAL))+            return -1;+        break;+    case TOK_VAR:+    case TOK_LET:+    case TOK_CONST:+        return js_parse_var(s, TRUE, tok, TRUE);+    default:+        return js_parse_error(s, "invalid export syntax");+    }+    return js_parse_expect_semi(s);+}++static int add_closure_var(JSContext *ctx, JSFunctionDef *s,+                           BOOL is_local, BOOL is_arg,+                           int var_idx, JSAtom var_name,+                           BOOL is_const, BOOL is_lexical,+                           JSVarKindEnum var_kind);++static int add_import(JSParseState *s, JSModuleDef *m,+                      JSAtom local_name, JSAtom import_name)+{+    JSContext *ctx = s->ctx;+    int i, var_idx;+    JSImportEntry *mi;+    BOOL is_local;++    if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval)+        return js_parse_error(s, "invalid import binding");++    if (local_name != JS_ATOM_default) {+        for (i = 0; i < s->cur_func->closure_var_count; i++) {+            if (s->cur_func->closure_var[i].var_name == local_name)+                return js_parse_error(s, "duplicate import binding");+        }+    }++    is_local = (import_name == JS_ATOM__star_);+    var_idx = add_closure_var(ctx, s->cur_func, is_local, FALSE,+                              m->import_entries_count,+                              local_name, TRUE, TRUE, FALSE);+    if (var_idx < 0)+        return -1;+    if (js_resize_array(ctx, (void **)&m->import_entries,+                        sizeof(JSImportEntry),+                        &m->import_entries_size,+                        m->import_entries_count + 1))+        return -1;+    mi = &m->import_entries[m->import_entries_count++];+    mi->import_name = JS_DupAtom(ctx, import_name);+    mi->var_idx = var_idx;+    return 0;+}++static __exception int js_parse_import(JSParseState *s)+{+    JSContext *ctx = s->ctx;+    JSModuleDef *m = s->cur_func->module;+    JSAtom local_name, import_name, module_name;+    int first_import, i, idx;++    if (next_token(s))+        return -1;++    first_import = m->import_entries_count;+    if (s->token.val == TOK_STRING) {+        module_name = JS_ValueToAtom(ctx, s->token.u.str.str);+        if (module_name == JS_ATOM_NULL)+            return -1;+        if (next_token(s)) {+            JS_FreeAtom(ctx, module_name);+            return -1;+        }+    } else {+        if (s->token.val == TOK_IDENT) {+            if (s->token.u.ident.is_reserved) {+                return js_parse_error_reserved_identifier(s);+            }+            /* "default" import */+            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            import_name = JS_ATOM_default;+            if (next_token(s))+                goto fail;+            if (add_import(s, m, local_name, import_name))+                goto fail;+            JS_FreeAtom(ctx, local_name);++            if (s->token.val != ',')+                goto end_import_clause;+            if (next_token(s))+                return -1;+        }++        if (s->token.val == '*') {+            /* name space import */+            if (next_token(s))+                return -1;+            if (!token_is_pseudo_keyword(s, JS_ATOM_as))+                return js_parse_error(s, "expecting 'as'");+            if (next_token(s))+                return -1;+            if (!token_is_ident(s->token.val)) {+                js_parse_error(s, "identifier expected");+                return -1;+            }+            local_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            import_name = JS_ATOM__star_;+            if (next_token(s))+                goto fail;+            if (add_import(s, m, local_name, import_name))+                goto fail;+            JS_FreeAtom(ctx, local_name);+        } else if (s->token.val == '{') {+            if (next_token(s))+                return -1;++            while (s->token.val != '}') {+                if (!token_is_ident(s->token.val)) {+                    js_parse_error(s, "identifier expected");+                    return -1;+                }+                import_name = JS_DupAtom(ctx, s->token.u.ident.atom);+                local_name = JS_ATOM_NULL;+                if (next_token(s))+                    goto fail;+                if (token_is_pseudo_keyword(s, JS_ATOM_as)) {+                    if (next_token(s))+                        goto fail;+                    if (!token_is_ident(s->token.val)) {+                        js_parse_error(s, "identifier expected");+                        goto fail;+                    }+                    local_name = JS_DupAtom(ctx, s->token.u.ident.atom);+                    if (next_token(s)) {+                    fail:+                        JS_FreeAtom(ctx, local_name);+                        JS_FreeAtom(ctx, import_name);+                        return -1;+                    }+                } else {+                    local_name = JS_DupAtom(ctx, import_name);+                }+                if (add_import(s, m, local_name, import_name))+                    goto fail;+                JS_FreeAtom(ctx, local_name);+                JS_FreeAtom(ctx, import_name);+                if (s->token.val != ',')+                    break;+                if (next_token(s))+                    return -1;+            }+            if (js_parse_expect(s, '}'))+                return -1;+        }+    end_import_clause:+        module_name = js_parse_from_clause(s);+        if (module_name == JS_ATOM_NULL)+            return -1;+    }+    idx = add_req_module_entry(ctx, m, module_name);+    JS_FreeAtom(ctx, module_name);+    if (idx < 0)+        return -1;+    for(i = first_import; i < m->import_entries_count; i++)+        m->import_entries[i].req_module_idx = idx;++    return js_parse_expect_semi(s);+}++static __exception int js_parse_source_element(JSParseState *s)+{+    JSFunctionDef *fd = s->cur_func;+    int tok;+    +    if (s->token.val == TOK_FUNCTION ||+        (token_is_pseudo_keyword(s, JS_ATOM_async) &&+         peek_token(s, TRUE) == TOK_FUNCTION)) {+        if (js_parse_function_decl(s, JS_PARSE_FUNC_STATEMENT,+                                   JS_FUNC_NORMAL, JS_ATOM_NULL,+                                   s->token.ptr, s->token.line_num))+            return -1;+    } else if (s->token.val == TOK_EXPORT && fd->module) {+        if (js_parse_export(s))+            return -1;+    } else if (s->token.val == TOK_IMPORT && fd->module &&+               ((tok = peek_token(s, FALSE)) != '(' && tok != '.'))  {+        /* the peek_token is needed to avoid confusion with ImportCall+           (dynamic import) or import.meta */+        if (js_parse_import(s))+            return -1;+    } else {+        if (js_parse_statement_or_decl(s, DECL_MASK_ALL))+            return -1;+    }+    return 0;+}++static JSFunctionDef *js_new_function_def(JSContext *ctx,+                                          JSFunctionDef *parent,+                                          BOOL is_eval,+                                          BOOL is_func_expr,+                                          const char *filename, int line_num)+{+    JSFunctionDef *fd;++    fd = js_mallocz(ctx, sizeof(*fd));+    if (!fd)+        return NULL;++    fd->ctx = ctx;+    init_list_head(&fd->child_list);++    /* insert in parent list */+    fd->parent = parent;+    fd->parent_cpool_idx = -1;+    if (parent) {+        list_add_tail(&fd->link, &parent->child_list);+        fd->js_mode = parent->js_mode;+        fd->parent_scope_level = parent->scope_level;+    }++    fd->is_eval = is_eval;+    fd->is_func_expr = is_func_expr;+    js_dbuf_init(ctx, &fd->byte_code);+    fd->last_opcode_pos = -1;+    fd->func_name = JS_ATOM_NULL;+    fd->var_object_idx = -1;+    fd->arg_var_object_idx = -1;+    fd->arguments_var_idx = -1;+    fd->arguments_arg_idx = -1;+    fd->func_var_idx = -1;+    fd->eval_ret_idx = -1;+    fd->this_var_idx = -1;+    fd->new_target_var_idx = -1;+    fd->this_active_func_var_idx = -1;+    fd->home_object_var_idx = -1;++    /* XXX: should distinguish arg, var and var object and body scopes */+    fd->scopes = fd->def_scope_array;+    fd->scope_size = countof(fd->def_scope_array);+    fd->scope_count = 1;+    fd->scopes[0].first = -1;+    fd->scopes[0].parent = -1;+    fd->scope_level = 0;  /* 0: var/arg scope */+    fd->scope_first = -1;+    fd->body_scope = -1;++    fd->filename = JS_NewAtom(ctx, filename);+    fd->line_num = line_num;++    js_dbuf_init(ctx, &fd->pc2line);+    //fd->pc2line_last_line_num = line_num;+    //fd->pc2line_last_pc = 0;+    fd->last_opcode_line_num = line_num;++    return fd;+}++static void free_bytecode_atoms(JSRuntime *rt,+                                const uint8_t *bc_buf, int bc_len,+                                BOOL use_short_opcodes)+{+    int pos, len, op;+    JSAtom atom;+    const JSOpCode *oi;+    +    pos = 0;+    while (pos < bc_len) {+        op = bc_buf[pos];+        if (use_short_opcodes)+            oi = &short_opcode_info(op);+        else+            oi = &opcode_info[op];+            +        len = oi->size;+        switch(oi->fmt) {+        case OP_FMT_atom:+        case OP_FMT_atom_u8:+        case OP_FMT_atom_u16:+        case OP_FMT_atom_label_u8:+        case OP_FMT_atom_label_u16:+            atom = get_u32(bc_buf + pos + 1);+            JS_FreeAtomRT(rt, atom);+            break;+        default:+            break;+        }+        pos += len;+    }+}++static void js_free_function_def(JSContext *ctx, JSFunctionDef *fd)+{+    int i;+    struct list_head *el, *el1;++    /* free the child functions */+    list_for_each_safe(el, el1, &fd->child_list) {+        JSFunctionDef *fd1;+        fd1 = list_entry(el, JSFunctionDef, link);+        js_free_function_def(ctx, fd1);+    }++    free_bytecode_atoms(ctx->rt, fd->byte_code.buf, fd->byte_code.size,+                        fd->use_short_opcodes);+    dbuf_free(&fd->byte_code);+    js_free(ctx, fd->jump_slots);+    js_free(ctx, fd->label_slots);+    js_free(ctx, fd->line_number_slots);++    for(i = 0; i < fd->cpool_count; i++) {+        JS_FreeValue(ctx, fd->cpool[i]);+    }+    js_free(ctx, fd->cpool);++    JS_FreeAtom(ctx, fd->func_name);++    for(i = 0; i < fd->var_count; i++) {+        JS_FreeAtom(ctx, fd->vars[i].var_name);+    }+    js_free(ctx, fd->vars);+    for(i = 0; i < fd->arg_count; i++) {+        JS_FreeAtom(ctx, fd->args[i].var_name);+    }+    js_free(ctx, fd->args);++    for(i = 0; i < fd->global_var_count; i++) {+        JS_FreeAtom(ctx, fd->global_vars[i].var_name);+    }+    js_free(ctx, fd->global_vars);++    for(i = 0; i < fd->closure_var_count; i++) {+        JSClosureVar *cv = &fd->closure_var[i];+        JS_FreeAtom(ctx, cv->var_name);+    }+    js_free(ctx, fd->closure_var);++    if (fd->scopes != fd->def_scope_array)+        js_free(ctx, fd->scopes);++    JS_FreeAtom(ctx, fd->filename);+    dbuf_free(&fd->pc2line);++    js_free(ctx, fd->source);++    if (fd->parent) {+        /* remove in parent list */+        list_del(&fd->link);+    }+    js_free(ctx, fd);+}++#ifdef DUMP_BYTECODE+static const char *skip_lines(const char *p, int n) {+    while (n-- > 0 && *p) {+        while (*p && *p++ != '\n')+            continue;+    }+    return p;+}++static void print_lines(const char *source, int line, int line1) {+    const char *s = source;+    const char *p = skip_lines(s, line);+    if (*p) {+        while (line++ < line1) {+            p = skip_lines(s = p, 1);+            printf(";; %.*s", (int)(p - s), s);+            if (!*p) {+                if (p[-1] != '\n')+                    printf("\n");+                break;+            }+        }+    }+}++static void dump_byte_code(JSContext *ctx, int pass,+                           const uint8_t *tab, int len,+                           const JSVarDef *args, int arg_count,+                           const JSVarDef *vars, int var_count,+                           const JSClosureVar *closure_var, int closure_var_count,+                           const JSValue *cpool, uint32_t cpool_count,+                           const char *source, int line_num,+                           const LabelSlot *label_slots, JSFunctionBytecode *b)+{+    const JSOpCode *oi;+    int pos, pos_next, op, size, idx, addr, line, line1, in_source;+    uint8_t *bits = js_mallocz(ctx, len * sizeof(*bits));+    BOOL use_short_opcodes = (b != NULL);++    /* scan for jump targets */+    for (pos = 0; pos < len; pos = pos_next) {+        op = tab[pos];+        if (use_short_opcodes)+            oi = &short_opcode_info(op);+        else+            oi = &opcode_info[op];+        pos_next = pos + oi->size;+        if (op < OP_COUNT) {+            switch (oi->fmt) {+#if SHORT_OPCODES+            case OP_FMT_label8:+                pos++;+                addr = (int8_t)tab[pos];+                goto has_addr;+            case OP_FMT_label16:+                pos++;+                addr = (int16_t)get_u16(tab + pos);+                goto has_addr;+#endif+            case OP_FMT_atom_label_u8:+            case OP_FMT_atom_label_u16:+                pos += 4;+                /* fall thru */+            case OP_FMT_label:+            case OP_FMT_label_u16:+                pos++;+                addr = get_u32(tab + pos);+                goto has_addr;+            has_addr:+                if (pass == 1)+                    addr = label_slots[addr].pos;+                if (pass == 2)+                    addr = label_slots[addr].pos2;+                if (pass == 3)+                    addr += pos;+                if (addr >= 0 && addr < len)+                    bits[addr] |= 1;+                break;+            }+        }+    }+    in_source = 0;+    if (source) {+        /* Always print first line: needed if single line */+        print_lines(source, 0, 1);+        in_source = 1;+    }+    line1 = line = 1;+    pos = 0;+    while (pos < len) {+        op = tab[pos];+        if (source) {+            if (b) {+                line1 = find_line_num(ctx, b, pos) - line_num + 1;+            } else if (op == OP_line_num) {+                line1 = get_u32(tab + pos + 1) - line_num + 1;+            }+            if (line1 > line) {+                if (!in_source)+                    printf("\n");+                in_source = 1;+                print_lines(source, line, line1);+                line = line1;+                //bits[pos] |= 2;+            }+        }+        if (in_source)+            printf("\n");+        in_source = 0;+        if (op >= OP_COUNT) {+            printf("invalid opcode (0x%02x)\n", op);+            pos++;+            continue;+        }+        if (use_short_opcodes)+            oi = &short_opcode_info(op);+        else+            oi = &opcode_info[op];+        size = oi->size;+        if (pos + size > len) {+            printf("truncated opcode (0x%02x)\n", op);+            break;+        }+#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 16)+        {+            int i, x, x0;+            x = x0 = printf("%5d ", pos);+            for (i = 0; i < size; i++) {+                if (i == 6) {+                    printf("\n%*s", x = x0, "");+                }+                x += printf(" %02X", tab[pos + i]);+            }+            printf("%*s", x0 + 20 - x, "");+        }+#endif+        if (bits[pos]) {+            printf("%5d:  ", pos);+        } else {+            printf("        ");+        }+        printf("%s", oi->name);+        pos++;+        switch(oi->fmt) {+        case OP_FMT_none_int:+            printf(" %d", op - OP_push_0);+            break;+        case OP_FMT_npopx:+            printf(" %d", op - OP_call0);+            break;+        case OP_FMT_u8:+            printf(" %u", get_u8(tab + pos));+            break;+        case OP_FMT_i8:+            printf(" %d", get_i8(tab + pos));+            break;+        case OP_FMT_u16:+        case OP_FMT_npop:+            printf(" %u", get_u16(tab + pos));+            break;+        case OP_FMT_npop_u16:+            printf(" %u,%u", get_u16(tab + pos), get_u16(tab + pos + 2));+            break;+        case OP_FMT_i16:+            printf(" %d", get_i16(tab + pos));+            break;+        case OP_FMT_i32:+            printf(" %d", get_i32(tab + pos));+            break;+        case OP_FMT_u32:+            printf(" %u", get_u32(tab + pos));+            break;+#if SHORT_OPCODES+        case OP_FMT_label8:+            addr = get_i8(tab + pos);+            goto has_addr1;+        case OP_FMT_label16:+            addr = get_i16(tab + pos);+            goto has_addr1;+#endif+        case OP_FMT_label:+            addr = get_u32(tab + pos);+            goto has_addr1;+        has_addr1:+            if (pass == 1)+                printf(" %u:%u", addr, label_slots[addr].pos);+            if (pass == 2)+                printf(" %u:%u", addr, label_slots[addr].pos2);+            if (pass == 3)+                printf(" %u", addr + pos);+            break;+        case OP_FMT_label_u16:+            addr = get_u32(tab + pos);+            if (pass == 1)+                printf(" %u:%u", addr, label_slots[addr].pos);+            if (pass == 2)+                printf(" %u:%u", addr, label_slots[addr].pos2);+            if (pass == 3)+                printf(" %u", addr + pos);+            printf(",%u", get_u16(tab + pos + 4));+            break;+#if SHORT_OPCODES+        case OP_FMT_const8:+            idx = get_u8(tab + pos);+            goto has_pool_idx;+#endif+        case OP_FMT_const:+            idx = get_u32(tab + pos);+            goto has_pool_idx;+        has_pool_idx:+            printf(" %u: ", idx);+            if (idx < cpool_count) {+                JS_DumpValue(ctx, cpool[idx]);+            }+            break;+        case OP_FMT_atom:+            printf(" ");+            print_atom(ctx, get_u32(tab + pos));+            break;+        case OP_FMT_atom_u8:+            printf(" ");+            print_atom(ctx, get_u32(tab + pos));+            printf(",%d", get_u8(tab + pos + 4));+            break;+        case OP_FMT_atom_u16:+            printf(" ");+            print_atom(ctx, get_u32(tab + pos));+            printf(",%d", get_u16(tab + pos + 4));+            break;+        case OP_FMT_atom_label_u8:+        case OP_FMT_atom_label_u16:+            printf(" ");+            print_atom(ctx, get_u32(tab + pos));+            addr = get_u32(tab + pos + 4);+            if (pass == 1)+                printf(",%u:%u", addr, label_slots[addr].pos);+            if (pass == 2)+                printf(",%u:%u", addr, label_slots[addr].pos2);+            if (pass == 3)+                printf(",%u", addr + pos + 4);+            if (oi->fmt == OP_FMT_atom_label_u8)+                printf(",%u", get_u8(tab + pos + 8));+            else+                printf(",%u", get_u16(tab + pos + 8));+            break;+        case OP_FMT_none_loc:+            idx = (op - OP_get_loc0) % 4;+            goto has_loc;+        case OP_FMT_loc8:+            idx = get_u8(tab + pos);+            goto has_loc;+        case OP_FMT_loc:+            idx = get_u16(tab + pos);+        has_loc:+            printf(" %d: ", idx);+            if (idx < var_count) {+                print_atom(ctx, vars[idx].var_name);+            }+            break;+        case OP_FMT_none_arg:+            idx = (op - OP_get_arg0) % 4;+            goto has_arg;+        case OP_FMT_arg:+            idx = get_u16(tab + pos);+        has_arg:+            printf(" %d: ", idx);+            if (idx < arg_count) {+                print_atom(ctx, args[idx].var_name);+            }+            break;+        case OP_FMT_none_var_ref:+            idx = (op - OP_get_var_ref0) % 4;+            goto has_var_ref;+        case OP_FMT_var_ref:+            idx = get_u16(tab + pos);+        has_var_ref:+            printf(" %d: ", idx);+            if (idx < closure_var_count) {+                print_atom(ctx, closure_var[idx].var_name);+            }+            break;+        default:+            break;+        }+        printf("\n");+        pos += oi->size - 1;+    }+    if (source) {+        if (!in_source)+            printf("\n");+        print_lines(source, line, INT32_MAX);+    }+    js_free(ctx, bits);+}++static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,+                                                 int line_num)+{+    const uint8_t *p_end, *p_next, *p;+    int pc, v;+    unsigned int op;++    if (len <= 0)+        return;++    printf("%5s %5s\n", "PC", "LINE");++    p = buf;+    p_end = buf + len;+    pc = 0;+    while (p < p_end) {+        op = *p++;+        if (op == 0) {+            v = unicode_from_utf8(p, p_end - p, &p_next);+            if (v < 0)+                goto fail;+            pc += v;+            p = p_next;+            v = unicode_from_utf8(p, p_end - p, &p_next);+            if (v < 0) {+            fail:+                printf("invalid pc2line encode pos=%d\n", (int)(p - buf));+                return;+            }+            if (!(v & 1)) {+                v = v >> 1;+            } else {+                v = -(v >> 1) - 1;+            }+            line_num += v;+            p = p_next;+        } else {+            op -= PC2LINE_OP_FIRST;+            pc += (op / PC2LINE_RANGE);+            line_num += (op % PC2LINE_RANGE) + PC2LINE_BASE;+        }+        printf("%5d %5d\n", pc, line_num);+    }+}++static __maybe_unused void js_dump_function_bytecode(JSContext *ctx, JSFunctionBytecode *b)+{+    int i;+    char atom_buf[ATOM_GET_STR_BUF_SIZE];+    const char *str;++    if (b->has_debug && b->debug.filename != JS_ATOM_NULL) {+        str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->debug.filename);+        printf("%s:%d: ", str, b->debug.line_num);+    }++    str = JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), b->func_name);+    printf("function: %s%s\n", &"*"[b->func_kind != JS_FUNC_GENERATOR], str);+    if (b->js_mode) {+        printf("  mode:");+        if (b->js_mode & JS_MODE_STRICT)+            printf(" strict");+#ifdef CONFIG_BIGNUM+        if (b->js_mode & JS_MODE_MATH)+            printf(" math");+#endif+        printf("\n");+    }+    if (b->arg_count && b->vardefs) {+        printf("  args:");+        for(i = 0; i < b->arg_count; i++) {+            printf(" %s", JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf),+                                        b->vardefs[i].var_name));+        }+        printf("\n");+    }+    if (b->var_count && b->vardefs) {+        printf("  locals:\n");+        for(i = 0; i < b->var_count; i++) {+            JSVarDef *vd = &b->vardefs[b->arg_count + i];+            printf("%5d: %s %s", i,+                   vd->var_kind == JS_VAR_CATCH ? "catch" :+                   (vd->var_kind == JS_VAR_FUNCTION_DECL ||+                    vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) ? "function" :+                   vd->is_const ? "const" :+                   vd->is_lexical ? "let" : "var",+                   JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), vd->var_name));+            if (vd->scope_level)+                printf(" [level:%d next:%d]", vd->scope_level, vd->scope_next);+            printf("\n");+        }+    }+    if (b->closure_var_count) {+        printf("  closure vars:\n");+        for(i = 0; i < b->closure_var_count; i++) {+            JSClosureVar *cv = &b->closure_var[i];+            printf("%5d: %s %s:%s%d %s\n", i,+                   JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), cv->var_name),+                   cv->is_local ? "local" : "parent",+                   cv->is_arg ? "arg" : "loc", cv->var_idx,+                   cv->is_const ? "const" :+                   cv->is_lexical ? "let" : "var");+        }+    }+    printf("  stack_size: %d\n", b->stack_size);+    printf("  opcodes:\n");+    dump_byte_code(ctx, 3, b->byte_code_buf, b->byte_code_len,+                   b->vardefs, b->arg_count,+                   b->vardefs ? b->vardefs + b->arg_count : NULL, b->var_count,+                   b->closure_var, b->closure_var_count,+                   b->cpool, b->cpool_count,+                   b->has_debug ? b->debug.source : NULL,+                   b->has_debug ? b->debug.line_num : -1, NULL, b);+#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 32)+    if (b->has_debug)+        dump_pc2line(ctx, b->debug.pc2line_buf, b->debug.pc2line_len, b->debug.line_num);+#endif+    printf("\n");+}+#endif++static int add_closure_var(JSContext *ctx, JSFunctionDef *s,+                           BOOL is_local, BOOL is_arg,+                           int var_idx, JSAtom var_name,+                           BOOL is_const, BOOL is_lexical,+                           JSVarKindEnum var_kind)+{+    JSClosureVar *cv;++    /* the closure variable indexes are currently stored on 16 bits */+    if (s->closure_var_count >= JS_MAX_LOCAL_VARS) {+        JS_ThrowInternalError(ctx, "too many closure variables");+        return -1;+    }++    if (js_resize_array(ctx, (void **)&s->closure_var,+                        sizeof(s->closure_var[0]),+                        &s->closure_var_size, s->closure_var_count + 1))+        return -1;+    cv = &s->closure_var[s->closure_var_count++];+    cv->is_local = is_local;+    cv->is_arg = is_arg;+    cv->is_const = is_const;+    cv->is_lexical = is_lexical;+    cv->var_kind = var_kind;+    cv->var_idx = var_idx;+    cv->var_name = JS_DupAtom(ctx, var_name);+    return s->closure_var_count - 1;+}++static int find_closure_var(JSContext *ctx, JSFunctionDef *s,+                            JSAtom var_name)+{+    int i;+    for(i = 0; i < s->closure_var_count; i++) {+        JSClosureVar *cv = &s->closure_var[i];+        if (cv->var_name == var_name)+            return i;+    }+    return -1;+}++/* 'fd' must be a parent of 's'. Create in 's' a closure referencing a+   local variable (is_local = TRUE) or a closure (is_local = FALSE) in+   'fd' */+static int get_closure_var2(JSContext *ctx, JSFunctionDef *s,+                            JSFunctionDef *fd, BOOL is_local,+                            BOOL is_arg, int var_idx, JSAtom var_name,+                            BOOL is_const, BOOL is_lexical,+                            JSVarKindEnum var_kind)+{+    int i;++    if (fd != s->parent) {+        var_idx = get_closure_var2(ctx, s->parent, fd, is_local,+                                   is_arg, var_idx, var_name,+                                   is_const, is_lexical, var_kind);+        if (var_idx < 0)+            return -1;+        is_local = FALSE;+    }+    for(i = 0; i < s->closure_var_count; i++) {+        JSClosureVar *cv = &s->closure_var[i];+        if (cv->var_idx == var_idx && cv->is_arg == is_arg &&+            cv->is_local == is_local)+            return i;+    }+    return add_closure_var(ctx, s, is_local, is_arg, var_idx, var_name,+                           is_const, is_lexical, var_kind);+}++static int get_closure_var(JSContext *ctx, JSFunctionDef *s,+                           JSFunctionDef *fd, BOOL is_arg,+                           int var_idx, JSAtom var_name,+                           BOOL is_const, BOOL is_lexical,+                           JSVarKindEnum var_kind)+{+    return get_closure_var2(ctx, s, fd, TRUE, is_arg,+                            var_idx, var_name, is_const, is_lexical,+                            var_kind);+}++static int get_with_scope_opcode(int op)+{+    if (op == OP_scope_get_var_undef)+        return OP_with_get_var;+    else+        return OP_with_get_var + (op - OP_scope_get_var);+}++static BOOL can_opt_put_ref_value(const uint8_t *bc_buf, int pos)+{+    int opcode = bc_buf[pos];+    return (bc_buf[pos + 1] == OP_put_ref_value &&+            (opcode == OP_insert3 ||+             opcode == OP_perm4 ||+             opcode == OP_nop ||+             opcode == OP_rot3l));+}++static BOOL can_opt_put_global_ref_value(const uint8_t *bc_buf, int pos)+{+    int opcode = bc_buf[pos];+    return (bc_buf[pos + 1] == OP_put_ref_value &&+            (opcode == OP_insert3 ||+             opcode == OP_perm4 ||+             opcode == OP_nop ||+             opcode == OP_rot3l));+}++static int optimize_scope_make_ref(JSContext *ctx, JSFunctionDef *s,+                                   DynBuf *bc, uint8_t *bc_buf,+                                   LabelSlot *ls, int pos_next,+                                   int get_op, int var_idx)+{+    int label_pos, end_pos, pos;++    /* XXX: should optimize `loc(a) += expr` as `expr add_loc(a)`+       but only if expr does not modify `a`.+       should scan the code between pos_next and label_pos+       for operations that can potentially change `a`:+       OP_scope_make_ref(a), function calls, jumps and gosub.+     */+    /* replace the reference get/put with normal variable+       accesses */+    if (bc_buf[pos_next] == OP_get_ref_value) {+        dbuf_putc(bc, get_op);+        dbuf_put_u16(bc, var_idx);+        pos_next++;+    }+    /* remove the OP_label to make room for replacement */+    /* label should have a refcount of 0 anyway */+    /* XXX: should avoid this patch by inserting nops in phase 1 */+    label_pos = ls->pos;+    pos = label_pos - 5;+    assert(bc_buf[pos] == OP_label);+    /* label points to an instruction pair:+       - insert3 / put_ref_value+       - perm4 / put_ref_value+       - rot3l / put_ref_value+       - nop / put_ref_value+     */+    end_pos = label_pos + 2;+    if (bc_buf[label_pos] == OP_insert3)+        bc_buf[pos++] = OP_dup;+    bc_buf[pos] = get_op + 1;+    put_u16(bc_buf + pos + 1, var_idx);+    pos += 3;+    /* pad with OP_nop */+    while (pos < end_pos)+        bc_buf[pos++] = OP_nop;+    return pos_next;+}++static int optimize_scope_make_global_ref(JSContext *ctx, JSFunctionDef *s,+                                          DynBuf *bc, uint8_t *bc_buf,+                                          LabelSlot *ls, int pos_next,+                                          JSAtom var_name)+{+    int label_pos, end_pos, pos, op;+    BOOL is_strict;+    is_strict = ((s->js_mode & JS_MODE_STRICT) != 0);++    /* replace the reference get/put with normal variable+       accesses */+    if (is_strict) {+        /* need to check if the variable exists before evaluating the right+           expression */+        /* XXX: need an extra OP_true if destructuring an array */+        dbuf_putc(bc, OP_check_var);+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+    } else {+        /* XXX: need 2 extra OP_true if destructuring an array */+    }+    if (bc_buf[pos_next] == OP_get_ref_value) {+        dbuf_putc(bc, OP_get_var);+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        pos_next++;+    }+    /* remove the OP_label to make room for replacement */+    /* label should have a refcount of 0 anyway */+    /* XXX: should have emitted several OP_nop to avoid this kludge */+    label_pos = ls->pos;+    pos = label_pos - 5;+    assert(bc_buf[pos] == OP_label);+    end_pos = label_pos + 2;+    op = bc_buf[label_pos];+    if (is_strict) {+        if (op != OP_nop) {+            switch(op) {+            case OP_insert3:+                op = OP_insert2;+                break;+            case OP_perm4:+                op = OP_perm3;+                break;+            case OP_rot3l:+                op = OP_swap;+                break;+            default:+                abort();+            }+            bc_buf[pos++] = op;+        }+    } else {+        if (op == OP_insert3)+            bc_buf[pos++] = OP_dup;+    }+    if (is_strict) {+        bc_buf[pos] = OP_put_var_strict;+        /* XXX: need 1 extra OP_drop if destructuring an array */+    } else {+        bc_buf[pos] = OP_put_var;+        /* XXX: need 2 extra OP_drop if destructuring an array */+    }+    put_u32(bc_buf + pos + 1, JS_DupAtom(ctx, var_name));+    pos += 5;+    /* pad with OP_nop */+    while (pos < end_pos)+        bc_buf[pos++] = OP_nop;+    return pos_next;+}++static int add_var_this(JSContext *ctx, JSFunctionDef *fd)+{+    int idx;+    idx = add_var(ctx, fd, JS_ATOM_this);+    if (idx >= 0 && fd->is_derived_class_constructor) {+        JSVarDef *vd = &fd->vars[idx];+        /* XXX: should have is_this flag or var type */+        vd->is_lexical = 1; /* used to trigger 'uninitialized' checks+                               in a derived class constructor */+    }+    return idx;+}++static int resolve_pseudo_var(JSContext *ctx, JSFunctionDef *s,+                               JSAtom var_name)+{+    int var_idx;++    if (!s->has_this_binding)+        return -1;+    switch(var_name) {+    case JS_ATOM_home_object:+        /* 'home_object' pseudo variable */+        if (s->home_object_var_idx < 0)+            s->home_object_var_idx = add_var(ctx, s, var_name);+        var_idx = s->home_object_var_idx;+        break;+    case JS_ATOM_this_active_func:+        /* 'this.active_func' pseudo variable */+        if (s->this_active_func_var_idx < 0)+            s->this_active_func_var_idx = add_var(ctx, s, var_name);+        var_idx = s->this_active_func_var_idx;+        break;+    case JS_ATOM_new_target:+        /* 'new.target' pseudo variable */+        if (s->new_target_var_idx < 0)+            s->new_target_var_idx = add_var(ctx, s, var_name);+        var_idx = s->new_target_var_idx;+        break;+    case JS_ATOM_this:+        /* 'this' pseudo variable */+        if (s->this_var_idx < 0)+            s->this_var_idx = add_var_this(ctx, s);+        var_idx = s->this_var_idx;+        break;+    default:+        var_idx = -1;+        break;+    }+    return var_idx;+}++/* test if 'var_name' is in the variable object on the stack. If is it+   the case, handle it and jump to 'label_done' */+static void var_object_test(JSContext *ctx, JSFunctionDef *s,+                            JSAtom var_name, int op, DynBuf *bc,+                            int *plabel_done, BOOL is_with)+{+    dbuf_putc(bc, get_with_scope_opcode(op));+    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+    *plabel_done = new_label_fd(s, *plabel_done);+    dbuf_put_u32(bc, *plabel_done);+    dbuf_putc(bc, is_with);+    update_label(s, *plabel_done, 1);+    s->jump_size++;+}+    +/* return the position of the next opcode */+static int resolve_scope_var(JSContext *ctx, JSFunctionDef *s,+                             JSAtom var_name, int scope_level, int op,+                             DynBuf *bc, uint8_t *bc_buf,+                             LabelSlot *ls, int pos_next)+{+    int idx, var_idx, is_put;+    int label_done;+    JSFunctionDef *fd;+    JSVarDef *vd;+    BOOL is_pseudo_var, is_arg_scope;++    label_done = -1;++    /* XXX: could be simpler to use a specific function to+       resolve the pseudo variables */+    is_pseudo_var = (var_name == JS_ATOM_home_object ||+                     var_name == JS_ATOM_this_active_func ||+                     var_name == JS_ATOM_new_target ||+                     var_name == JS_ATOM_this);++    /* resolve local scoped variables */+    var_idx = -1;+    for (idx = s->scopes[scope_level].first; idx >= 0;) {+        vd = &s->vars[idx];+        if (vd->var_name == var_name) {+            if (op == OP_scope_put_var || op == OP_scope_make_ref) {+                if (vd->is_const) {+                    dbuf_putc(bc, OP_throw_error);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                    dbuf_putc(bc, JS_THROW_VAR_RO);+                    goto done;+                }+            }+            var_idx = idx;+            break;+        } else+        if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {+            dbuf_putc(bc, OP_get_loc);+            dbuf_put_u16(bc, idx);+            var_object_test(ctx, s, var_name, op, bc, &label_done, 1);+        }+        idx = vd->scope_next;+    }+    is_arg_scope = (idx == ARG_SCOPE_END);+    if (var_idx < 0) {+        /* argument scope: variables are not visible but pseudo+           variables are visible */+        if (!is_arg_scope) {+            var_idx = find_var(ctx, s, var_name);+        }++        if (var_idx < 0 && is_pseudo_var)+            var_idx = resolve_pseudo_var(ctx, s, var_name);++        if (var_idx < 0 && var_name == JS_ATOM_arguments &&+            s->has_arguments_binding) {+            /* 'arguments' pseudo variable */+            var_idx = add_arguments_var(ctx, s);+        }+        if (var_idx < 0 && s->is_func_expr && var_name == s->func_name) {+            /* add a new variable with the function name */+            var_idx = add_func_var(ctx, s, var_name);+        }+    }+    if (var_idx >= 0) {+        if ((op == OP_scope_put_var || op == OP_scope_make_ref) &&+            !(var_idx & ARGUMENT_VAR_OFFSET) &&+            s->vars[var_idx].is_const) {+            /* only happens when assigning a function expression name+               in strict mode */+            dbuf_putc(bc, OP_throw_error);+            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+            dbuf_putc(bc, JS_THROW_VAR_RO);+            goto done;+        }+        /* OP_scope_put_var_init is only used to initialize a+           lexical variable, so it is never used in a with or var object. It+           can be used with a closure (module global variable case). */+        switch (op) {+        case OP_scope_make_ref:+            if (!(var_idx & ARGUMENT_VAR_OFFSET) &&+                s->vars[var_idx].var_kind == JS_VAR_FUNCTION_NAME) {+                /* Create a dummy object reference for the func_var */+                dbuf_putc(bc, OP_object);+                dbuf_putc(bc, OP_get_loc);+                dbuf_put_u16(bc, var_idx);+                dbuf_putc(bc, OP_define_field);+                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                dbuf_putc(bc, OP_push_atom_value);+                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+            } else+            if (label_done == -1 && can_opt_put_ref_value(bc_buf, ls->pos)) {+                int get_op;+                if (var_idx & ARGUMENT_VAR_OFFSET) {+                    get_op = OP_get_arg;+                    var_idx -= ARGUMENT_VAR_OFFSET;+                } else {+                    if (s->vars[var_idx].is_lexical)+                        get_op = OP_get_loc_check;+                    else+                        get_op = OP_get_loc;+                }+                pos_next = optimize_scope_make_ref(ctx, s, bc, bc_buf, ls,+                                                   pos_next, get_op, var_idx);+            } else {+                /* Create a dummy object with a named slot that is+                   a reference to the local variable */+                if (var_idx & ARGUMENT_VAR_OFFSET) {+                    dbuf_putc(bc, OP_make_arg_ref);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                    dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);+                } else {+                    dbuf_putc(bc, OP_make_loc_ref);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                    dbuf_put_u16(bc, var_idx);+                }+            }+            break;+        case OP_scope_get_ref:+            dbuf_putc(bc, OP_undefined);+            /* fall thru */+        case OP_scope_get_var_undef:+        case OP_scope_get_var:+        case OP_scope_put_var:+        case OP_scope_put_var_init:+            is_put = (op == OP_scope_put_var || op == OP_scope_put_var_init);+            if (var_idx & ARGUMENT_VAR_OFFSET) {+                dbuf_putc(bc, OP_get_arg + is_put);+                dbuf_put_u16(bc, var_idx - ARGUMENT_VAR_OFFSET);+            } else {+                if (is_put) {+                    if (s->vars[var_idx].is_lexical) {+                        if (op == OP_scope_put_var_init) {+                            /* 'this' can only be initialized once */+                            if (var_name == JS_ATOM_this)+                                dbuf_putc(bc, OP_put_loc_check_init);+                            else+                                dbuf_putc(bc, OP_put_loc);+                        } else {+                            dbuf_putc(bc, OP_put_loc_check);+                        }+                    } else {+                        dbuf_putc(bc, OP_put_loc);+                    }+                } else {+                    if (s->vars[var_idx].is_lexical) {+                        dbuf_putc(bc, OP_get_loc_check);+                    } else {+                        dbuf_putc(bc, OP_get_loc);+                    }+                }+                dbuf_put_u16(bc, var_idx);+            }+            break;+        case OP_scope_delete_var:+            dbuf_putc(bc, OP_push_false);+            break;+        }+        goto done;+    }+    /* check eval object */+    if (!is_arg_scope && s->var_object_idx >= 0 && !is_pseudo_var) {+        dbuf_putc(bc, OP_get_loc);+        dbuf_put_u16(bc, s->var_object_idx);+        var_object_test(ctx, s, var_name, op, bc, &label_done, 0);+    }+    /* check eval object in argument scope */+    if (s->arg_var_object_idx >= 0 && !is_pseudo_var) {+        dbuf_putc(bc, OP_get_loc);+        dbuf_put_u16(bc, s->arg_var_object_idx);+        var_object_test(ctx, s, var_name, op, bc, &label_done, 0);+    }++    /* check parent scopes */+    for (fd = s; fd->parent;) {+        scope_level = fd->parent_scope_level;+        fd = fd->parent;+        for (idx = fd->scopes[scope_level].first; idx >= 0;) {+            vd = &fd->vars[idx];+            if (vd->var_name == var_name) {+                if (op == OP_scope_put_var || op == OP_scope_make_ref) {+                    if (vd->is_const) {+                        dbuf_putc(bc, OP_throw_error);+                        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                        dbuf_putc(bc, JS_THROW_VAR_RO);+                        goto done;+                    }+                }+                var_idx = idx;+                break;+            } else if (vd->var_name == JS_ATOM__with_ && !is_pseudo_var) {+                vd->is_captured = 1;+                idx = get_closure_var(ctx, s, fd, FALSE, idx, vd->var_name, FALSE, FALSE, JS_VAR_NORMAL);+                if (idx >= 0) {+                    dbuf_putc(bc, OP_get_var_ref);+                    dbuf_put_u16(bc, idx);+                    var_object_test(ctx, s, var_name, op, bc, &label_done, 1);+                }+            }+            idx = vd->scope_next;+        }+        is_arg_scope = (idx == ARG_SCOPE_END);+        if (var_idx >= 0)+            break;+        +        if (!is_arg_scope) {+            var_idx = find_var(ctx, fd, var_name);+            if (var_idx >= 0)+                break;+        }+        if (is_pseudo_var) {+            var_idx = resolve_pseudo_var(ctx, fd, var_name);+            if (var_idx >= 0)+                break;+        }+        if (var_name == JS_ATOM_arguments && fd->has_arguments_binding) {+            var_idx = add_arguments_var(ctx, fd);+            break;+        }+        if (fd->is_func_expr && fd->func_name == var_name) {+            /* add a new variable with the function name */+            var_idx = add_func_var(ctx, fd, var_name);+            break;+        }++        /* check eval object */+        if (!is_arg_scope && fd->var_object_idx >= 0 && !is_pseudo_var) {+            vd = &fd->vars[fd->var_object_idx];+            vd->is_captured = 1;+            idx = get_closure_var(ctx, s, fd, FALSE,+                                  fd->var_object_idx, vd->var_name,+                                  FALSE, FALSE, JS_VAR_NORMAL);+            dbuf_putc(bc, OP_get_var_ref);+            dbuf_put_u16(bc, idx);+            var_object_test(ctx, s, var_name, op, bc, &label_done, 0);+        }++        /* check eval object in argument scope */+        if (fd->arg_var_object_idx >= 0 && !is_pseudo_var) {+            vd = &fd->vars[fd->arg_var_object_idx];+            vd->is_captured = 1;+            idx = get_closure_var(ctx, s, fd, FALSE,+                                  fd->arg_var_object_idx, vd->var_name,+                                  FALSE, FALSE, JS_VAR_NORMAL);+            dbuf_putc(bc, OP_get_var_ref);+            dbuf_put_u16(bc, idx);+            var_object_test(ctx, s, var_name, op, bc, &label_done, 0);+        }+        +        if (fd->is_eval)+            break; /* it it necessarily the top level function */+    }++    /* check direct eval scope (in the closure of the eval function+       which is necessarily at the top level) */+    if (!fd)+        fd = s;+    if (var_idx < 0 && fd->is_eval) {+        int idx1;+        for (idx1 = 0; idx1 < fd->closure_var_count; idx1++) {+            JSClosureVar *cv = &fd->closure_var[idx1];+            if (var_name == cv->var_name) {+                if (fd != s) {+                    idx = get_closure_var2(ctx, s, fd,+                                           FALSE,+                                           cv->is_arg, idx1,+                                           cv->var_name, cv->is_const,+                                           cv->is_lexical, cv->var_kind);+                } else {+                    idx = idx1;+                }+                goto has_idx;+            } else if ((cv->var_name == JS_ATOM__var_ ||+                        cv->var_name == JS_ATOM__arg_var_ ||+                        cv->var_name == JS_ATOM__with_) && !is_pseudo_var) {+                int is_with = (cv->var_name == JS_ATOM__with_);+                if (fd != s) {+                    idx = get_closure_var2(ctx, s, fd,+                                           FALSE,+                                           cv->is_arg, idx1,+                                           cv->var_name, FALSE, FALSE,+                                           JS_VAR_NORMAL);+                } else {+                    idx = idx1;+                }+                dbuf_putc(bc, OP_get_var_ref);+                dbuf_put_u16(bc, idx);+                var_object_test(ctx, s, var_name, op, bc, &label_done, is_with);+            }+        }+    }++    if (var_idx >= 0) {+        /* find the corresponding closure variable */+        if (var_idx & ARGUMENT_VAR_OFFSET) {+            fd->args[var_idx - ARGUMENT_VAR_OFFSET].is_captured = 1;+            idx = get_closure_var(ctx, s, fd,+                                  TRUE, var_idx - ARGUMENT_VAR_OFFSET,+                                  var_name, FALSE, FALSE, JS_VAR_NORMAL);+        } else {+            fd->vars[var_idx].is_captured = 1;+            idx = get_closure_var(ctx, s, fd,+                                  FALSE, var_idx,+                                  var_name,+                                  fd->vars[var_idx].is_const,+                                  fd->vars[var_idx].is_lexical,+                                  fd->vars[var_idx].var_kind);+        }+        if (idx >= 0) {+        has_idx:+            if ((op == OP_scope_put_var || op == OP_scope_make_ref) &&+                s->closure_var[idx].is_const) {+                dbuf_putc(bc, OP_throw_error);+                dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                dbuf_putc(bc, JS_THROW_VAR_RO);+                goto done;+            }+            switch (op) {+            case OP_scope_make_ref:+                if (s->closure_var[idx].var_kind == JS_VAR_FUNCTION_NAME) {+                    /* Create a dummy object reference for the func_var */+                    dbuf_putc(bc, OP_object);+                    dbuf_putc(bc, OP_get_var_ref);+                    dbuf_put_u16(bc, idx);+                    dbuf_putc(bc, OP_define_field);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                    dbuf_putc(bc, OP_push_atom_value);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                } else+                if (label_done == -1 &&+                    can_opt_put_ref_value(bc_buf, ls->pos)) {+                    int get_op;+                    if (s->closure_var[idx].is_lexical)+                        get_op = OP_get_var_ref_check;+                    else+                        get_op = OP_get_var_ref;+                    pos_next = optimize_scope_make_ref(ctx, s, bc, bc_buf, ls,+                                                       pos_next,+                                                       get_op, idx);+                } else {+                    /* Create a dummy object with a named slot that is+                       a reference to the closure variable */+                    dbuf_putc(bc, OP_make_var_ref_ref);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+                    dbuf_put_u16(bc, idx);+                }+                break;+            case OP_scope_get_ref:+                /* XXX: should create a dummy object with a named slot that is+                   a reference to the closure variable */+                dbuf_putc(bc, OP_undefined);+                /* fall thru */+            case OP_scope_get_var_undef:+            case OP_scope_get_var:+            case OP_scope_put_var:+            case OP_scope_put_var_init:+                is_put = (op == OP_scope_put_var ||+                          op == OP_scope_put_var_init);+                if (is_put) {+                    if (s->closure_var[idx].is_lexical) {+                        if (op == OP_scope_put_var_init) {+                            /* 'this' can only be initialized once */+                            if (var_name == JS_ATOM_this)+                                dbuf_putc(bc, OP_put_var_ref_check_init);+                            else+                                dbuf_putc(bc, OP_put_var_ref);+                        } else {+                            dbuf_putc(bc, OP_put_var_ref_check);+                        }+                    } else {+                        dbuf_putc(bc, OP_put_var_ref);+                    }+                } else {+                    if (s->closure_var[idx].is_lexical) {+                        dbuf_putc(bc, OP_get_var_ref_check);+                    } else {+                        dbuf_putc(bc, OP_get_var_ref);+                    }+                }+                dbuf_put_u16(bc, idx);+                break;+            case OP_scope_delete_var:+                dbuf_putc(bc, OP_push_false);+                break;+            }+            goto done;+        }+    }++    /* global variable access */++    switch (op) {+    case OP_scope_make_ref:+        if (label_done == -1 && can_opt_put_global_ref_value(bc_buf, ls->pos)) {+            pos_next = optimize_scope_make_global_ref(ctx, s, bc, bc_buf, ls,+                                                      pos_next, var_name);+        } else {+            dbuf_putc(bc, OP_make_var_ref);+            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        }+        break;+    case OP_scope_get_ref:+        /* XXX: should create a dummy object with a named slot that is+           a reference to the global variable */+        dbuf_putc(bc, OP_undefined);+        dbuf_putc(bc, OP_get_var);+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        break;+    case OP_scope_get_var_undef:+    case OP_scope_get_var:+    case OP_scope_put_var:+        dbuf_putc(bc, OP_get_var_undef + (op - OP_scope_get_var_undef));+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        break;+    case OP_scope_put_var_init:+        dbuf_putc(bc, OP_put_var_init);+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        break;+    case OP_scope_delete_var:+        dbuf_putc(bc, OP_delete_var);+        dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+        break;+    }+done:+    if (label_done >= 0) {+        dbuf_putc(bc, OP_label);+        dbuf_put_u32(bc, label_done);+        s->label_slots[label_done].pos2 = bc->size;+    }+    return pos_next;+}++/* search in all scopes */+static int find_private_class_field_all(JSContext *ctx, JSFunctionDef *fd,+                                        JSAtom name, int scope_level)+{+    int idx;++    idx = fd->scopes[scope_level].first;+    while (idx >= 0) {+        if (fd->vars[idx].var_name == name)+            return idx;+        idx = fd->vars[idx].scope_next;+    }+    return -1;+}++static void get_loc_or_ref(DynBuf *bc, BOOL is_ref, int idx)+{+    /* if the field is not initialized, the error is catched when+       accessing it */+    if (is_ref) +        dbuf_putc(bc, OP_get_var_ref);+    else+        dbuf_putc(bc, OP_get_loc);+    dbuf_put_u16(bc, idx);+}++static int resolve_scope_private_field1(JSContext *ctx,+                                        BOOL *pis_ref, int *pvar_kind,+                                        JSFunctionDef *s,+                                        JSAtom var_name, int scope_level)+{+    int idx, var_kind;+    JSFunctionDef *fd;+    BOOL is_ref;+    +    fd = s;+    is_ref = FALSE;+    for(;;) {+        idx = find_private_class_field_all(ctx, fd, var_name, scope_level);+        if (idx >= 0) {+            var_kind = fd->vars[idx].var_kind;+            if (is_ref) {+                idx = get_closure_var(ctx, s, fd, FALSE, idx, var_name,+                                      TRUE, TRUE, JS_VAR_NORMAL);+                if (idx < 0)+                    return -1;+            }+            break;+        }+        scope_level = fd->parent_scope_level;+        if (!fd->parent) {+            if (fd->is_eval) {+                /* closure of the eval function (top level) */+                for (idx = 0; idx < fd->closure_var_count; idx++) {+                    JSClosureVar *cv = &fd->closure_var[idx];+                    if (cv->var_name == var_name) {+                        var_kind = cv->var_kind;+                        is_ref = TRUE;+                        if (fd != s) {+                            idx = get_closure_var2(ctx, s, fd,+                                                   FALSE,+                                                   cv->is_arg, idx,+                                                   cv->var_name, cv->is_const,+                                                   cv->is_lexical,+                                                   cv->var_kind);+                            if (idx < 0)+                                return -1;+                        }+                        goto done;+                    }+                }+            }+            /* XXX: no line number info */+            JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'",+                                    var_name);+            return -1;+        } else {+            fd = fd->parent;+        }+        is_ref = TRUE;+    }+ done:+    *pis_ref = is_ref;+    *pvar_kind = var_kind;+    return idx;+}++/* return 0 if OK or -1 if the private field could not be resolved */+static int resolve_scope_private_field(JSContext *ctx, JSFunctionDef *s,+                                       JSAtom var_name, int scope_level, int op,+                                       DynBuf *bc)+{+    int idx, var_kind;+    BOOL is_ref;++    idx = resolve_scope_private_field1(ctx, &is_ref, &var_kind, s,+                                       var_name, scope_level);+    if (idx < 0)+        return -1;+    assert(var_kind != JS_VAR_NORMAL);+    switch (op) {+    case OP_scope_get_private_field:+    case OP_scope_get_private_field2:+        switch(var_kind) {+        case JS_VAR_PRIVATE_FIELD:+            if (op == OP_scope_get_private_field2)+                dbuf_putc(bc, OP_dup);+            get_loc_or_ref(bc, is_ref, idx);+            dbuf_putc(bc, OP_get_private_field);+            break;+        case JS_VAR_PRIVATE_METHOD:+            get_loc_or_ref(bc, is_ref, idx);+            dbuf_putc(bc, OP_check_brand);+            if (op != OP_scope_get_private_field2)+                dbuf_putc(bc, OP_nip);+            break;+        case JS_VAR_PRIVATE_GETTER:+        case JS_VAR_PRIVATE_GETTER_SETTER:+            if (op == OP_scope_get_private_field2)+                dbuf_putc(bc, OP_dup);+            get_loc_or_ref(bc, is_ref, idx);+            dbuf_putc(bc, OP_check_brand);+            dbuf_putc(bc, OP_call_method);+            dbuf_put_u16(bc, 0);+            break;+        case JS_VAR_PRIVATE_SETTER:+            /* XXX: add clearer error message */+            dbuf_putc(bc, OP_throw_error);+            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+            dbuf_putc(bc, JS_THROW_VAR_RO);+            break;+        default:+            abort();+        }+        break;+    case OP_scope_put_private_field:+        switch(var_kind) {+        case JS_VAR_PRIVATE_FIELD:+            get_loc_or_ref(bc, is_ref, idx);+            dbuf_putc(bc, OP_put_private_field);+            break;+        case JS_VAR_PRIVATE_METHOD:+        case JS_VAR_PRIVATE_GETTER:+            /* XXX: add clearer error message */+            dbuf_putc(bc, OP_throw_error);+            dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));+            dbuf_putc(bc, JS_THROW_VAR_RO);+            break;+        case JS_VAR_PRIVATE_SETTER:+        case JS_VAR_PRIVATE_GETTER_SETTER:+            {+                JSAtom setter_name = get_private_setter_name(ctx, var_name);+                if (setter_name == JS_ATOM_NULL)+                    return -1;+                idx = resolve_scope_private_field1(ctx, &is_ref,+                                                   &var_kind, s,+                                                   setter_name, scope_level);+                JS_FreeAtom(ctx, setter_name);+                if (idx < 0)+                    return -1;+                assert(var_kind == JS_VAR_PRIVATE_SETTER);+                get_loc_or_ref(bc, is_ref, idx);+                dbuf_putc(bc, OP_swap);+                /* obj func value */+                dbuf_putc(bc, OP_rot3r);+                /* value obj func */+                dbuf_putc(bc, OP_check_brand);+                dbuf_putc(bc, OP_rot3l);+                /* obj func value */+                dbuf_putc(bc, OP_call_method);+                dbuf_put_u16(bc, 1);+            }+            break;+        default:+            abort();+        }+        break;+    default:+        abort();+    }+    return 0;+}++static void mark_eval_captured_variables(JSContext *ctx, JSFunctionDef *s,+                                         int scope_level)+{+    int idx;+    JSVarDef *vd;++    for (idx = s->scopes[scope_level].first; idx >= 0;) {+        vd = &s->vars[idx];+        vd->is_captured = 1;+        idx = vd->scope_next;+    }+}++/* XXX: should handle the argument scope generically */+static BOOL is_var_in_arg_scope(const JSVarDef *vd)+{+    return (vd->var_name == JS_ATOM_home_object ||+            vd->var_name == JS_ATOM_this_active_func ||+            vd->var_name == JS_ATOM_new_target ||+            vd->var_name == JS_ATOM_this ||+            vd->var_name == JS_ATOM__arg_var_ ||+            vd->var_kind == JS_VAR_FUNCTION_NAME);+}++static void add_eval_variables(JSContext *ctx, JSFunctionDef *s)+{+    JSFunctionDef *fd;+    JSVarDef *vd;+    int i, scope_level, scope_idx;+    BOOL has_arguments_binding, has_this_binding, is_arg_scope;++    /* in non strict mode, variables are created in the caller's+       environment object */+    if (!s->is_eval && !(s->js_mode & JS_MODE_STRICT)) {+        s->var_object_idx = add_var(ctx, s, JS_ATOM__var_);+        if (s->has_parameter_expressions) {+            /* an additional variable object is needed for the+               argument scope */+            s->arg_var_object_idx = add_var(ctx, s, JS_ATOM__arg_var_);+        }+    }++    /* eval can potentially use 'arguments' so we must define it */+    has_this_binding = s->has_this_binding;+    if (has_this_binding) {+        if (s->this_var_idx < 0)+            s->this_var_idx = add_var_this(ctx, s);+        if (s->new_target_var_idx < 0)+            s->new_target_var_idx = add_var(ctx, s, JS_ATOM_new_target);+        if (s->is_derived_class_constructor && s->this_active_func_var_idx < 0)+            s->this_active_func_var_idx = add_var(ctx, s, JS_ATOM_this_active_func);+        if (s->has_home_object && s->home_object_var_idx < 0)+            s->home_object_var_idx = add_var(ctx, s, JS_ATOM_home_object);+    }+    has_arguments_binding = s->has_arguments_binding;+    if (has_arguments_binding) {+        add_arguments_var(ctx, s);+        /* also add an arguments binding in the argument scope to+           raise an error if a direct eval in the argument scope tries+           to redefine it */+        if (s->has_parameter_expressions && !(s->js_mode & JS_MODE_STRICT))+            add_arguments_arg(ctx, s);+    }+    if (s->is_func_expr && s->func_name != JS_ATOM_NULL)+        add_func_var(ctx, s, s->func_name);++    /* eval can use all the variables of the enclosing functions, so+       they must be all put in the closure. The closure variables are+       ordered by scope. It works only because no closure are created+       before. */+    assert(s->is_eval || s->closure_var_count == 0);++    /* XXX: inefficient, but eval performance is less critical */+    fd = s;+    for(;;) {+        scope_level = fd->parent_scope_level;+        fd = fd->parent;+        if (!fd)+            break;+        /* add 'this' if it was not previously added */+        if (!has_this_binding && fd->has_this_binding) {+            if (fd->this_var_idx < 0)+                fd->this_var_idx = add_var_this(ctx, fd);+            if (fd->new_target_var_idx < 0)+                fd->new_target_var_idx = add_var(ctx, fd, JS_ATOM_new_target);+            if (fd->is_derived_class_constructor && fd->this_active_func_var_idx < 0)+                fd->this_active_func_var_idx = add_var(ctx, fd, JS_ATOM_this_active_func);+            if (fd->has_home_object && fd->home_object_var_idx < 0)+                fd->home_object_var_idx = add_var(ctx, fd, JS_ATOM_home_object);+            has_this_binding = TRUE;+        }+        /* add 'arguments' if it was not previously added */+        if (!has_arguments_binding && fd->has_arguments_binding) {+            add_arguments_var(ctx, fd);+            has_arguments_binding = TRUE;+        }+        /* add function name */+        if (fd->is_func_expr && fd->func_name != JS_ATOM_NULL)+            add_func_var(ctx, fd, fd->func_name);++        /* add lexical variables */+        scope_idx = fd->scopes[scope_level].first;+        while (scope_idx >= 0) {+            vd = &fd->vars[scope_idx];+            vd->is_captured = 1;+            get_closure_var(ctx, s, fd, FALSE, scope_idx,+                            vd->var_name, vd->is_const, vd->is_lexical, vd->var_kind);+            scope_idx = vd->scope_next;+        }+        is_arg_scope = (scope_idx == ARG_SCOPE_END);+        if (!is_arg_scope) {+            /* add unscoped variables */+            for(i = 0; i < fd->arg_count; i++) {+                vd = &fd->args[i];+                if (vd->var_name != JS_ATOM_NULL) {+                    get_closure_var(ctx, s, fd,+                                    TRUE, i, vd->var_name, FALSE, FALSE,+                                    JS_VAR_NORMAL);+                }+            }+            for(i = 0; i < fd->var_count; i++) {+                vd = &fd->vars[i];+                /* do not close top level last result */+                if (vd->scope_level == 0 &&+                    vd->var_name != JS_ATOM__ret_ &&+                    vd->var_name != JS_ATOM_NULL) {+                    get_closure_var(ctx, s, fd,+                                    FALSE, i, vd->var_name, FALSE, FALSE,+                                    JS_VAR_NORMAL);+                }+            }+        } else {+            for(i = 0; i < fd->var_count; i++) {+                vd = &fd->vars[i];+                /* do not close top level last result */+                if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {+                    get_closure_var(ctx, s, fd,+                                    FALSE, i, vd->var_name, FALSE, FALSE,+                                    JS_VAR_NORMAL);+                }+            }+        }+        if (fd->is_eval) {+            int idx;+            /* add direct eval variables (we are necessarily at the+               top level) */+            for (idx = 0; idx < fd->closure_var_count; idx++) {+                JSClosureVar *cv = &fd->closure_var[idx];+                get_closure_var2(ctx, s, fd,+                                 FALSE, cv->is_arg,+                                 idx, cv->var_name, cv->is_const,+                                 cv->is_lexical, cv->var_kind);+            }+        }+    }+}++static void set_closure_from_var(JSContext *ctx, JSClosureVar *cv,+                                 JSVarDef *vd, int var_idx)+{+    cv->is_local = TRUE;+    cv->is_arg = FALSE;+    cv->is_const = vd->is_const;+    cv->is_lexical = vd->is_lexical;+    cv->var_kind = vd->var_kind;+    cv->var_idx = var_idx;+    cv->var_name = JS_DupAtom(ctx, vd->var_name);+}++/* for direct eval compilation: add references to the variables of the+   calling function */+static __exception int add_closure_variables(JSContext *ctx, JSFunctionDef *s,+                                             JSFunctionBytecode *b, int scope_idx)+{+    int i, count;+    JSVarDef *vd;+    BOOL is_arg_scope;+    +    count = b->arg_count + b->var_count + b->closure_var_count;+    s->closure_var = NULL;+    s->closure_var_count = 0;+    s->closure_var_size = count;+    if (count == 0)+        return 0;+    s->closure_var = js_malloc(ctx, sizeof(s->closure_var[0]) * count);+    if (!s->closure_var)+        return -1;+    /* Add lexical variables in scope at the point of evaluation */+    for (i = scope_idx; i >= 0;) {+        vd = &b->vardefs[b->arg_count + i];+        if (vd->scope_level > 0) {+            JSClosureVar *cv = &s->closure_var[s->closure_var_count++];+            set_closure_from_var(ctx, cv, vd, i);+        }+        i = vd->scope_next;+    }+    is_arg_scope = (i == ARG_SCOPE_END);+    if (!is_arg_scope) {+        /* Add argument variables */+        for(i = 0; i < b->arg_count; i++) {+            JSClosureVar *cv = &s->closure_var[s->closure_var_count++];+            vd = &b->vardefs[i];+            cv->is_local = TRUE;+            cv->is_arg = TRUE;+            cv->is_const = FALSE;+            cv->is_lexical = FALSE;+            cv->var_kind = JS_VAR_NORMAL;+            cv->var_idx = i;+            cv->var_name = JS_DupAtom(ctx, vd->var_name);+        }+        /* Add local non lexical variables */+        for(i = 0; i < b->var_count; i++) {+            vd = &b->vardefs[b->arg_count + i];+            if (vd->scope_level == 0 && vd->var_name != JS_ATOM__ret_) {+                JSClosureVar *cv = &s->closure_var[s->closure_var_count++];+                set_closure_from_var(ctx, cv, vd, i);+            }+        }+    } else {+        /* only add pseudo variables */+        for(i = 0; i < b->var_count; i++) {+            vd = &b->vardefs[b->arg_count + i];+            if (vd->scope_level == 0 && is_var_in_arg_scope(vd)) {+                JSClosureVar *cv = &s->closure_var[s->closure_var_count++];+                set_closure_from_var(ctx, cv, vd, i);+            }+        }+    }+    for(i = 0; i < b->closure_var_count; i++) {+        JSClosureVar *cv0 = &b->closure_var[i];+        JSClosureVar *cv = &s->closure_var[s->closure_var_count++];+        cv->is_local = FALSE;+        cv->is_arg = cv0->is_arg;+        cv->is_const = cv0->is_const;+        cv->is_lexical = cv0->is_lexical;+        cv->var_kind = cv0->var_kind;+        cv->var_idx = i;+        cv->var_name = JS_DupAtom(ctx, cv0->var_name);+    }+    return 0;+}++typedef struct CodeContext {+    const uint8_t *bc_buf; /* code buffer */+    int bc_len;   /* length of the code buffer */+    int pos;      /* position past the matched code pattern */+    int line_num; /* last visited OP_line_num parameter or -1 */+    int op;+    int idx;+    int label;+    int val;+    JSAtom atom;+} CodeContext;++#define M2(op1, op2)            ((op1) | ((op2) << 8))+#define M3(op1, op2, op3)       ((op1) | ((op2) << 8) | ((op3) << 16))+#define M4(op1, op2, op3, op4)  ((op1) | ((op2) << 8) | ((op3) << 16) | ((op4) << 24))++static BOOL code_match(CodeContext *s, int pos, ...)+{+    const uint8_t *tab = s->bc_buf;+    int op, len, op1, line_num, pos_next;+    va_list ap;+    BOOL ret = FALSE;++    line_num = -1;+    va_start(ap, pos);++    for(;;) {+        op1 = va_arg(ap, int);+        if (op1 == -1) {+            s->pos = pos;+            s->line_num = line_num;+            ret = TRUE;+            break;+        }+        for (;;) {+            if (pos >= s->bc_len)+                goto done;+            op = tab[pos];+            len = opcode_info[op].size;+            pos_next = pos + len;+            if (pos_next > s->bc_len)+                goto done;+            if (op == OP_line_num) {+                line_num = get_u32(tab + pos + 1);+                pos = pos_next;+            } else {+                break;+            }+        }+        if (op != op1) {+            if (op1 == (uint8_t)op1 || !op)+                break;+            if (op != (uint8_t)op1+            &&  op != (uint8_t)(op1 >> 8)+            &&  op != (uint8_t)(op1 >> 16)+            &&  op != (uint8_t)(op1 >> 24)) {+                break;+            }+            s->op = op;+        }++        pos++;+        switch(opcode_info[op].fmt) {+        case OP_FMT_loc8:+        case OP_FMT_u8:+            {+                int idx = tab[pos];+                int arg = va_arg(ap, int);+                if (arg == -1) {+                    s->idx = idx;+                } else {+                    if (arg != idx)+                        goto done;+                }+                break;+            }+        case OP_FMT_u16:+        case OP_FMT_npop:+        case OP_FMT_loc:+        case OP_FMT_arg:+        case OP_FMT_var_ref:+            {+                int idx = get_u16(tab + pos);+                int arg = va_arg(ap, int);+                if (arg == -1) {+                    s->idx = idx;+                } else {+                    if (arg != idx)+                        goto done;+                }+                break;+            }+        case OP_FMT_i32:+        case OP_FMT_u32:+        case OP_FMT_label:+        case OP_FMT_const:+            {+                s->label = get_u32(tab + pos);+                break;+            }+        case OP_FMT_label_u16:+            {+                s->label = get_u32(tab + pos);+                s->val = get_u16(tab + pos + 4);+                break;+            }+        case OP_FMT_atom:+            {+                s->atom = get_u32(tab + pos);+                break;+            }+        case OP_FMT_atom_u8:+            {+                s->atom = get_u32(tab + pos);+                s->val = get_u8(tab + pos + 4);+                break;+            }+        case OP_FMT_atom_u16:+            {+                s->atom = get_u32(tab + pos);+                s->val = get_u16(tab + pos + 4);+                break;+            }+        case OP_FMT_atom_label_u8:+            {+                s->atom = get_u32(tab + pos);+                s->label = get_u32(tab + pos + 4);+                s->val = get_u8(tab + pos + 8);+                break;+            }+        default:+            break;+        }+        pos = pos_next;+    }+ done:+    va_end(ap);+    return ret;+}++static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, DynBuf *bc)+{+    int i, idx, label_next = -1;++    /* add the hoisted functions in arguments and local variables */+    for(i = 0; i < s->arg_count; i++) {+        JSVarDef *vd = &s->args[i];+        if (vd->func_pool_idx >= 0) {+            dbuf_putc(bc, OP_fclosure);+            dbuf_put_u32(bc, vd->func_pool_idx);+            dbuf_putc(bc, OP_put_arg);+            dbuf_put_u16(bc, i);+        }+    }+    for(i = 0; i < s->var_count; i++) {+        JSVarDef *vd = &s->vars[i];+        if (vd->scope_level == 0 && vd->func_pool_idx >= 0) {+            dbuf_putc(bc, OP_fclosure);+            dbuf_put_u32(bc, vd->func_pool_idx);+            dbuf_putc(bc, OP_put_loc);+            dbuf_put_u16(bc, i);+        }+    }++    /* the module global variables must be initialized before+       evaluating the module so that the exported functions are+       visible if there are cyclic module references */+    if (s->module) {+        label_next = new_label_fd(s, -1);+        +        /* if 'this' is true, initialize the global variables and return */+        dbuf_putc(bc, OP_push_this);+        dbuf_putc(bc, OP_if_false);+        dbuf_put_u32(bc, label_next);+        update_label(s, label_next, 1);+        s->jump_size++;+    }+    +    /* add the global variables (only happens if s->is_global_var is+       true) */+    for(i = 0; i < s->global_var_count; i++) {+        JSGlobalVar *hf = &s->global_vars[i];+        int has_closure = 0;+        BOOL force_init = hf->force_init;+        /* we are in an eval, so the closure contains all the+           enclosing variables */+        /* If the outer function has a variable environment,+           create a property for the variable there */+        for(idx = 0; idx < s->closure_var_count; idx++) {+            JSClosureVar *cv = &s->closure_var[idx];+            if (cv->var_name == hf->var_name) {+                has_closure = 2;+                force_init = FALSE;+                break;+            }+            if (cv->var_name == JS_ATOM__var_ ||+                cv->var_name == JS_ATOM__arg_var_) {+                dbuf_putc(bc, OP_get_var_ref);+                dbuf_put_u16(bc, idx);+                has_closure = 1;+                force_init = TRUE;+                break;+            }+        }+        if (!has_closure) {+            int flags;+            +            flags = 0;+            if (s->eval_type != JS_EVAL_TYPE_GLOBAL)+                flags |= JS_PROP_CONFIGURABLE;+            if (hf->cpool_idx >= 0 && !hf->is_lexical) {+                /* global function definitions need a specific handling */+                dbuf_putc(bc, OP_fclosure);+                dbuf_put_u32(bc, hf->cpool_idx);+                +                dbuf_putc(bc, OP_define_func);+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));+                dbuf_putc(bc, flags);+                +                goto done_global_var;+            } else {+                if (hf->is_lexical) {+                    flags |= DEFINE_GLOBAL_LEX_VAR;+                    if (!hf->is_const)+                        flags |= JS_PROP_WRITABLE;+                }+                dbuf_putc(bc, OP_define_var);+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));+                dbuf_putc(bc, flags);+            }+        }+        if (hf->cpool_idx >= 0 || force_init) {+            if (hf->cpool_idx >= 0) {+                dbuf_putc(bc, OP_fclosure);+                dbuf_put_u32(bc, hf->cpool_idx);+                if (hf->var_name == JS_ATOM__default_) {+                    /* set default export function name */+                    dbuf_putc(bc, OP_set_name);+                    dbuf_put_u32(bc, JS_DupAtom(ctx, JS_ATOM_default));+                }+            } else {+                dbuf_putc(bc, OP_undefined);+            }+            if (has_closure == 2) {+                dbuf_putc(bc, OP_put_var_ref);+                dbuf_put_u16(bc, idx);+            } else if (has_closure == 1) {+                dbuf_putc(bc, OP_define_field);+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));+                dbuf_putc(bc, OP_drop);+            } else {+                /* XXX: Check if variable is writable and enumerable */+                dbuf_putc(bc, OP_put_var);+                dbuf_put_u32(bc, JS_DupAtom(ctx, hf->var_name));+            }+        }+    done_global_var:+        JS_FreeAtom(ctx, hf->var_name);+    }++    if (s->module) {+        dbuf_putc(bc, OP_return_undef);+        +        dbuf_putc(bc, OP_label);+        dbuf_put_u32(bc, label_next);+        s->label_slots[label_next].pos2 = bc->size;+    }++    js_free(ctx, s->global_vars);+    s->global_vars = NULL;+    s->global_var_count = 0;+    s->global_var_size = 0;+}++static int skip_dead_code(JSFunctionDef *s, const uint8_t *bc_buf, int bc_len,+                          int pos, int *linep)+{+    int op, len, label;++    for (; pos < bc_len; pos += len) {+        op = bc_buf[pos];+        len = opcode_info[op].size;+        if (op == OP_line_num) {+            *linep = get_u32(bc_buf + pos + 1);+        } else+        if (op == OP_label) {+            label = get_u32(bc_buf + pos + 1);+            if (update_label(s, label, 0) > 0)+                break;+#if 0+            if (s->label_slots[label].first_reloc) {+                printf("line %d: unreferenced label %d:%d has relocations\n",+                       *linep, label, s->label_slots[label].pos2);+            }+#endif+            assert(s->label_slots[label].first_reloc == NULL);+        } else {+            /* XXX: output a warning for unreachable code? */+            JSAtom atom;+            switch(opcode_info[op].fmt) {+            case OP_FMT_label:+            case OP_FMT_label_u16:+                label = get_u32(bc_buf + pos + 1);+                update_label(s, label, -1);+                break;+            case OP_FMT_atom_label_u8:+            case OP_FMT_atom_label_u16:+                label = get_u32(bc_buf + pos + 5);+                update_label(s, label, -1);+                /* fall thru */+            case OP_FMT_atom:+            case OP_FMT_atom_u8:+            case OP_FMT_atom_u16:+                atom = get_u32(bc_buf + pos + 1);+                JS_FreeAtom(s->ctx, atom);+                break;+            default:+                break;+            }+        }+    }+    return pos;+}++static int get_label_pos(JSFunctionDef *s, int label)+{+    int i, pos;+    for (i = 0; i < 20; i++) {+        pos = s->label_slots[label].pos;+        for (;;) {+            switch (s->byte_code.buf[pos]) {+            case OP_line_num:+            case OP_label:+                pos += 5;+                continue;+            case OP_goto:+                label = get_u32(s->byte_code.buf + pos + 1);+                break;+            default:+                return pos;+            }+            break;+        }+    }+    return pos;+}++/* convert global variable accesses to local variables or closure+   variables when necessary */+static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)+{+    int pos, pos_next, bc_len, op, len, i, idx, line_num;+    uint8_t *bc_buf;+    JSAtom var_name;+    DynBuf bc_out;+    CodeContext cc;+    int scope;++    cc.bc_buf = bc_buf = s->byte_code.buf;+    cc.bc_len = bc_len = s->byte_code.size;+    js_dbuf_init(ctx, &bc_out);++    /* first pass for runtime checks (must be done before the+       variables are created) */+    for(i = 0; i < s->global_var_count; i++) {+        JSGlobalVar *hf = &s->global_vars[i];+        int flags;+        +        /* check if global variable (XXX: simplify) */+        for(idx = 0; idx < s->closure_var_count; idx++) {+            JSClosureVar *cv = &s->closure_var[idx];+            if (cv->var_name == hf->var_name) {+                if (s->eval_type == JS_EVAL_TYPE_DIRECT &&+                    cv->is_lexical) {+                    /* Check if a lexical variable is+                       redefined as 'var'. XXX: Could abort+                       compilation here, but for consistency+                       with the other checks, we delay the+                       error generation. */+                    dbuf_putc(&bc_out, OP_throw_error);+                    dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));+                    dbuf_putc(&bc_out, JS_THROW_VAR_REDECL);+                }+                goto next;+            }+            if (cv->var_name == JS_ATOM__var_ ||+                cv->var_name == JS_ATOM__arg_var_)+                goto next;+        }+        +        dbuf_putc(&bc_out, OP_check_define_var);+        dbuf_put_u32(&bc_out, JS_DupAtom(ctx, hf->var_name));+        flags = 0;+        if (hf->is_lexical)+            flags |= DEFINE_GLOBAL_LEX_VAR;+        if (hf->cpool_idx >= 0)+            flags |= DEFINE_GLOBAL_FUNC_VAR;+        dbuf_putc(&bc_out, flags);+    next: ;+    }++    line_num = 0; /* avoid warning */+    for (pos = 0; pos < bc_len; pos = pos_next) {+        op = bc_buf[pos];+        len = opcode_info[op].size;+        pos_next = pos + len;+        switch(op) {+        case OP_line_num:+            line_num = get_u32(bc_buf + pos + 1);+            s->line_number_size++;+            goto no_change;++        case OP_eval: /* convert scope index to adjusted variable index */+            {+                int call_argc = get_u16(bc_buf + pos + 1);+                scope = get_u16(bc_buf + pos + 1 + 2);+                mark_eval_captured_variables(ctx, s, scope);+                dbuf_putc(&bc_out, op);+                dbuf_put_u16(&bc_out, call_argc);+                dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);+            }+            break;+        case OP_apply_eval: /* convert scope index to adjusted variable index */+            scope = get_u16(bc_buf + pos + 1);+            mark_eval_captured_variables(ctx, s, scope);+            dbuf_putc(&bc_out, op);+            dbuf_put_u16(&bc_out, s->scopes[scope].first + 1);+            break;+        case OP_scope_get_var_undef:+        case OP_scope_get_var:+        case OP_scope_put_var:+        case OP_scope_delete_var:+        case OP_scope_get_ref:+        case OP_scope_put_var_init:+            var_name = get_u32(bc_buf + pos + 1);+            scope = get_u16(bc_buf + pos + 5);+            pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,+                                         NULL, NULL, pos_next);+            JS_FreeAtom(ctx, var_name);+            break;+        case OP_scope_make_ref:+            {+                int label;+                LabelSlot *ls;+                var_name = get_u32(bc_buf + pos + 1);+                label = get_u32(bc_buf + pos + 5);+                scope = get_u16(bc_buf + pos + 9);+                ls = &s->label_slots[label];+                ls->ref_count--;  /* always remove label reference */+                pos_next = resolve_scope_var(ctx, s, var_name, scope, op, &bc_out,+                                             bc_buf, ls, pos_next);+                JS_FreeAtom(ctx, var_name);+            }+            break;+        case OP_scope_get_private_field:+        case OP_scope_get_private_field2:+        case OP_scope_put_private_field:+            {+                int ret;+                var_name = get_u32(bc_buf + pos + 1);+                scope = get_u16(bc_buf + pos + 5);+                ret = resolve_scope_private_field(ctx, s, var_name, scope, op, &bc_out);+                if (ret < 0)+                    goto fail;+                JS_FreeAtom(ctx, var_name);+            }+            break;+        case OP_gosub:+            s->jump_size++;+            if (OPTIMIZE) {+                /* remove calls to empty finalizers  */+                int label;+                LabelSlot *ls;++                label = get_u32(bc_buf + pos + 1);+                assert(label >= 0 && label < s->label_count);+                ls = &s->label_slots[label];+                if (code_match(&cc, ls->pos, OP_ret, -1)) {+                    ls->ref_count--;+                    break;+                }+            }+            goto no_change;+        case OP_drop:+            if (0) {+                /* remove drops before return_undef */+                /* do not perform this optimization in pass2 because+                   it breaks patterns recognised in resolve_labels */+                int pos1 = pos_next;+                int line1 = line_num;+                while (code_match(&cc, pos1, OP_drop, -1)) {+                    if (cc.line_num >= 0) line1 = cc.line_num;+                    pos1 = cc.pos;+                }+                if (code_match(&cc, pos1, OP_return_undef, -1)) {+                    pos_next = pos1;+                    if (line1 != -1 && line1 != line_num) {+                        line_num = line1;+                        s->line_number_size++;+                        dbuf_putc(&bc_out, OP_line_num);+                        dbuf_put_u32(&bc_out, line_num);+                    }+                    break;+                }+            }+            goto no_change;+        case OP_insert3:+            if (OPTIMIZE) {+                /* Transformation: insert3 put_array_el|put_ref_value drop -> put_array_el|put_ref_value */+                if (code_match(&cc, pos_next, M2(OP_put_array_el, OP_put_ref_value), OP_drop, -1)) {+                    dbuf_putc(&bc_out, cc.op);+                    pos_next = cc.pos;+                    if (cc.line_num != -1 && cc.line_num != line_num) {+                        line_num = cc.line_num;+                        s->line_number_size++;+                        dbuf_putc(&bc_out, OP_line_num);+                        dbuf_put_u32(&bc_out, line_num);+                    }+                    break;+                }+            }+            goto no_change;++        case OP_goto:+            s->jump_size++;+            /* fall thru */+        case OP_tail_call:+        case OP_tail_call_method:+        case OP_return:+        case OP_return_undef:+        case OP_throw:+        case OP_throw_error:+        case OP_ret:+            if (OPTIMIZE) {+                /* remove dead code */+                int line = -1;+                dbuf_put(&bc_out, bc_buf + pos, len);+                pos = skip_dead_code(s, bc_buf, bc_len, pos + len, &line);+                pos_next = pos;+                if (pos < bc_len && line >= 0 && line_num != line) {+                    line_num = line;+                    s->line_number_size++;+                    dbuf_putc(&bc_out, OP_line_num);+                    dbuf_put_u32(&bc_out, line_num);+                }+                break;+            }+            goto no_change;++        case OP_label:+            {+                int label;+                LabelSlot *ls;++                label = get_u32(bc_buf + pos + 1);+                assert(label >= 0 && label < s->label_count);+                ls = &s->label_slots[label];+                ls->pos2 = bc_out.size + opcode_info[op].size;+            }+            goto no_change;++        case OP_enter_scope:+            {+                int scope_idx, scope = get_u16(bc_buf + pos + 1);++                if (scope == s->body_scope) {+                    instantiate_hoisted_definitions(ctx, s, &bc_out);+                }++                for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {+                    JSVarDef *vd = &s->vars[scope_idx];+                    if (vd->scope_level == scope) {+                        if (scope_idx != s->arguments_arg_idx) {+                            if (vd->var_kind == JS_VAR_FUNCTION_DECL ||+                                vd->var_kind == JS_VAR_NEW_FUNCTION_DECL) {+                                /* Initialize lexical variable upon entering scope */+                                dbuf_putc(&bc_out, OP_fclosure);+                                dbuf_put_u32(&bc_out, vd->func_pool_idx);+                                dbuf_putc(&bc_out, OP_put_loc);+                                dbuf_put_u16(&bc_out, scope_idx);+                            } else {+                                /* XXX: should check if variable can be used+                                   before initialization */+                                dbuf_putc(&bc_out, OP_set_loc_uninitialized);+                                dbuf_put_u16(&bc_out, scope_idx);+                            }+                        }+                        scope_idx = vd->scope_next;+                    } else {+                        break;+                    }+                }+            }+            break;++        case OP_leave_scope:+            {+                int scope_idx, scope = get_u16(bc_buf + pos + 1);++                for(scope_idx = s->scopes[scope].first; scope_idx >= 0;) {+                    JSVarDef *vd = &s->vars[scope_idx];+                    if (vd->scope_level == scope) {+                        if (vd->is_captured) {+                            dbuf_putc(&bc_out, OP_close_loc);+                            dbuf_put_u16(&bc_out, scope_idx);+                        }+                        scope_idx = vd->scope_next;+                    } else {+                        break;+                    }+                }+            }+            break;++        case OP_set_name:+            {+                /* remove dummy set_name opcodes */+                JSAtom name = get_u32(bc_buf + pos + 1);+                if (name == JS_ATOM_NULL)+                    break;+            }+            goto no_change;++        case OP_if_false:+        case OP_if_true:+        case OP_catch:+            s->jump_size++;+            goto no_change;++        case OP_dup:+            if (OPTIMIZE) {+                /* Transformation: dup if_false(l1) drop, l1: if_false(l2) -> if_false(l2) */+                /* Transformation: dup if_true(l1) drop, l1: if_true(l2) -> if_true(l2) */+                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), OP_drop, -1)) {+                    int lab0, lab1, op1, pos1, line1, pos2;+                    lab0 = lab1 = cc.label;+                    assert(lab1 >= 0 && lab1 < s->label_count);+                    op1 = cc.op;+                    pos1 = cc.pos;+                    line1 = cc.line_num;+                    while (code_match(&cc, (pos2 = get_label_pos(s, lab1)), OP_dup, op1, OP_drop, -1)) {+                        lab1 = cc.label;+                    }+                    if (code_match(&cc, pos2, op1, -1)) {+                        s->jump_size++;+                        update_label(s, lab0, -1);+                        update_label(s, cc.label, +1);+                        dbuf_putc(&bc_out, op1);+                        dbuf_put_u32(&bc_out, cc.label);+                        pos_next = pos1;+                        if (line1 != -1 && line1 != line_num) {+                            line_num = line1;+                            s->line_number_size++;+                            dbuf_putc(&bc_out, OP_line_num);+                            dbuf_put_u32(&bc_out, line_num);+                        }+                        break;+                    }+                }+            }+            goto no_change;++        case OP_nop:+            /* remove erased code */+            break;+        case OP_set_class_name:+            /* only used during parsing */+            break;+            +        default:+        no_change:+            dbuf_put(&bc_out, bc_buf + pos, len);+            break;+        }+    }++    /* set the new byte code */+    dbuf_free(&s->byte_code);+    s->byte_code = bc_out;+    if (dbuf_error(&s->byte_code)) {+        JS_ThrowOutOfMemory(ctx);+        return -1;+    }+    return 0;+ fail:+    /* continue the copy to keep the atom refcounts consistent */+    /* XXX: find a better solution ? */+    for (; pos < bc_len; pos = pos_next) {+        op = bc_buf[pos];+        len = opcode_info[op].size;+        pos_next = pos + len;+        dbuf_put(&bc_out, bc_buf + pos, len);+    }+    dbuf_free(&s->byte_code);+    s->byte_code = bc_out;+    return -1;+}++/* the pc2line table gives a line number for each PC value */+static void add_pc2line_info(JSFunctionDef *s, uint32_t pc, int line_num)+{+    if (s->line_number_slots != NULL+    &&  s->line_number_count < s->line_number_size+    &&  pc >= s->line_number_last_pc+    &&  line_num != s->line_number_last) {+        s->line_number_slots[s->line_number_count].pc = pc;+        s->line_number_slots[s->line_number_count].line_num = line_num;+        s->line_number_count++;+        s->line_number_last_pc = pc;+        s->line_number_last = line_num;+    }+}++static void compute_pc2line_info(JSFunctionDef *s)+{+    if (!(s->js_mode & JS_MODE_STRIP) && s->line_number_slots) {+        int last_line_num = s->line_num;+        uint32_t last_pc = 0;+        int i;++        js_dbuf_init(s->ctx, &s->pc2line);+        for (i = 0; i < s->line_number_count; i++) {+            uint32_t pc = s->line_number_slots[i].pc;+            int line_num = s->line_number_slots[i].line_num;+            int diff_pc, diff_line;++            if (line_num < 0)+                continue;++            diff_pc = pc - last_pc;+            diff_line = line_num - last_line_num;+            if (diff_line == 0 || diff_pc < 0)+                continue;++            if (diff_line >= PC2LINE_BASE &&+                diff_line < PC2LINE_BASE + PC2LINE_RANGE &&+                diff_pc <= PC2LINE_DIFF_PC_MAX) {+                dbuf_putc(&s->pc2line, (diff_line - PC2LINE_BASE) ++                          diff_pc * PC2LINE_RANGE + PC2LINE_OP_FIRST);+            } else {+                /* longer encoding */+                dbuf_putc(&s->pc2line, 0);+                dbuf_put_leb128(&s->pc2line, diff_pc);+                dbuf_put_sleb128(&s->pc2line, diff_line);+            }+            last_pc = pc;+            last_line_num = line_num;+        }+    }+}++static RelocEntry *add_reloc(JSContext *ctx, LabelSlot *ls, uint32_t addr, int size)+{+    RelocEntry *re;+    re = js_malloc(ctx, sizeof(*re));+    if (!re)+        return NULL;+    re->addr = addr;+    re->size = size;+    re->next = ls->first_reloc;+    ls->first_reloc = re;+    return re;+}++static BOOL code_has_label(CodeContext *s, int pos, int label)+{+    while (pos < s->bc_len) {+        int op = s->bc_buf[pos];+        if (op == OP_line_num) {+            pos += 5;+            continue;+        }+        if (op == OP_label) {+            int lab = get_u32(s->bc_buf + pos + 1);+            if (lab == label)+                return TRUE;+            pos += 5;+            continue;+        }+        if (op == OP_goto) {+            int lab = get_u32(s->bc_buf + pos + 1);+            if (lab == label)+                return TRUE;+        }+        break;+    }+    return FALSE;+}++/* return the target label, following the OP_goto jumps+   the first opcode at destination is stored in *pop+ */+static int find_jump_target(JSFunctionDef *s, int label, int *pop, int *pline)+{+    int i, pos, op;++    update_label(s, label, -1);+    for (i = 0; i < 10; i++) {+        assert(label >= 0 && label < s->label_count);+        pos = s->label_slots[label].pos2;+        for (;;) {+            switch(op = s->byte_code.buf[pos]) {+            case OP_line_num:+                if (pline)+                    *pline = get_u32(s->byte_code.buf + pos + 1);+                /* fall thru */+            case OP_label:+                pos += opcode_info[op].size;+                continue;+            case OP_goto:+                label = get_u32(s->byte_code.buf + pos + 1);+                break;+            case OP_drop:+                /* ignore drop opcodes if followed by OP_return_undef */+                while (s->byte_code.buf[++pos] == OP_drop)+                    continue;+                if (s->byte_code.buf[pos] == OP_return_undef)+                    op = OP_return_undef;+                /* fall thru */+            default:+                goto done;+            }+            break;+        }+    }+    /* cycle detected, could issue a warning */+ done:+    *pop = op;+    update_label(s, label, +1);+    return label;+}++static void push_short_int(DynBuf *bc_out, int val)+{+#if SHORT_OPCODES+    if (val >= -1 && val <= 7) {+        dbuf_putc(bc_out, OP_push_0 + val);+        return;+    }+    if (val == (int8_t)val) {+        dbuf_putc(bc_out, OP_push_i8);+        dbuf_putc(bc_out, val);+        return;+    }+    if (val == (int16_t)val) {+        dbuf_putc(bc_out, OP_push_i16);+        dbuf_put_u16(bc_out, val);+        return;+    }+#endif+    dbuf_putc(bc_out, OP_push_i32);+    dbuf_put_u32(bc_out, val);+}++static void put_short_code(DynBuf *bc_out, int op, int idx)+{+#if SHORT_OPCODES+    if (idx < 4) {+        switch (op) {+        case OP_get_loc:+            dbuf_putc(bc_out, OP_get_loc0 + idx);+            return;+        case OP_put_loc:+            dbuf_putc(bc_out, OP_put_loc0 + idx);+            return;+        case OP_set_loc:+            dbuf_putc(bc_out, OP_set_loc0 + idx);+            return;+        case OP_get_arg:+            dbuf_putc(bc_out, OP_get_arg0 + idx);+            return;+        case OP_put_arg:+            dbuf_putc(bc_out, OP_put_arg0 + idx);+            return;+        case OP_set_arg:+            dbuf_putc(bc_out, OP_set_arg0 + idx);+            return;+        case OP_get_var_ref:+            dbuf_putc(bc_out, OP_get_var_ref0 + idx);+            return;+        case OP_put_var_ref:+            dbuf_putc(bc_out, OP_put_var_ref0 + idx);+            return;+        case OP_set_var_ref:+            dbuf_putc(bc_out, OP_set_var_ref0 + idx);+            return;+        case OP_call:+            dbuf_putc(bc_out, OP_call0 + idx);+            return;+        }+    }+    if (idx < 256) {+        switch (op) {+        case OP_get_loc:+            dbuf_putc(bc_out, OP_get_loc8);+            dbuf_putc(bc_out, idx);+            return;+        case OP_put_loc:+            dbuf_putc(bc_out, OP_put_loc8);+            dbuf_putc(bc_out, idx);+            return;+        case OP_set_loc:+            dbuf_putc(bc_out, OP_set_loc8);+            dbuf_putc(bc_out, idx);+            return;+        }+    }+#endif+    dbuf_putc(bc_out, op);+    dbuf_put_u16(bc_out, idx);+}++/* peephole optimizations and resolve goto/labels */+static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)+{+    int pos, pos_next, bc_len, op, op1, len, i, line_num;+    const uint8_t *bc_buf;+    DynBuf bc_out;+    LabelSlot *label_slots, *ls;+    RelocEntry *re, *re_next;+    CodeContext cc;+    int label;+#if SHORT_OPCODES+    JumpSlot *jp;+#endif++    label_slots = s->label_slots;++    line_num = s->line_num;++    cc.bc_buf = bc_buf = s->byte_code.buf;+    cc.bc_len = bc_len = s->byte_code.size;+    js_dbuf_init(ctx, &bc_out);++#if SHORT_OPCODES+    if (s->jump_size) {+        s->jump_slots = js_mallocz(s->ctx, sizeof(*s->jump_slots) * s->jump_size);+        if (s->jump_slots == NULL)+            return -1;+    }+#endif+    /* XXX: Should skip this phase if not generating SHORT_OPCODES */+    if (s->line_number_size && !(s->js_mode & JS_MODE_STRIP)) {+        s->line_number_slots = js_mallocz(s->ctx, sizeof(*s->line_number_slots) * s->line_number_size);+        if (s->line_number_slots == NULL)+            return -1;+        s->line_number_last = s->line_num;+        s->line_number_last_pc = 0;+    }++    /* initialize the 'home_object' variable if needed */+    if (s->home_object_var_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_HOME_OBJECT);+        put_short_code(&bc_out, OP_put_loc, s->home_object_var_idx);+    }+    /* initialize the 'this.active_func' variable if needed */+    if (s->this_active_func_var_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC);+        put_short_code(&bc_out, OP_put_loc, s->this_active_func_var_idx);+    }+    /* initialize the 'new.target' variable if needed */+    if (s->new_target_var_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_NEW_TARGET);+        put_short_code(&bc_out, OP_put_loc, s->new_target_var_idx);+    }+    /* initialize the 'this' variable if needed. In a derived class+       constructor, this is initially uninitialized. */+    if (s->this_var_idx >= 0) {+        if (s->is_derived_class_constructor) {+            dbuf_putc(&bc_out, OP_set_loc_uninitialized);+            dbuf_put_u16(&bc_out, s->this_var_idx);+        } else {+            dbuf_putc(&bc_out, OP_push_this);+            put_short_code(&bc_out, OP_put_loc, s->this_var_idx);+        }+    }+    /* initialize the 'arguments' variable if needed */+    if (s->arguments_var_idx >= 0) {+        if ((s->js_mode & JS_MODE_STRICT) || !s->has_simple_parameter_list) {+            dbuf_putc(&bc_out, OP_special_object);+            dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_ARGUMENTS);+        } else {+            dbuf_putc(&bc_out, OP_special_object);+            dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_MAPPED_ARGUMENTS);+        }+        if (s->arguments_arg_idx >= 0)+            put_short_code(&bc_out, OP_set_loc, s->arguments_arg_idx);+        put_short_code(&bc_out, OP_put_loc, s->arguments_var_idx);+    }+    /* initialize a reference to the current function if needed */+    if (s->func_var_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_THIS_FUNC);+        put_short_code(&bc_out, OP_put_loc, s->func_var_idx);+    }+    /* initialize the variable environment object if needed */+    if (s->var_object_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT);+        put_short_code(&bc_out, OP_put_loc, s->var_object_idx);+    }+    if (s->arg_var_object_idx >= 0) {+        dbuf_putc(&bc_out, OP_special_object);+        dbuf_putc(&bc_out, OP_SPECIAL_OBJECT_VAR_OBJECT);+        put_short_code(&bc_out, OP_put_loc, s->arg_var_object_idx);+    }++    for (pos = 0; pos < bc_len; pos = pos_next) {+        int val;+        op = bc_buf[pos];+        len = opcode_info[op].size;+        pos_next = pos + len;+        switch(op) {+        case OP_line_num:+            /* line number info (for debug). We put it in a separate+               compressed table to reduce memory usage and get better+               performance */+            line_num = get_u32(bc_buf + pos + 1);+            break;++        case OP_label:+            {+                label = get_u32(bc_buf + pos + 1);+                assert(label >= 0 && label < s->label_count);+                ls = &label_slots[label];+                assert(ls->addr == -1);+                ls->addr = bc_out.size;+                /* resolve the relocation entries */+                for(re = ls->first_reloc; re != NULL; re = re_next) {+                    int diff = ls->addr - re->addr;+                    re_next = re->next;+                    switch (re->size) {+                    case 4:+                        put_u32(bc_out.buf + re->addr, diff);+                        break;+                    case 2:+                        assert(diff == (int16_t)diff);+                        put_u16(bc_out.buf + re->addr, diff);+                        break;+                    case 1:+                        assert(diff == (int8_t)diff);+                        put_u8(bc_out.buf + re->addr, diff);+                        break;+                    }+                    js_free(ctx, re);+                }+                ls->first_reloc = NULL;+            }+            break;++        case OP_call:+        case OP_call_method:+            {+                /* detect and transform tail calls */+                int argc;+                argc = get_u16(bc_buf + pos + 1);+                if (code_match(&cc, pos_next, OP_return, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    put_short_code(&bc_out, op + 1, argc);+                    pos_next = skip_dead_code(s, bc_buf, bc_len, cc.pos, &line_num);+                    break;+                }+                add_pc2line_info(s, bc_out.size, line_num);+                put_short_code(&bc_out, op, argc);+                break;+            }+            goto no_change;++        case OP_return:+        case OP_return_undef:+        case OP_return_async:+        case OP_throw:+        case OP_throw_error:+            pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);+            goto no_change;++        case OP_goto:+            label = get_u32(bc_buf + pos + 1);+        has_goto:+            if (OPTIMIZE) {+                int line1 = -1;+                /* Use custom matcher because multiple labels can follow */+                label = find_jump_target(s, label, &op1, &line1);+                if (code_has_label(&cc, pos_next, label)) {+                    /* jump to next instruction: remove jump */+                    update_label(s, label, -1);+                    break;+                }+                if (op1 == OP_return || op1 == OP_return_undef || op1 == OP_throw) {+                    /* jump to return/throw: remove jump, append return/throw */+                    /* updating the line number obfuscates assembly listing */+                    //if (line1 >= 0) line_num = line1;+                    update_label(s, label, -1);+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, op1);+                    pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);+                    break;+                }+                /* XXX: should duplicate single instructions followed by goto or return */+                /* For example, can match one of these followed by return:+                   push_i32 / push_const / push_atom_value / get_var /+                   undefined / null / push_false / push_true / get_ref_value /+                   get_loc / get_arg / get_var_ref+                 */+            }+            goto has_label;++        case OP_gosub:+            label = get_u32(bc_buf + pos + 1);+            if (0 && OPTIMIZE) {+                label = find_jump_target(s, label, &op1, NULL);+                if (op1 == OP_ret) {+                    update_label(s, label, -1);+                    /* empty finally clause: remove gosub */+                    break;+                }+            }+            goto has_label;++        case OP_catch:+            label = get_u32(bc_buf + pos + 1);+            goto has_label;++        case OP_if_true:+        case OP_if_false:+            label = get_u32(bc_buf + pos + 1);+            if (OPTIMIZE) {+                label = find_jump_target(s, label, &op1, NULL);+                /* transform if_false/if_true(l1) label(l1) -> drop label(l1) */+                if (code_has_label(&cc, pos_next, label)) {+                    update_label(s, label, -1);+                    dbuf_putc(&bc_out, OP_drop);+                    break;+                }+                /* transform if_false(l1) goto(l2) label(l1) -> if_false(l2) label(l1) */+                if (code_match(&cc, pos_next, OP_goto, -1)) {+                    int pos1 = cc.pos;+                    int line1 = cc.line_num;+                    if (code_has_label(&cc, pos1, label)) {+                        if (line1 >= 0) line_num = line1;+                        pos_next = pos1;+                        update_label(s, label, -1);+                        label = cc.label;+                        op ^= OP_if_true ^ OP_if_false;+                    }+                }+            }+        has_label:+            add_pc2line_info(s, bc_out.size, line_num);+            if (op == OP_goto) {+                pos_next = skip_dead_code(s, bc_buf, bc_len, pos_next, &line_num);+            }+            assert(label >= 0 && label < s->label_count);+            ls = &label_slots[label];+#if SHORT_OPCODES+            jp = &s->jump_slots[s->jump_count++];+            jp->op = op;+            jp->size = 4;+            jp->pos = bc_out.size + 1;+            jp->label = label;++            if (ls->addr == -1) {+                int diff = ls->pos2 - pos - 1;+                if (diff < 128 && (op == OP_if_false || op == OP_if_true || op == OP_goto)) {+                    jp->size = 1;+                    jp->op = OP_if_false8 + (op - OP_if_false);+                    dbuf_putc(&bc_out, OP_if_false8 + (op - OP_if_false));+                    dbuf_putc(&bc_out, 0);+                    if (!add_reloc(ctx, ls, bc_out.size - 1, 1))+                        goto fail;+                    break;+                }+                if (diff < 32768 && op == OP_goto) {+                    jp->size = 2;+                    jp->op = OP_goto16;+                    dbuf_putc(&bc_out, OP_goto16);+                    dbuf_put_u16(&bc_out, 0);+                    if (!add_reloc(ctx, ls, bc_out.size - 2, 2))+                        goto fail;+                    break;+                }+            } else {+                int diff = ls->addr - bc_out.size - 1;+                if (diff == (int8_t)diff && (op == OP_if_false || op == OP_if_true || op == OP_goto)) {+                    jp->size = 1;+                    jp->op = OP_if_false8 + (op - OP_if_false);+                    dbuf_putc(&bc_out, OP_if_false8 + (op - OP_if_false));+                    dbuf_putc(&bc_out, diff);+                    break;+                }+                if (diff == (int16_t)diff && op == OP_goto) {+                    jp->size = 2;+                    jp->op = OP_goto16;+                    dbuf_putc(&bc_out, OP_goto16);+                    dbuf_put_u16(&bc_out, diff);+                    break;+                }+            }+#endif+            dbuf_putc(&bc_out, op);+            dbuf_put_u32(&bc_out, ls->addr - bc_out.size);+            if (ls->addr == -1) {+                /* unresolved yet: create a new relocation entry */+                if (!add_reloc(ctx, ls, bc_out.size - 4, 4))+                    goto fail;+            }+            break;+        case OP_with_get_var:+        case OP_with_put_var:+        case OP_with_delete_var:+        case OP_with_make_ref:+        case OP_with_get_ref:+        case OP_with_get_ref_undef:+            {+                JSAtom atom;+                int is_with;++                atom = get_u32(bc_buf + pos + 1);+                label = get_u32(bc_buf + pos + 5);+                is_with = bc_buf[pos + 9];+                if (OPTIMIZE) {+                    label = find_jump_target(s, label, &op1, NULL);+                }+                assert(label >= 0 && label < s->label_count);+                ls = &label_slots[label];+                add_pc2line_info(s, bc_out.size, line_num);+#if SHORT_OPCODES+                jp = &s->jump_slots[s->jump_count++];+                jp->op = op;+                jp->size = 4;+                jp->pos = bc_out.size + 5;+                jp->label = label;+#endif+                dbuf_putc(&bc_out, op);+                dbuf_put_u32(&bc_out, atom);+                dbuf_put_u32(&bc_out, ls->addr - bc_out.size);+                if (ls->addr == -1) {+                    /* unresolved yet: create a new relocation entry */+                    if (!add_reloc(ctx, ls, bc_out.size - 4, 4))+                        goto fail;+                }+                dbuf_putc(&bc_out, is_with);+            }+            break;++        case OP_drop:+            if (OPTIMIZE) {+                /* remove useless drops before return */+                if (code_match(&cc, pos_next, OP_return_undef, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    break;+                }+            }+            goto no_change;++        case OP_null:+#if SHORT_OPCODES+            if (OPTIMIZE) {+                /* transform null strict_eq into is_null */+                if (code_match(&cc, pos_next, OP_strict_eq, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_is_null);+                    pos_next = cc.pos;+                    break;+                }+                /* transform null strict_neq if_false/if_true -> is_null if_true/if_false */+                if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_is_null);+                    pos_next = cc.pos;+                    label = cc.label;+                    op = cc.op ^ OP_if_false ^ OP_if_true;+                    goto has_label;+                }+            }+#endif+            /* fall thru */+        case OP_push_false:+        case OP_push_true:+            if (OPTIMIZE) {+                val = (op == OP_push_true);+                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {+                has_constant_test:+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    if (val == cc.op - OP_if_false) {+                        /* transform null if_false(l1) -> goto l1 */+                        /* transform false if_false(l1) -> goto l1 */+                        /* transform true if_true(l1) -> goto l1 */+                        pos_next = cc.pos;+                        op = OP_goto;+                        label = cc.label;+                        goto has_goto;+                    } else {+                        /* transform null if_true(l1) -> nop */+                        /* transform false if_true(l1) -> nop */+                        /* transform true if_false(l1) -> nop */+                        pos_next = cc.pos;+                        update_label(s, cc.label, -1);+                        break;+                    }+                }+            }+            goto no_change;++        case OP_push_i32:+            if (OPTIMIZE) {+                /* transform i32(val) neg -> i32(-val) */+                val = get_i32(bc_buf + pos + 1);+                if ((val != INT32_MIN && val != 0)+                &&  code_match(&cc, pos_next, OP_neg, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    if (code_match(&cc, cc.pos, OP_drop, -1)) {+                        if (cc.line_num >= 0) line_num = cc.line_num;+                    } else {+                        add_pc2line_info(s, bc_out.size, line_num);+                        push_short_int(&bc_out, -val);+                    }+                    pos_next = cc.pos;+                    break;+                }+                /* remove push/drop pairs generated by the parser */+                if (code_match(&cc, pos_next, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    pos_next = cc.pos;+                    break;+                }+                /* Optimize constant tests: `if (0)`, `if (1)`, `if (!0)`... */+                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {+                    val = (val != 0);+                    goto has_constant_test;+                }+                add_pc2line_info(s, bc_out.size, line_num);+                push_short_int(&bc_out, val);+                break;+            }+            goto no_change;++#if SHORT_OPCODES+        case OP_push_const:+        case OP_fclosure:+            if (OPTIMIZE) {+                int idx = get_u32(bc_buf + pos + 1);+                if (idx < 256) {+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_push_const8 + op - OP_push_const);+                    dbuf_putc(&bc_out, idx);+                    break;+                }+            }+            goto no_change;++        case OP_get_field:+            if (OPTIMIZE) {+                JSAtom atom = get_u32(bc_buf + pos + 1);+                if (atom == JS_ATOM_length) {+                    JS_FreeAtom(ctx, atom);+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_get_length);+                    break;+                }+            }+            goto no_change;+#endif+        case OP_push_atom_value:+            if (OPTIMIZE) {+                JSAtom atom = get_u32(bc_buf + pos + 1);+                /* remove push/drop pairs generated by the parser */+                if (code_match(&cc, pos_next, OP_drop, -1)) {+                    JS_FreeAtom(ctx, atom);+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    pos_next = cc.pos;+                    break;+                }+#if SHORT_OPCODES+                if (atom == JS_ATOM_empty_string) {+                    JS_FreeAtom(ctx, atom);+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_push_empty_string);+                    break;+                }+#endif+            }+            goto no_change;++        case OP_to_propkey:+        case OP_to_propkey2:+            if (OPTIMIZE) {+                /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */+                if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1)+                ||  code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1)+                ||  code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) {+                    break;+                }+            }+            goto no_change;++        case OP_undefined:+            if (OPTIMIZE) {+                /* remove push/drop pairs generated by the parser */+                if (code_match(&cc, pos_next, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    pos_next = cc.pos;+                    break;+                }+                /* transform undefined return -> return_undefined */+                if (code_match(&cc, pos_next, OP_return, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_return_undef);+                    pos_next = cc.pos;+                    break;+                }+                /* transform undefined if_true(l1)/if_false(l1) -> nop/goto(l1) */+                if (code_match(&cc, pos_next, M2(OP_if_false, OP_if_true), -1)) {+                    val = 0;+                    goto has_constant_test;+                }+#if SHORT_OPCODES+                /* transform undefined strict_eq -> is_undefined */+                if (code_match(&cc, pos_next, OP_strict_eq, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_is_undefined);+                    pos_next = cc.pos;+                    break;+                }+                /* transform undefined strict_neq if_false/if_true -> is_undefined if_true/if_false */+                if (code_match(&cc, pos_next, OP_strict_neq, M2(OP_if_false, OP_if_true), -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_is_undefined);+                    pos_next = cc.pos;+                    label = cc.label;+                    op = cc.op ^ OP_if_false ^ OP_if_true;+                    goto has_label;+                }+#endif+            }+            goto no_change;++        case OP_insert2:+            if (OPTIMIZE) {+                /* Transformation:+                   insert2 put_field(a) drop -> put_field(a)+                   insert2 put_var_strict(a) drop -> put_var_strict(a)+                */+                if (code_match(&cc, pos_next, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, cc.op);+                    dbuf_put_u32(&bc_out, cc.atom);+                    pos_next = cc.pos;+                    break;+                }+            }+            goto no_change;++        case OP_dup:+            if (OPTIMIZE) {+                /* Transformation: dup put_x(n) drop -> put_x(n) */+                int op1, line2 = -1;+                /* Transformation: dup put_x(n) -> set_x(n) */+                if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    op1 = cc.op + 1;  /* put_x -> set_x */+                    pos_next = cc.pos;+                    if (code_match(&cc, cc.pos, OP_drop, -1)) {+                        if (cc.line_num >= 0) line_num = cc.line_num;+                        op1 -= 1; /* set_x drop -> put_x */+                        pos_next = cc.pos;+                        if (code_match(&cc, cc.pos, op1 - 1, cc.idx, -1)) {+                            line2 = cc.line_num; /* delay line number update */+                            op1 += 1;   /* put_x(n) get_x(n) -> set_x(n) */+                            pos_next = cc.pos;+                        }+                    }+                    add_pc2line_info(s, bc_out.size, line_num);+                    put_short_code(&bc_out, op1, cc.idx);+                    if (line2 >= 0) line_num = line2;+                    break;+                }+            }+            goto no_change;++        case OP_get_loc:+            if (OPTIMIZE) {+                /* transformation:+                   get_loc(n) post_dec put_loc(n) drop -> dec_loc(n)+                   get_loc(n) post_inc put_loc(n) drop -> inc_loc(n)+                   get_loc(n) dec dup put_loc(n) drop -> dec_loc(n)+                   get_loc(n) inc dup put_loc(n) drop -> inc_loc(n)+                 */+                int idx;+                idx = get_u16(bc_buf + pos + 1);+                if (idx >= 256)+                    goto no_change;+                if (code_match(&cc, pos_next, M2(OP_post_dec, OP_post_inc), OP_put_loc, idx, OP_drop, -1) ||+                    code_match(&cc, pos_next, M2(OP_dec, OP_inc), OP_dup, OP_put_loc, idx, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, (cc.op == OP_inc || cc.op == OP_post_inc) ? OP_inc_loc : OP_dec_loc);+                    dbuf_putc(&bc_out, idx);+                    pos_next = cc.pos;+                    break;+                }+                /* transformation:+                   get_loc(n) push_atom_value(x) add dup put_loc(n) drop -> push_atom_value(x) add_loc(n)+                 */+                if (code_match(&cc, pos_next, OP_push_atom_value, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+#if SHORT_OPCODES+                    if (cc.atom == JS_ATOM_empty_string) {+                        JS_FreeAtom(ctx, cc.atom);+                        dbuf_putc(&bc_out, OP_push_empty_string);+                    } else+#endif+                    {+                        dbuf_putc(&bc_out, OP_push_atom_value);+                        dbuf_put_u32(&bc_out, cc.atom);+                    }+                    dbuf_putc(&bc_out, OP_add_loc);+                    dbuf_putc(&bc_out, idx);+                    pos_next = cc.pos;+                    break;+                }+                /* transformation:+                   get_loc(n) push_i32(x) add dup put_loc(n) drop -> push_i32(x) add_loc(n)+                 */+                if (code_match(&cc, pos_next, OP_push_i32, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    push_short_int(&bc_out, cc.label);+                    dbuf_putc(&bc_out, OP_add_loc);+                    dbuf_putc(&bc_out, idx);+                    pos_next = cc.pos;+                    break;+                }+                /* transformation: XXX: also do these:+                   get_loc(n) get_loc(x) add dup put_loc(n) drop -> get_loc(x) add_loc(n)+                   get_loc(n) get_arg(x) add dup put_loc(n) drop -> get_arg(x) add_loc(n)+                   get_loc(n) get_var_ref(x) add dup put_loc(n) drop -> get_var_ref(x) add_loc(n)+                 */+                if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_add, OP_dup, OP_put_loc, idx, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    put_short_code(&bc_out, cc.op, cc.idx);+                    dbuf_putc(&bc_out, OP_add_loc);+                    dbuf_putc(&bc_out, idx);+                    pos_next = cc.pos;+                    break;+                }+                add_pc2line_info(s, bc_out.size, line_num);+                put_short_code(&bc_out, op, idx);+                break;+            }+            goto no_change;+#if SHORT_OPCODES+        case OP_get_arg:+        case OP_get_var_ref:+            if (OPTIMIZE) {+                int idx;+                idx = get_u16(bc_buf + pos + 1);+                add_pc2line_info(s, bc_out.size, line_num);+                put_short_code(&bc_out, op, idx);+                break;+            }+            goto no_change;+#endif+        case OP_put_loc:+        case OP_put_arg:+        case OP_put_var_ref:+            if (OPTIMIZE) {+                /* transformation: put_x(n) get_x(n) -> set_x(n) */+                int idx;+                idx = get_u16(bc_buf + pos + 1);+                if (code_match(&cc, pos_next, op - 1, idx, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    put_short_code(&bc_out, op + 1, idx);+                    pos_next = cc.pos;+                    break;+                }+                add_pc2line_info(s, bc_out.size, line_num);+                put_short_code(&bc_out, op, idx);+                break;+            }+            goto no_change;++        case OP_post_inc:+        case OP_post_dec:+            if (OPTIMIZE) {+                /* transformation:+                   post_inc put_x drop -> inc put_x+                   post_inc perm3 put_field drop -> inc put_field+                   post_inc perm3 put_var_strict drop -> inc put_var_strict+                   post_inc perm4 put_array_el drop -> inc put_array_el+                 */+                int op1, idx;+                if (code_match(&cc, pos_next, M3(OP_put_loc, OP_put_arg, OP_put_var_ref), -1, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    op1 = cc.op;+                    idx = cc.idx;+                    pos_next = cc.pos;+                    if (code_match(&cc, cc.pos, op1 - 1, idx, -1)) {+                        if (cc.line_num >= 0) line_num = cc.line_num;+                        op1 += 1;   /* put_x(n) get_x(n) -> set_x(n) */+                        pos_next = cc.pos;+                    }+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));+                    put_short_code(&bc_out, op1, idx);+                    break;+                }+                if (code_match(&cc, pos_next, OP_perm3, M2(OP_put_field, OP_put_var_strict), OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));+                    dbuf_putc(&bc_out, cc.op);+                    dbuf_put_u32(&bc_out, cc.atom);+                    pos_next = cc.pos;+                    break;+                }+                if (code_match(&cc, pos_next, OP_perm4, OP_put_array_el, OP_drop, -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    add_pc2line_info(s, bc_out.size, line_num);+                    dbuf_putc(&bc_out, OP_dec + (op - OP_post_dec));+                    dbuf_putc(&bc_out, OP_put_array_el);+                    pos_next = cc.pos;+                    break;+                }+            }+            goto no_change;++#if SHORT_OPCODES+        case OP_typeof:+            if (OPTIMIZE) {+                /* simplify typeof tests */+                if (code_match(&cc, pos_next, OP_push_atom_value, M4(OP_strict_eq, OP_strict_neq, OP_eq, OP_neq), -1)) {+                    if (cc.line_num >= 0) line_num = cc.line_num;+                    int op1 = (cc.op == OP_strict_eq || cc.op == OP_eq) ? OP_strict_eq : OP_strict_neq;+                    int op2 = -1;+                    switch (cc.atom) {+                    case JS_ATOM_undefined:+                        op2 = OP_typeof_is_undefined;+                        break;+                    case JS_ATOM_function:+                        op2 = OP_typeof_is_function;+                        break;+                    }+                    if (op2 >= 0) {+                        /* transform typeof(s) == "<type>" into is_<type> */+                        if (op1 == OP_strict_eq) {+                            add_pc2line_info(s, bc_out.size, line_num);+                            dbuf_putc(&bc_out, op2);+                            JS_FreeAtom(ctx, cc.atom);+                            pos_next = cc.pos;+                            break;+                        }+                        if (op1 == OP_strict_neq && code_match(&cc, cc.pos, OP_if_false, -1)) {+                            /* transform typeof(s) != "<type>" if_false into is_<type> if_true */+                            if (cc.line_num >= 0) line_num = cc.line_num;+                            add_pc2line_info(s, bc_out.size, line_num);+                            dbuf_putc(&bc_out, op2);+                            JS_FreeAtom(ctx, cc.atom);+                            pos_next = cc.pos;+                            label = cc.label;+                            op = OP_if_true;+                            goto has_label;+                        }+                    }+                }+            }+            goto no_change;+#endif++        default:+        no_change:+            add_pc2line_info(s, bc_out.size, line_num);+            dbuf_put(&bc_out, bc_buf + pos, len);+            break;+        }+    }++    /* check that there were no missing labels */+    for(i = 0; i < s->label_count; i++) {+        assert(label_slots[i].first_reloc == NULL);+    }+#if SHORT_OPCODES+    if (OPTIMIZE) {+        /* more jump optimizations */+        int patch_offsets = 0;+        for (i = 0, jp = s->jump_slots; i < s->jump_count; i++, jp++) {+            LabelSlot *ls;+            JumpSlot *jp1;+            int j, pos, diff, delta;++            delta = 3;+            switch (op = jp->op) {+            case OP_goto16:+                delta = 1;+                /* fall thru */+            case OP_if_false:+            case OP_if_true:+            case OP_goto:+                pos = jp->pos;+                diff = s->label_slots[jp->label].addr - pos;+                if (diff >= -128 && diff <= 127 + delta) {+                    //put_u8(bc_out.buf + pos, diff);+                    jp->size = 1;+                    if (op == OP_goto16) {+                        bc_out.buf[pos - 1] = jp->op = OP_goto8;+                    } else {+                        bc_out.buf[pos - 1] = jp->op = OP_if_false8 + (op - OP_if_false);+                    }+                    goto shrink;+                } else+                if (diff == (int16_t)diff && op == OP_goto) {+                    //put_u16(bc_out.buf + pos, diff);+                    jp->size = 2;+                    delta = 2;+                    bc_out.buf[pos - 1] = jp->op = OP_goto16;+                shrink:+                    /* XXX: should reduce complexity, using 2 finger copy scheme */+                    memmove(bc_out.buf + pos + jp->size, bc_out.buf + pos + jp->size + delta,+                            bc_out.size - pos - jp->size - delta);+                    bc_out.size -= delta;+                    patch_offsets++;+                    for (j = 0, ls = s->label_slots; j < s->label_count; j++, ls++) {+                        if (ls->addr > pos)+                            ls->addr -= delta;+                    }+                    for (j = i + 1, jp1 = jp + 1; j < s->jump_count; j++, jp1++) {+                        if (jp1->pos > pos)+                            jp1->pos -= delta;+                    }+                    for (j = 0; j < s->line_number_count; j++) {+                        if (s->line_number_slots[j].pc > pos)+                            s->line_number_slots[j].pc -= delta;+                    }+                    continue;+                }+                break;+            }+        }+        if (patch_offsets) {+            JumpSlot *jp1;+            int j;+            for (j = 0, jp1 = s->jump_slots; j < s->jump_count; j++, jp1++) {+                int diff1 = s->label_slots[jp1->label].addr - jp1->pos;+                switch (jp1->size) {+                case 1:+                    put_u8(bc_out.buf + jp1->pos, diff1);+                    break;+                case 2:+                    put_u16(bc_out.buf + jp1->pos, diff1);+                    break;+                case 4:+                    put_u32(bc_out.buf + jp1->pos, diff1);+                    break;+                }+            }+        }+    }+    js_free(ctx, s->jump_slots);+    s->jump_slots = NULL;+#endif+    js_free(ctx, s->label_slots);+    s->label_slots = NULL;+    /* XXX: should delay until copying to runtime bytecode function */+    compute_pc2line_info(s);+    js_free(ctx, s->line_number_slots);+    s->line_number_slots = NULL;+    /* set the new byte code */+    dbuf_free(&s->byte_code);+    s->byte_code = bc_out;+    s->use_short_opcodes = TRUE;+    if (dbuf_error(&s->byte_code)) {+        JS_ThrowOutOfMemory(ctx);+        return -1;+    }+    return 0;+ fail:+    /* XXX: not safe */+    dbuf_free(&bc_out);+    return -1;+}++/* compute the maximum stack size needed by the function */++typedef struct StackSizeState {+    int bc_len;+    int stack_len_max;+    uint16_t *stack_level_tab;+    int *pc_stack;+    int pc_stack_len;+    int pc_stack_size;+} StackSizeState;++/* 'op' is only used for error indication */+static __exception int ss_check(JSContext *ctx, StackSizeState *s,+                                int pos, int op, int stack_len)+{+    if ((unsigned)pos >= s->bc_len) {+        JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);+        return -1;+    }+    if (stack_len > s->stack_len_max) {+        s->stack_len_max = stack_len;+        if (s->stack_len_max > JS_STACK_SIZE_MAX) {+            JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);+            return -1;+        }+    }+    if (s->stack_level_tab[pos] != 0xffff) {+        /* already explored: check that the stack size is consistent */+        if (s->stack_level_tab[pos] != stack_len) {+            JS_ThrowInternalError(ctx, "unconsistent stack size: %d %d (pc=%d)",+                                  s->stack_level_tab[pos], stack_len, pos);+            return -1;+        } else {+            return 0;+        }+    }++    /* mark as explored and store the stack size */+    s->stack_level_tab[pos] = stack_len;++    /* queue the new PC to explore */+    if (js_resize_array(ctx, (void **)&s->pc_stack, sizeof(s->pc_stack[0]),+                        &s->pc_stack_size, s->pc_stack_len + 1))+        return -1;+    s->pc_stack[s->pc_stack_len++] = pos;+    return 0;+}++static __exception int compute_stack_size(JSContext *ctx,+                                          JSFunctionDef *fd,+                                          int *pstack_size)+{+    StackSizeState s_s, *s = &s_s;+    int i, diff, n_pop, pos_next, stack_len, pos, op;+    const JSOpCode *oi;+    const uint8_t *bc_buf;++    bc_buf = fd->byte_code.buf;+    s->bc_len = fd->byte_code.size;+    /* bc_len > 0 */+    s->stack_level_tab = js_malloc(ctx, sizeof(s->stack_level_tab[0]) *+                                   s->bc_len);+    if (!s->stack_level_tab)+        return -1;+    for(i = 0; i < s->bc_len; i++)+        s->stack_level_tab[i] = 0xffff;+    s->stack_len_max = 0;+    s->pc_stack = NULL;+    s->pc_stack_len = 0;+    s->pc_stack_size = 0;++    /* breadth-first graph exploration */+    if (ss_check(ctx, s, 0, OP_invalid, 0))+        goto fail;++    while (s->pc_stack_len > 0) {+        pos = s->pc_stack[--s->pc_stack_len];+        stack_len = s->stack_level_tab[pos];+        op = bc_buf[pos];+        if (op == 0 || op >= OP_COUNT) {+            JS_ThrowInternalError(ctx, "invalid opcode (op=%d, pc=%d)", op, pos);+            goto fail;+        }+        oi = &short_opcode_info(op);+        pos_next = pos + oi->size;+        if (pos_next > s->bc_len) {+            JS_ThrowInternalError(ctx, "bytecode buffer overflow (op=%d, pc=%d)", op, pos);+            goto fail;+        }+        n_pop = oi->n_pop;+        /* call pops a variable number of arguments */+        if (oi->fmt == OP_FMT_npop || oi->fmt == OP_FMT_npop_u16) {+            n_pop += get_u16(bc_buf + pos + 1);+        } else {+#if SHORT_OPCODES+            if (oi->fmt == OP_FMT_npopx) {+                n_pop += op - OP_call0;+            }+#endif+        }++        if (stack_len < n_pop) {+            JS_ThrowInternalError(ctx, "stack underflow (op=%d, pc=%d)", op, pos);+            goto fail;+        }+        stack_len += oi->n_push - n_pop;+        if (stack_len > s->stack_len_max) {+            s->stack_len_max = stack_len;+            if (s->stack_len_max > JS_STACK_SIZE_MAX) {+                JS_ThrowInternalError(ctx, "stack overflow (op=%d, pc=%d)", op, pos);+                goto fail;+            }+        }+        switch(op) {+        case OP_tail_call:+        case OP_tail_call_method:+        case OP_return:+        case OP_return_undef:+        case OP_return_async:+        case OP_throw:+        case OP_throw_error:+        case OP_ret:+            goto done_insn;+        case OP_goto:+            diff = get_u32(bc_buf + pos + 1);+            pos_next = pos + 1 + diff;+            break;+#if SHORT_OPCODES+        case OP_goto16:+            diff = (int16_t)get_u16(bc_buf + pos + 1);+            pos_next = pos + 1 + diff;+            break;+        case OP_goto8:+            diff = (int8_t)bc_buf[pos + 1];+            pos_next = pos + 1 + diff;+            break;+        case OP_if_true8:+        case OP_if_false8:+            diff = (int8_t)bc_buf[pos + 1];+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))+                goto fail;+            break;+#endif+        case OP_if_true:+        case OP_if_false:+        case OP_catch:+            diff = get_u32(bc_buf + pos + 1);+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len))+                goto fail;+            break;+        case OP_gosub:+            diff = get_u32(bc_buf + pos + 1);+            if (ss_check(ctx, s, pos + 1 + diff, op, stack_len + 1))+                goto fail;+            break;+        case OP_with_get_var:+        case OP_with_delete_var:+            diff = get_u32(bc_buf + pos + 5);+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 1))+                goto fail;+            break;+        case OP_with_make_ref:+        case OP_with_get_ref:+        case OP_with_get_ref_undef:+            diff = get_u32(bc_buf + pos + 5);+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len + 2))+                goto fail;+            break;+        case OP_with_put_var:+            diff = get_u32(bc_buf + pos + 5);+            if (ss_check(ctx, s, pos + 5 + diff, op, stack_len - 1))+                goto fail;+            break;++        default:+            break;+        }+        if (ss_check(ctx, s, pos_next, op, stack_len))+            goto fail;+    done_insn: ;+    }+    js_free(ctx, s->stack_level_tab);+    js_free(ctx, s->pc_stack);+    *pstack_size = s->stack_len_max;+    return 0;+ fail:+    js_free(ctx, s->stack_level_tab);+    js_free(ctx, s->pc_stack);+    *pstack_size = 0;+    return -1;+}++static int add_module_variables(JSContext *ctx, JSFunctionDef *fd)+{+    int i, idx;+    JSModuleDef *m = fd->module;+    JSExportEntry *me;+    JSGlobalVar *hf;++    /* The imported global variables were added as closure variables+       in js_parse_import(). We add here the module global+       variables. */++    for(i = 0; i < fd->global_var_count; i++) {+        hf = &fd->global_vars[i];+        if (add_closure_var(ctx, fd, TRUE, FALSE, i, hf->var_name, hf->is_const,+                            hf->is_lexical, FALSE) < 0)+            return -1;+    }++    /* resolve the variable names of the local exports */+    for(i = 0; i < m->export_entries_count; i++) {+        me = &m->export_entries[i];+        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+            idx = find_closure_var(ctx, fd, me->local_name);+            if (idx < 0) {+                JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist",+                                        me->local_name);+                return -1;+            }+            me->u.local.var_idx = idx;+        }+    }+    return 0;+}++/* create a function object from a function definition. The function+   definition is freed. All the child functions are also created. It+   must be done this way to resolve all the variables. */+static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)+{+    JSValue func_obj;+    JSFunctionBytecode *b;+    struct list_head *el, *el1;+    int stack_size, scope, idx;+    int function_size, byte_code_offset, cpool_offset;+    int closure_var_offset, vardefs_offset;++    /* recompute scope linkage */+    for (scope = 0; scope < fd->scope_count; scope++) {+        fd->scopes[scope].first = -1;+    }+    if (fd->has_parameter_expressions) {+        /* special end of variable list marker for the argument scope */+        fd->scopes[ARG_SCOPE_INDEX].first = ARG_SCOPE_END;+    }+    for (idx = 0; idx < fd->var_count; idx++) {+        JSVarDef *vd = &fd->vars[idx];+        vd->scope_next = fd->scopes[vd->scope_level].first;+        fd->scopes[vd->scope_level].first = idx;+    }+    for (scope = 2; scope < fd->scope_count; scope++) {+        JSVarScope *sd = &fd->scopes[scope];+        if (sd->first < 0)+            sd->first = fd->scopes[sd->parent].first;+    }+    for (idx = 0; idx < fd->var_count; idx++) {+        JSVarDef *vd = &fd->vars[idx];+        if (vd->scope_next < 0 && vd->scope_level > 1) {+            scope = fd->scopes[vd->scope_level].parent;+            vd->scope_next = fd->scopes[scope].first;+        }+    }++    /* if the function contains an eval call, the closure variables+       are used to compile the eval and they must be ordered by scope,+       so it is necessary to create the closure variables before any+       other variable lookup is done. */+    if (fd->has_eval_call)+        add_eval_variables(ctx, fd);++    /* add the module global variables in the closure */+    if (fd->module) {+        if (add_module_variables(ctx, fd))+            goto fail;+    }++    /* first create all the child functions */+    list_for_each_safe(el, el1, &fd->child_list) {+        JSFunctionDef *fd1;+        int cpool_idx;++        fd1 = list_entry(el, JSFunctionDef, link);+        cpool_idx = fd1->parent_cpool_idx;+        func_obj = js_create_function(ctx, fd1);+        if (JS_IsException(func_obj))+            goto fail;+        /* save it in the constant pool */+        assert(cpool_idx >= 0);+        fd->cpool[cpool_idx] = func_obj;+    }++#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 4)+    if (!(fd->js_mode & JS_MODE_STRIP)) {+        printf("pass 1\n");+        dump_byte_code(ctx, 1, fd->byte_code.buf, fd->byte_code.size,+                       fd->args, fd->arg_count, fd->vars, fd->var_count,+                       fd->closure_var, fd->closure_var_count,+                       fd->cpool, fd->cpool_count, fd->source, fd->line_num,+                       fd->label_slots, NULL);+        printf("\n");+    }+#endif++    if (resolve_variables(ctx, fd))+        goto fail;++#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 2)+    if (!(fd->js_mode & JS_MODE_STRIP)) {+        printf("pass 2\n");+        dump_byte_code(ctx, 2, fd->byte_code.buf, fd->byte_code.size,+                       fd->args, fd->arg_count, fd->vars, fd->var_count,+                       fd->closure_var, fd->closure_var_count,+                       fd->cpool, fd->cpool_count, fd->source, fd->line_num,+                       fd->label_slots, NULL);+        printf("\n");+    }+#endif++    if (resolve_labels(ctx, fd))+        goto fail;++    if (compute_stack_size(ctx, fd, &stack_size) < 0)+        goto fail;++    if (fd->js_mode & JS_MODE_STRIP) {+        function_size = offsetof(JSFunctionBytecode, debug);+    } else {+        function_size = sizeof(*b);+    }+    cpool_offset = function_size;+    function_size += fd->cpool_count * sizeof(*fd->cpool);+    vardefs_offset = function_size;+    if (!(fd->js_mode & JS_MODE_STRIP) || fd->has_eval_call) {+        function_size += (fd->arg_count + fd->var_count) * sizeof(*b->vardefs);+    }+    closure_var_offset = function_size;+    function_size += fd->closure_var_count * sizeof(*fd->closure_var);+    byte_code_offset = function_size;+    function_size += fd->byte_code.size;++    b = js_mallocz(ctx, function_size);+    if (!b)+        goto fail;+    b->header.ref_count = 1;++    b->byte_code_buf = (void *)((uint8_t*)b + byte_code_offset);+    b->byte_code_len = fd->byte_code.size;+    memcpy(b->byte_code_buf, fd->byte_code.buf, fd->byte_code.size);+    js_free(ctx, fd->byte_code.buf);+    fd->byte_code.buf = NULL;++    b->func_name = fd->func_name;+    if (fd->arg_count + fd->var_count > 0) {+        if ((fd->js_mode & JS_MODE_STRIP) && !fd->has_eval_call) {+            /* Strip variable definitions not needed at runtime */+            int i;+            for(i = 0; i < fd->var_count; i++) {+                JS_FreeAtom(ctx, fd->vars[i].var_name);+            }+            for(i = 0; i < fd->arg_count; i++) {+                JS_FreeAtom(ctx, fd->args[i].var_name);+            }+            for(i = 0; i < fd->closure_var_count; i++) {+                JS_FreeAtom(ctx, fd->closure_var[i].var_name);+                fd->closure_var[i].var_name = JS_ATOM_NULL;+            }+        } else {+            b->vardefs = (void *)((uint8_t*)b + vardefs_offset);+            memcpy(b->vardefs, fd->args, fd->arg_count * sizeof(fd->args[0]));+            memcpy(b->vardefs + fd->arg_count, fd->vars, fd->var_count * sizeof(fd->vars[0]));+        }+        b->var_count = fd->var_count;+        b->arg_count = fd->arg_count;+        b->defined_arg_count = fd->defined_arg_count;+        js_free(ctx, fd->args);+        js_free(ctx, fd->vars);+    }+    b->cpool_count = fd->cpool_count;+    if (b->cpool_count) {+        b->cpool = (void *)((uint8_t*)b + cpool_offset);+        memcpy(b->cpool, fd->cpool, b->cpool_count * sizeof(*b->cpool));+    }+    js_free(ctx, fd->cpool);+    fd->cpool = NULL;++    b->stack_size = stack_size;++    if (fd->js_mode & JS_MODE_STRIP) {+        JS_FreeAtom(ctx, fd->filename);+        dbuf_free(&fd->pc2line);    // probably useless+    } else {+        /* XXX: source and pc2line info should be packed at the end of the+           JSFunctionBytecode structure, avoiding allocation overhead+         */+        b->has_debug = 1;+        b->debug.filename = fd->filename;+        b->debug.line_num = fd->line_num;++        //DynBuf pc2line;+        //compute_pc2line_info(fd, &pc2line);+        //js_free(ctx, fd->line_number_slots)+        b->debug.pc2line_buf = js_realloc(ctx, fd->pc2line.buf, fd->pc2line.size);+        if (!b->debug.pc2line_buf)+            b->debug.pc2line_buf = fd->pc2line.buf;+        b->debug.pc2line_len = fd->pc2line.size;+        b->debug.source = fd->source;+        b->debug.source_len = fd->source_len;+    }+    if (fd->scopes != fd->def_scope_array)+        js_free(ctx, fd->scopes);++    b->closure_var_count = fd->closure_var_count;+    if (b->closure_var_count) {+        b->closure_var = (void *)((uint8_t*)b + closure_var_offset);+        memcpy(b->closure_var, fd->closure_var, b->closure_var_count * sizeof(*b->closure_var));+    }+    js_free(ctx, fd->closure_var);+    fd->closure_var = NULL;++    b->has_prototype = fd->has_prototype;+    b->has_simple_parameter_list = fd->has_simple_parameter_list;+    b->js_mode = fd->js_mode;+    b->is_derived_class_constructor = fd->is_derived_class_constructor;+    b->func_kind = fd->func_kind;+    b->need_home_object = (fd->home_object_var_idx >= 0 ||+                           fd->need_home_object);+    b->new_target_allowed = fd->new_target_allowed;+    b->super_call_allowed = fd->super_call_allowed;+    b->super_allowed = fd->super_allowed;+    b->arguments_allowed = fd->arguments_allowed;+    b->backtrace_barrier = fd->backtrace_barrier;+    b->realm = JS_DupContext(ctx);++    add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);+    +#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 1)+    if (!(fd->js_mode & JS_MODE_STRIP)) {+        js_dump_function_bytecode(ctx, b);+    }+#endif++    if (fd->parent) {+        /* remove from parent list */+        list_del(&fd->link);+    }++    js_free(ctx, fd);+    return JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);+ fail:+    js_free_function_def(ctx, fd);+    return JS_EXCEPTION;+}++static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)+{+    int i;++#if 0+    {+        char buf[ATOM_GET_STR_BUF_SIZE];+        printf("freeing %s\n",+               JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));+    }+#endif+    free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE);++    if (b->vardefs) {+        for(i = 0; i < b->arg_count + b->var_count; i++) {+            JS_FreeAtomRT(rt, b->vardefs[i].var_name);+        }+    }+    for(i = 0; i < b->cpool_count; i++)+        JS_FreeValueRT(rt, b->cpool[i]);++    for(i = 0; i < b->closure_var_count; i++) {+        JSClosureVar *cv = &b->closure_var[i];+        JS_FreeAtomRT(rt, cv->var_name);+    }+    if (b->realm)+        JS_FreeContext(b->realm);++    JS_FreeAtomRT(rt, b->func_name);+    if (b->has_debug) {+        JS_FreeAtomRT(rt, b->debug.filename);+        js_free_rt(rt, b->debug.pc2line_buf);+        js_free_rt(rt, b->debug.source);+    }++    remove_gc_object(&b->header);+    if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) {+        list_add_tail(&b->header.link, &rt->gc_zero_ref_count_list);+    } else {+        js_free_rt(rt, b);+    }+}++static __exception int js_parse_directives(JSParseState *s)+{+    char str[20];+    JSParsePos pos;+    BOOL has_semi;++    if (s->token.val != TOK_STRING)+        return 0;++    js_parse_get_pos(s, &pos);++    while(s->token.val == TOK_STRING) {+        /* Copy actual source string representation */+        snprintf(str, sizeof str, "%.*s",+                 (int)(s->buf_ptr - s->token.ptr - 2), s->token.ptr + 1);++        if (next_token(s))+            return -1;++        has_semi = FALSE;+        switch (s->token.val) {+        case ';':+            if (next_token(s))+                return -1;+            has_semi = TRUE;+            break;+        case '}':+        case TOK_EOF:+            has_semi = TRUE;+            break;+        case TOK_NUMBER:+        case TOK_STRING:+        case TOK_TEMPLATE:+        case TOK_IDENT:+        case TOK_REGEXP:+        case TOK_DEC:+        case TOK_INC:+        case TOK_NULL:+        case TOK_FALSE:+        case TOK_TRUE:+        case TOK_IF:+        case TOK_RETURN:+        case TOK_VAR:+        case TOK_THIS:+        case TOK_DELETE:+        case TOK_TYPEOF:+        case TOK_NEW:+        case TOK_DO:+        case TOK_WHILE:+        case TOK_FOR:+        case TOK_SWITCH:+        case TOK_THROW:+        case TOK_TRY:+        case TOK_FUNCTION:+        case TOK_DEBUGGER:+        case TOK_WITH:+        case TOK_CLASS:+        case TOK_CONST:+        case TOK_ENUM:+        case TOK_EXPORT:+        case TOK_IMPORT:+        case TOK_SUPER:+        case TOK_INTERFACE:+        case TOK_LET:+        case TOK_PACKAGE:+        case TOK_PRIVATE:+        case TOK_PROTECTED:+        case TOK_PUBLIC:+        case TOK_STATIC:+            /* automatic insertion of ';' */+            if (s->got_lf)+                has_semi = TRUE;+            break;+        default:+            break;+        }+        if (!has_semi)+            break;+        if (!strcmp(str, "use strict")) {+            s->cur_func->has_use_strict = TRUE;+            s->cur_func->js_mode |= JS_MODE_STRICT;+        }+#if !defined(DUMP_BYTECODE) || !(DUMP_BYTECODE & 8)+        else if (!strcmp(str, "use strip")) {+            s->cur_func->js_mode |= JS_MODE_STRIP;+        }+#endif+#ifdef CONFIG_BIGNUM+        else if (s->ctx->bignum_ext && !strcmp(str, "use math")) {+            s->cur_func->js_mode |= JS_MODE_MATH;+        }+#endif+    }+    return js_parse_seek_token(s, &pos);+}++static int js_parse_function_check_names(JSParseState *s, JSFunctionDef *fd,+                                         JSAtom func_name)+{+    JSAtom name;+    int i, idx;++    if (fd->js_mode & JS_MODE_STRICT) {+        if (!fd->has_simple_parameter_list && fd->has_use_strict) {+            return js_parse_error(s, "\"use strict\" not allowed in function with default or destructuring parameter");+        }+        if (func_name == JS_ATOM_eval || func_name == JS_ATOM_arguments) {+            return js_parse_error(s, "invalid function name in strict code");+        }+        for (idx = 0; idx < fd->arg_count; idx++) {+            name = fd->args[idx].var_name;++            if (name == JS_ATOM_eval || name == JS_ATOM_arguments) {+                return js_parse_error(s, "invalid argument name in strict code");+            }+        }+    }+    /* check async_generator case */+    if ((fd->js_mode & JS_MODE_STRICT)+    ||  !fd->has_simple_parameter_list+    ||  (fd->func_type == JS_PARSE_FUNC_METHOD && fd->func_kind == JS_FUNC_ASYNC)+    ||  fd->func_type == JS_PARSE_FUNC_ARROW+    ||  fd->func_type == JS_PARSE_FUNC_METHOD) {+        for (idx = 0; idx < fd->arg_count; idx++) {+            name = fd->args[idx].var_name;+            if (name != JS_ATOM_NULL) {+                for (i = 0; i < idx; i++) {+                    if (fd->args[i].var_name == name)+                        goto duplicate;+                }+                /* Check if argument name duplicates a destructuring parameter */+                /* XXX: should have a flag for such variables */+                for (i = 0; i < fd->var_count; i++) {+                    if (fd->vars[i].var_name == name &&+                        fd->vars[i].scope_level == 0)+                        goto duplicate;+                }+            }+        }+    }+    return 0;++duplicate:+    return js_parse_error(s, "duplicate argument names not allowed in this context");+}++/* create a function to initialize class fields */+static JSFunctionDef *js_parse_function_class_fields_init(JSParseState *s)+{+    JSFunctionDef *fd;+    +    fd = js_new_function_def(s->ctx, s->cur_func, FALSE, FALSE,+                             s->filename, 0);+    if (!fd)+        return NULL;+    fd->func_name = JS_ATOM_NULL;+    fd->has_prototype = FALSE;+    fd->has_home_object = TRUE;+    +    fd->has_arguments_binding = FALSE;+    fd->has_this_binding = TRUE;+    fd->is_derived_class_constructor = FALSE;+    fd->new_target_allowed = TRUE;+    fd->super_call_allowed = FALSE;+    fd->super_allowed = fd->has_home_object;+    fd->arguments_allowed = FALSE;+    +    fd->func_kind = JS_FUNC_NORMAL;+    fd->func_type = JS_PARSE_FUNC_METHOD;+    return fd;+}++/* func_name must be JS_ATOM_NULL for JS_PARSE_FUNC_STATEMENT and+   JS_PARSE_FUNC_EXPR, JS_PARSE_FUNC_ARROW and JS_PARSE_FUNC_VAR */+static __exception int js_parse_function_decl2(JSParseState *s,+                                               JSParseFunctionEnum func_type,+                                               JSFunctionKindEnum func_kind,+                                               JSAtom func_name,+                                               const uint8_t *ptr,+                                               int function_line_num,+                                               JSParseExportEnum export_flag,+                                               JSFunctionDef **pfd)+{+    JSContext *ctx = s->ctx;+    JSFunctionDef *fd = s->cur_func;+    BOOL is_expr;+    int func_idx, lexical_func_idx = -1;+    BOOL has_opt_arg;+    BOOL create_func_var = FALSE;++    is_expr = (func_type != JS_PARSE_FUNC_STATEMENT &&+               func_type != JS_PARSE_FUNC_VAR);++    if (func_type == JS_PARSE_FUNC_STATEMENT ||+        func_type == JS_PARSE_FUNC_VAR ||+        func_type == JS_PARSE_FUNC_EXPR) {+        if (func_kind == JS_FUNC_NORMAL &&+            token_is_pseudo_keyword(s, JS_ATOM_async) &&+            peek_token(s, TRUE) != '\n') {+            if (next_token(s))+                return -1;+            func_kind = JS_FUNC_ASYNC;+        }+        if (next_token(s))+            return -1;+        if (s->token.val == '*') {+            if (next_token(s))+                return -1;+            func_kind |= JS_FUNC_GENERATOR;+        }++        if (s->token.val == TOK_IDENT) {+            if (s->token.u.ident.is_reserved ||+                (s->token.u.ident.atom == JS_ATOM_yield &&+                 func_type == JS_PARSE_FUNC_EXPR &&+                 (func_kind & JS_FUNC_GENERATOR)) ||+                (s->token.u.ident.atom == JS_ATOM_await &&+                 func_type == JS_PARSE_FUNC_EXPR &&+                 (func_kind & JS_FUNC_ASYNC))) {+                return js_parse_error_reserved_identifier(s);+            }+        }+        if (s->token.val == TOK_IDENT ||+            (((s->token.val == TOK_YIELD && !(fd->js_mode & JS_MODE_STRICT)) ||+             (s->token.val == TOK_AWAIT && !s->is_module)) &&+             func_type == JS_PARSE_FUNC_EXPR)) {+            func_name = JS_DupAtom(ctx, s->token.u.ident.atom);+            if (next_token(s)) {+                JS_FreeAtom(ctx, func_name);+                return -1;+            }+        } else {+            if (func_type != JS_PARSE_FUNC_EXPR &&+                export_flag != JS_PARSE_EXPORT_DEFAULT) {+                return js_parse_error(s, "function name expected");+            }+        }+    } else if (func_type != JS_PARSE_FUNC_ARROW) {+        func_name = JS_DupAtom(ctx, func_name);+    }++    if (fd->is_eval && fd->eval_type == JS_EVAL_TYPE_MODULE &&+        (func_type == JS_PARSE_FUNC_STATEMENT || func_type == JS_PARSE_FUNC_VAR)) {+        JSGlobalVar *hf;+        hf = find_global_var(fd, func_name);+        /* XXX: should check scope chain */+        if (hf && hf->scope_level == fd->scope_level) {+            js_parse_error(s, "invalid redefinition of global identifier in module code");+            JS_FreeAtom(ctx, func_name);+            return -1;+        }+    }++    if (func_type == JS_PARSE_FUNC_VAR) {+        if (!(fd->js_mode & JS_MODE_STRICT)+        && func_kind == JS_FUNC_NORMAL+        &&  find_lexical_decl(ctx, fd, func_name, fd->scope_first, FALSE) < 0+        &&  !((func_idx = find_var(ctx, fd, func_name)) >= 0 && (func_idx & ARGUMENT_VAR_OFFSET))+        &&  !(func_name == JS_ATOM_arguments && fd->has_arguments_binding)) {+            create_func_var = TRUE;+        }+        /* Create the lexical name here so that the function closure+           contains it */+        if (fd->is_eval &&+            (fd->eval_type == JS_EVAL_TYPE_GLOBAL ||+             fd->eval_type == JS_EVAL_TYPE_MODULE) &&+            fd->scope_level == fd->body_scope) {+            /* avoid creating a lexical variable in the global+               scope. XXX: check annex B */+            JSGlobalVar *hf;+            hf = find_global_var(fd, func_name);+            /* XXX: should check scope chain */+            if (hf && hf->scope_level == fd->scope_level) {+                js_parse_error(s, "invalid redefinition of global identifier");+                JS_FreeAtom(ctx, func_name);+                return -1;+            }+        } else {+            /* Always create a lexical name, fail if at the same scope as+               existing name */+            /* Lexical variable will be initialized upon entering scope */+            lexical_func_idx = define_var(s, fd, func_name,+                                          func_kind != JS_FUNC_NORMAL ?+                                          JS_VAR_DEF_NEW_FUNCTION_DECL :+                                          JS_VAR_DEF_FUNCTION_DECL);+            if (lexical_func_idx < 0) {+                JS_FreeAtom(ctx, func_name);+                return -1;+            }+        }+    }++    fd = js_new_function_def(ctx, fd, FALSE, is_expr,+                             s->filename, function_line_num);+    if (!fd) {+        JS_FreeAtom(ctx, func_name);+        return -1;+    }+    if (pfd)+        *pfd = fd;+    s->cur_func = fd;+    fd->func_name = func_name;+    /* XXX: test !fd->is_generator is always false */+    fd->has_prototype = (func_type == JS_PARSE_FUNC_STATEMENT ||+                         func_type == JS_PARSE_FUNC_VAR ||+                         func_type == JS_PARSE_FUNC_EXPR) &&+                        func_kind == JS_FUNC_NORMAL;+    fd->has_home_object = (func_type == JS_PARSE_FUNC_METHOD ||+                           func_type == JS_PARSE_FUNC_GETTER ||+                           func_type == JS_PARSE_FUNC_SETTER ||+                           func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||+                           func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);+    fd->has_arguments_binding = (func_type != JS_PARSE_FUNC_ARROW);+    fd->has_this_binding = fd->has_arguments_binding;+    fd->is_derived_class_constructor = (func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR);+    if (func_type == JS_PARSE_FUNC_ARROW) {+        fd->new_target_allowed = fd->parent->new_target_allowed;+        fd->super_call_allowed = fd->parent->super_call_allowed;+        fd->super_allowed = fd->parent->super_allowed;+        fd->arguments_allowed = fd->parent->arguments_allowed;+    } else {+        fd->new_target_allowed = TRUE;+        fd->super_call_allowed = fd->is_derived_class_constructor;+        fd->super_allowed = fd->has_home_object;+        fd->arguments_allowed = TRUE;+    }++    /* fd->in_function_body == FALSE prevents yield/await during the parsing+       of the arguments in generator/async functions. They are parsed as+       regular identifiers for other function kinds. */+    fd->func_kind = func_kind;+    fd->func_type = func_type;++    if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR ||+        func_type == JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR) {+        /* error if not invoked as a constructor */+        emit_op(s, OP_check_ctor);+    }++    if (func_type == JS_PARSE_FUNC_CLASS_CONSTRUCTOR) {+        emit_class_field_init(s);+    }+    +    /* parse arguments */+    fd->has_simple_parameter_list = TRUE;+    fd->has_parameter_expressions = FALSE;+    has_opt_arg = FALSE;+    if (func_type == JS_PARSE_FUNC_ARROW && s->token.val == TOK_IDENT) {+        JSAtom name;+        if (s->token.u.ident.is_reserved) {+            js_parse_error_reserved_identifier(s);+            goto fail;+        }+        name = s->token.u.ident.atom;+        if (add_arg(ctx, fd, name) < 0)+            goto fail;+        fd->defined_arg_count = 1;+    } else {+        if (s->token.val == '(') {+            int skip_bits;+            /* if there is an '=' inside the parameter list, we+               consider there is a parameter expression inside */+            js_parse_skip_parens_token(s, &skip_bits, FALSE);+            if (skip_bits & SKIP_HAS_ASSIGNMENT)+                fd->has_parameter_expressions = TRUE;+            if (next_token(s))+                goto fail;+        } else {+            if (js_parse_expect(s, '('))+                goto fail;+        }++        if (fd->has_parameter_expressions) {+            fd->scope_level = -1; /* force no parent scope */+            if (push_scope(s) < 0)+                return -1;+        }+        +        while (s->token.val != ')') {+            JSAtom name;+            BOOL rest = FALSE;+            int idx, has_initializer;++            if (s->token.val == TOK_ELLIPSIS) {+                fd->has_simple_parameter_list = FALSE;+                rest = TRUE;+                if (next_token(s))+                    goto fail;+            }+            if (s->token.val == '[' || s->token.val == '{') {+                fd->has_simple_parameter_list = FALSE;+                if (rest) {+                    emit_op(s, OP_rest);+                    emit_u16(s, fd->arg_count);+                } else {+                    /* unnamed arg for destructuring */+                    idx = add_arg(ctx, fd, JS_ATOM_NULL);+                    emit_op(s, OP_get_arg);+                    emit_u16(s, idx);+                }+                has_initializer = js_parse_destructuring_element(s, fd->has_parameter_expressions ? TOK_LET : TOK_VAR, 1, TRUE, -1, TRUE);+                if (has_initializer < 0)+                    goto fail;+                if (has_initializer)+                    has_opt_arg = TRUE;+                if (!has_opt_arg)+                    fd->defined_arg_count++;+            } else if (s->token.val == TOK_IDENT) {+                if (s->token.u.ident.is_reserved) {+                    js_parse_error_reserved_identifier(s);+                    goto fail;+                }+                name = s->token.u.ident.atom;+                if (name == JS_ATOM_yield && fd->func_kind == JS_FUNC_GENERATOR) {+                    js_parse_error_reserved_identifier(s);+                    goto fail;+                }+                if (fd->has_parameter_expressions) {+                    if (define_var(s, fd, name, JS_VAR_DEF_LET) < 0)+                        goto fail;+                }+                /* XXX: could avoid allocating an argument if rest is true */+                idx = add_arg(ctx, fd, name);+                if (idx < 0)+                    goto fail;+                if (next_token(s))+                    goto fail;+                if (rest) {+                    emit_op(s, OP_rest);+                    emit_u16(s, idx);+                    if (fd->has_parameter_expressions) {+                        emit_op(s, OP_dup);+                        emit_op(s, OP_scope_put_var_init);+                        emit_atom(s, name);+                        emit_u16(s, fd->scope_level);+                    }+                    emit_op(s, OP_put_arg);+                    emit_u16(s, idx);+                    fd->has_simple_parameter_list = FALSE;+                    has_opt_arg = TRUE;+                } else if (s->token.val == '=') {+                    int label;+                    +                    fd->has_simple_parameter_list = FALSE;+                    has_opt_arg = TRUE;++                    if (next_token(s))+                        goto fail;++                    label = new_label(s);+                    emit_op(s, OP_get_arg);+                    emit_u16(s, idx);+                    emit_op(s, OP_dup);+                    emit_op(s, OP_undefined);+                    emit_op(s, OP_strict_eq);+                    emit_goto(s, OP_if_false, label);+                    emit_op(s, OP_drop);+                    if (js_parse_assign_expr(s))+                        goto fail;+                    set_object_name(s, name);+                    emit_op(s, OP_dup);+                    emit_op(s, OP_put_arg);+                    emit_u16(s, idx);+                    emit_label(s, label);+                    emit_op(s, OP_scope_put_var_init);+                    emit_atom(s, name);+                    emit_u16(s, fd->scope_level);+                } else {+                    if (!has_opt_arg) {+                        fd->defined_arg_count++;+                    }+                    if (fd->has_parameter_expressions) {+                        /* copy the argument to the argument scope */+                        emit_op(s, OP_get_arg);+                        emit_u16(s, idx);+                        emit_op(s, OP_scope_put_var_init);+                        emit_atom(s, name);+                        emit_u16(s, fd->scope_level);+                    }+                }+            } else {+                js_parse_error(s, "missing formal parameter");+                goto fail;+            }+            if (rest && s->token.val != ')') {+                js_parse_expect(s, ')');+                goto fail;+            }+            if (s->token.val == ')')+                break;+            if (js_parse_expect(s, ','))+                goto fail;+        }+        if ((func_type == JS_PARSE_FUNC_GETTER && fd->arg_count != 0) ||+            (func_type == JS_PARSE_FUNC_SETTER && fd->arg_count != 1)) {+            js_parse_error(s, "invalid number of arguments for getter or setter");+            goto fail;+        }+    }++    if (fd->has_parameter_expressions) {+        int idx;++        /* Copy the variables in the argument scope to the variable+           scope (see FunctionDeclarationInstantiation() in spec). The+           normal arguments are already present, so no need to copy+           them. */+        idx = fd->scopes[fd->scope_level].first;+        while (idx >= 0) {+            JSVarDef *vd = &fd->vars[idx];+            if (vd->scope_level != fd->scope_level)+                break;+            if (find_var(ctx, fd, vd->var_name) < 0) {+                if (add_var(ctx, fd, vd->var_name) < 0)+                    goto fail;+                vd = &fd->vars[idx]; /* fd->vars may have been reallocated */+                emit_op(s, OP_scope_get_var);+                emit_atom(s, vd->var_name);+                emit_u16(s, fd->scope_level);+                emit_op(s, OP_scope_put_var);+                emit_atom(s, vd->var_name);+                emit_u16(s, 0);+            }+            idx = vd->scope_next;+        }+        +        /* the argument scope has no parent, hence we don't use pop_scope(s) */+        emit_op(s, OP_leave_scope);+        emit_u16(s, fd->scope_level);++        /* set the variable scope as the current scope */+        fd->scope_level = 0;+        fd->scope_first = fd->scopes[fd->scope_level].first;+    }+    +    if (next_token(s))+        goto fail;++    /* generator function: yield after the parameters are evaluated */+    if (func_kind == JS_FUNC_GENERATOR ||+        func_kind == JS_FUNC_ASYNC_GENERATOR)+        emit_op(s, OP_initial_yield);++    /* in generators, yield expression is forbidden during the parsing+       of the arguments */+    fd->in_function_body = TRUE;+    push_scope(s);  /* enter body scope */+    fd->body_scope = fd->scope_level;++    if (s->token.val == TOK_ARROW) {+        if (next_token(s))+            goto fail;++        if (s->token.val != '{') {+            if (js_parse_function_check_names(s, fd, func_name))+                goto fail;++            if (js_parse_assign_expr(s))+                goto fail;++            if (func_kind != JS_FUNC_NORMAL)+                emit_op(s, OP_return_async);+            else+                emit_op(s, OP_return);++            if (!(fd->js_mode & JS_MODE_STRIP)) {+                /* save the function source code */+                /* the end of the function source code is after the last+                   token of the function source stored into s->last_ptr */+                fd->source_len = s->last_ptr - ptr;+                fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);+                if (!fd->source)+                    goto fail;+            }+            goto done;+        }+    }++    if (js_parse_expect(s, '{'))+        goto fail;++    if (js_parse_directives(s))+        goto fail;++    /* in strict_mode, check function and argument names */+    if (js_parse_function_check_names(s, fd, func_name))+        goto fail;++    while (s->token.val != '}') {+        if (js_parse_source_element(s))+            goto fail;+    }+    if (!(fd->js_mode & JS_MODE_STRIP)) {+        /* save the function source code */+        fd->source_len = s->buf_ptr - ptr;+        fd->source = js_strndup(ctx, (const char *)ptr, fd->source_len);+        if (!fd->source)+            goto fail;+    }++    if (next_token(s)) {+        /* consume the '}' */+        goto fail;+    }++    /* in case there is no return, add one */+    if (js_is_live_code(s)) {+        emit_return(s, FALSE);+    }+done:+    s->cur_func = fd->parent;++    /* create the function object */+    {+        int idx;+        JSAtom func_name = fd->func_name;++        /* the real object will be set at the end of the compilation */+        idx = cpool_add(s, JS_NULL);+        fd->parent_cpool_idx = idx;++        if (is_expr) {+            /* for constructors, no code needs to be generated here */+            if (func_type != JS_PARSE_FUNC_CLASS_CONSTRUCTOR &&+                func_type != JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR) {+                /* OP_fclosure creates the function object from the bytecode+                   and adds the scope information */+                emit_op(s, OP_fclosure);+                emit_u32(s, idx);+                if (func_name == JS_ATOM_NULL) {+                    emit_op(s, OP_set_name);+                    emit_u32(s, JS_ATOM_NULL);+                }+            }+        } else if (func_type == JS_PARSE_FUNC_VAR) {+            emit_op(s, OP_fclosure);+            emit_u32(s, idx);+            if (create_func_var) {+                if (s->cur_func->is_global_var) {+                    JSGlobalVar *hf;+                    /* the global variable must be defined at the start of the+                       function */+                    hf = add_global_var(ctx, s->cur_func, func_name);+                    if (!hf)+                        goto fail;+                    /* it is considered as defined at the top level+                       (needed for annex B.3.3.4 and B.3.3.5+                       checks) */+                    hf->scope_level = 0; +                    hf->force_init = ((s->cur_func->js_mode & JS_MODE_STRICT) != 0);+                    /* store directly into global var, bypass lexical scope */+                    emit_op(s, OP_dup);+                    emit_op(s, OP_scope_put_var);+                    emit_atom(s, func_name);+                    emit_u16(s, 0);+                } else {+                    /* do not call define_var to bypass lexical scope check */+                    func_idx = find_var(ctx, s->cur_func, func_name);+                    if (func_idx < 0) {+                        func_idx = add_var(ctx, s->cur_func, func_name);+                        if (func_idx < 0)+                            goto fail;+                    }+                    /* store directly into local var, bypass lexical catch scope */+                    emit_op(s, OP_dup);+                    emit_op(s, OP_scope_put_var);+                    emit_atom(s, func_name);+                    emit_u16(s, 0);+                }+            }+            if (lexical_func_idx >= 0) {+                /* lexical variable will be initialized upon entering scope */+                s->cur_func->vars[lexical_func_idx].func_pool_idx = idx;+                emit_op(s, OP_drop);+            } else {+                /* store function object into its lexical name */+                /* XXX: could use OP_put_loc directly */+                emit_op(s, OP_scope_put_var_init);+                emit_atom(s, func_name);+                emit_u16(s, s->cur_func->scope_level);+            }+        } else {+            if (!s->cur_func->is_global_var) {+                int var_idx = define_var(s, s->cur_func, func_name, JS_VAR_DEF_VAR);++                if (var_idx < 0)+                    goto fail;+                /* the variable will be assigned at the top of the function */+                if (var_idx & ARGUMENT_VAR_OFFSET) {+                    s->cur_func->args[var_idx - ARGUMENT_VAR_OFFSET].func_pool_idx = idx;+                } else {+                    s->cur_func->vars[var_idx].func_pool_idx = idx;+                }+            } else {+                JSAtom func_var_name;+                JSGlobalVar *hf;+                if (func_name == JS_ATOM_NULL)+                    func_var_name = JS_ATOM__default_; /* export default */+                else+                    func_var_name = func_name;+                /* the variable will be assigned at the top of the function */+                hf = add_global_var(ctx, s->cur_func, func_var_name);+                if (!hf)+                    goto fail;+                hf->cpool_idx = idx;+                if (export_flag != JS_PARSE_EXPORT_NONE) {+                    if (!add_export_entry(s, s->cur_func->module, func_var_name,+                                          export_flag == JS_PARSE_EXPORT_NAMED ? func_var_name : JS_ATOM_default, JS_EXPORT_TYPE_LOCAL))+                        goto fail;+                }+            }+        }+    }+    return 0;+ fail:+    s->cur_func = fd->parent;+    js_free_function_def(ctx, fd);+    if (pfd)+        *pfd = NULL;+    return -1;+}++static __exception int js_parse_function_decl(JSParseState *s,+                                              JSParseFunctionEnum func_type,+                                              JSFunctionKindEnum func_kind,+                                              JSAtom func_name,+                                              const uint8_t *ptr,+                                              int function_line_num)+{+    return js_parse_function_decl2(s, func_type, func_kind, func_name, ptr,+                                   function_line_num, JS_PARSE_EXPORT_NONE,+                                   NULL);+}++static __exception int js_parse_program(JSParseState *s)+{+    JSFunctionDef *fd = s->cur_func;+    int idx;++    if (next_token(s))+        return -1;++    if (js_parse_directives(s))+        return -1;++    fd->is_global_var = (fd->eval_type == JS_EVAL_TYPE_GLOBAL) ||+        (fd->eval_type == JS_EVAL_TYPE_MODULE) ||+        !(fd->js_mode & JS_MODE_STRICT);++    if (!s->is_module) {+        /* hidden variable for the return value */+        fd->eval_ret_idx = idx = add_var(s->ctx, fd, JS_ATOM__ret_);+        if (idx < 0)+            return -1;+    }++    while (s->token.val != TOK_EOF) {+        if (js_parse_source_element(s))+            return -1;+    }++    if (!s->is_module) {+        /* return the value of the hidden variable eval_ret_idx  */+        emit_op(s, OP_get_loc);+        emit_u16(s, fd->eval_ret_idx);++        emit_op(s, OP_return);+    } else {+        emit_op(s, OP_return_undef);+    }++    return 0;+}++static void js_parse_init(JSContext *ctx, JSParseState *s,+                          const char *input, size_t input_len,+                          const char *filename)+{+    memset(s, 0, sizeof(*s));+    s->ctx = ctx;+    s->filename = filename;+    s->line_num = 1;+    s->buf_ptr = (const uint8_t *)input;+    s->buf_end = s->buf_ptr + input_len;+    s->token.val = ' ';+    s->token.line_num = 1;+}++static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj,+                                       JSValueConst this_obj,+                                       JSVarRef **var_refs, JSStackFrame *sf)+{+    JSValue ret_val;+    uint32_t tag;++    tag = JS_VALUE_GET_TAG(fun_obj);+    if (tag == JS_TAG_FUNCTION_BYTECODE) {+        fun_obj = js_closure(ctx, fun_obj, var_refs, sf);+        ret_val = JS_CallFree(ctx, fun_obj, this_obj, 0, NULL);+    } else if (tag == JS_TAG_MODULE) {+        JSModuleDef *m;+        m = JS_VALUE_GET_PTR(fun_obj);+        /* the module refcount should be >= 2 */+        JS_FreeValue(ctx, fun_obj);+        if (js_create_module_function(ctx, m) < 0)+            goto fail;+        if (js_link_module(ctx, m) < 0)+            goto fail;+        ret_val = js_evaluate_module(ctx, m);+        if (JS_IsException(ret_val)) {+        fail:+            js_free_modules(ctx, JS_FREE_MODULE_NOT_EVALUATED);+            return JS_EXCEPTION;+        }+    } else {+        JS_FreeValue(ctx, fun_obj);+        ret_val = JS_ThrowTypeError(ctx, "bytecode function expected");+    }+    return ret_val;+}++JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj)+{+    return JS_EvalFunctionInternal(ctx, fun_obj, ctx->global_obj, NULL, NULL);+}++static void skip_shebang(JSParseState *s)+{+    const uint8_t *p = s->buf_ptr;+    int c;++    if (p[0] == '#' && p[1] == '!') {+        p += 2;+        while (p < s->buf_end) {+            if (*p == '\n' || *p == '\r') {+                break;+            } else if (*p >= 0x80) {+                c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);+                if (c == CP_LS || c == CP_PS) {+                    break;+                } else if (c == -1) {+                    p++; /* skip invalid UTF-8 */+                }+            } else {+                p++;+            }+        }+        s->buf_ptr = p;+    }+}++/* 'input' must be zero terminated i.e. input[input_len] = '\0'. */+static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,+                                 const char *input, size_t input_len,+                                 const char *filename, int flags, int scope_idx)+{+    JSParseState s1, *s = &s1;+    int err, js_mode, eval_type;+    JSValue fun_obj, ret_val;+    JSStackFrame *sf;+    JSVarRef **var_refs;+    JSFunctionBytecode *b;+    JSFunctionDef *fd;+    JSModuleDef *m;++    js_parse_init(ctx, s, input, input_len, filename);+    skip_shebang(s);++    eval_type = flags & JS_EVAL_TYPE_MASK;+    m = NULL;+    if (eval_type == JS_EVAL_TYPE_DIRECT) {+        JSObject *p;+        sf = ctx->rt->current_stack_frame;+        assert(sf != NULL);+        assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);+        p = JS_VALUE_GET_OBJ(sf->cur_func);+        assert(js_class_has_bytecode(p->class_id));+        b = p->u.func.function_bytecode;+        var_refs = p->u.func.var_refs;+        js_mode = b->js_mode;+    } else {+        sf = NULL;+        b = NULL;+        var_refs = NULL;+        js_mode = 0;+        if (flags & JS_EVAL_FLAG_STRICT)+            js_mode |= JS_MODE_STRICT;+        if (flags & JS_EVAL_FLAG_STRIP)+            js_mode |= JS_MODE_STRIP;+        if (eval_type == JS_EVAL_TYPE_MODULE) {+            JSAtom module_name = JS_NewAtom(ctx, filename);+            if (module_name == JS_ATOM_NULL)+                return JS_EXCEPTION;+            m = js_new_module_def(ctx, module_name);+            if (!m)+                return JS_EXCEPTION;+            js_mode |= JS_MODE_STRICT;+        }+    }+    fd = js_new_function_def(ctx, NULL, TRUE, FALSE, filename, 1);+    if (!fd)+        goto fail1;+    s->cur_func = fd;+    fd->eval_type = eval_type;+    fd->has_this_binding = (eval_type != JS_EVAL_TYPE_DIRECT);+    fd->backtrace_barrier = ((flags & JS_EVAL_FLAG_BACKTRACE_BARRIER) != 0);+    if (eval_type == JS_EVAL_TYPE_DIRECT) {+        fd->new_target_allowed = b->new_target_allowed;+        fd->super_call_allowed = b->super_call_allowed;+        fd->super_allowed = b->super_allowed;+        fd->arguments_allowed = b->arguments_allowed;+    } else {+        fd->new_target_allowed = FALSE;+        fd->super_call_allowed = FALSE;+        fd->super_allowed = FALSE;+        fd->arguments_allowed = TRUE;+    }+    fd->js_mode = js_mode;+    fd->func_name = JS_DupAtom(ctx, JS_ATOM__eval_);+    if (b) {+        if (add_closure_variables(ctx, fd, b, scope_idx))+            goto fail;+    }+    fd->module = m;+    s->is_module = (m != NULL);+    s->allow_html_comments = !s->is_module;++    push_scope(s); /* body scope */+    fd->body_scope = fd->scope_level;+    +    err = js_parse_program(s);+    if (err) {+    fail:+        free_token(s, &s->token);+        js_free_function_def(ctx, fd);+        goto fail1;+    }++    /* create the function object and all the enclosed functions */+    fun_obj = js_create_function(ctx, fd);+    if (JS_IsException(fun_obj))+        goto fail1;+    /* Could add a flag to avoid resolution if necessary */+    if (m) {+        m->func_obj = fun_obj;+        if (js_resolve_module(ctx, m) < 0)+            goto fail1;+        fun_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));+    }+    if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {+        ret_val = fun_obj;+    } else {+        ret_val = JS_EvalFunctionInternal(ctx, fun_obj, this_obj, var_refs, sf);+    }+    return ret_val;+ fail1:+    /* XXX: should free all the unresolved dependencies */+    if (m)+        js_free_module_def(ctx, m);+    return JS_EXCEPTION;+}++/* the indirection is needed to make 'eval' optional */+static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,+                               const char *input, size_t input_len,+                               const char *filename, int flags, int scope_idx)+{+    if (unlikely(!ctx->eval_internal)) {+        return JS_ThrowTypeError(ctx, "eval is not supported");+    }+    return ctx->eval_internal(ctx, this_obj, input, input_len, filename,+                              flags, scope_idx);+}++static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,+                             JSValueConst val, int flags, int scope_idx)+{+    JSValue ret;+    const char *str;+    size_t len;++    if (!JS_IsString(val))+        return JS_DupValue(ctx, val);+    str = JS_ToCStringLen(ctx, &len, val);+    if (!str)+        return JS_EXCEPTION;+    ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", flags, scope_idx);+    JS_FreeCString(ctx, str);+    return ret;++}++JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,+                    const char *input, size_t input_len,+                    const char *filename, int eval_flags)+{+    int eval_type = eval_flags & JS_EVAL_TYPE_MASK;+    JSValue ret;++    assert(eval_type == JS_EVAL_TYPE_GLOBAL ||+           eval_type == JS_EVAL_TYPE_MODULE);+    ret = JS_EvalInternal(ctx, this_obj, input, input_len, filename,+                          eval_flags, -1);+    return ret;+}++JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,+                const char *filename, int eval_flags)+{+    return JS_EvalThis(ctx, ctx->global_obj, input, input_len, filename,+                       eval_flags);+}++int JS_ResolveModule(JSContext *ctx, JSValueConst obj)+{+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {+        JSModuleDef *m = JS_VALUE_GET_PTR(obj);+        if (js_resolve_module(ctx, m) < 0) {+            js_free_modules(ctx, JS_FREE_MODULE_NOT_RESOLVED);+            return -1;+        }+    }+    return 0;+}++/*******************************************************************/+/* object list */++typedef struct {+    JSObject *obj;+    uint32_t hash_next; /* -1 if no next entry */+} JSObjectListEntry;++/* XXX: reuse it to optimize weak references */+typedef struct {+    JSObjectListEntry *object_tab;+    int object_count;+    int object_size;+    uint32_t *hash_table;+    uint32_t hash_size;+} JSObjectList;++static void js_object_list_init(JSObjectList *s)+{+    memset(s, 0, sizeof(*s));+}++static uint32_t js_object_list_get_hash(JSObject *p, uint32_t hash_size)+{+    return ((uintptr_t)p * 3163) & (hash_size - 1);+}++static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s,+                                 uint32_t new_hash_size)+{+    JSObjectListEntry *e;+    uint32_t i, h, *new_hash_table;++    new_hash_table = js_malloc(ctx, sizeof(new_hash_table[0]) * new_hash_size);+    if (!new_hash_table)+        return -1;+    js_free(ctx, s->hash_table);+    s->hash_table = new_hash_table;+    s->hash_size = new_hash_size;+    +    for(i = 0; i < s->hash_size; i++) {+        s->hash_table[i] = -1;+    }+    for(i = 0; i < s->object_count; i++) {+        e = &s->object_tab[i];+        h = js_object_list_get_hash(e->obj, s->hash_size); +        e->hash_next = s->hash_table[h];+        s->hash_table[h] = i;+    }+    return 0;+}++/* the reference count of 'obj' is not modified. Return 0 if OK, -1 if+   memory error */+static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj)+{+    JSObjectListEntry *e;+    uint32_t h, new_hash_size;+    +    if (js_resize_array(ctx, (void *)&s->object_tab,+                        sizeof(s->object_tab[0]),+                        &s->object_size, s->object_count + 1))+        return -1;+    if (unlikely((s->object_count + 1) >= s->hash_size)) {+        new_hash_size = max_uint32(s->hash_size, 4);+        while (new_hash_size <= s->object_count)+            new_hash_size *= 2;+        if (js_object_list_resize_hash(ctx, s, new_hash_size))+            return -1;+    }+    e = &s->object_tab[s->object_count++];+    h = js_object_list_get_hash(obj, s->hash_size); +    e->obj = obj;+    e->hash_next = s->hash_table[h];+    s->hash_table[h] = s->object_count - 1;+    return 0;+}++/* return -1 if not present or the object index */+static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj)+{+    JSObjectListEntry *e;+    uint32_t h, p;++    /* must test empty size because there is no hash table */+    if (s->object_count == 0)+        return -1;+    h = js_object_list_get_hash(obj, s->hash_size); +    p = s->hash_table[h];+    while (p != -1) {+        e = &s->object_tab[p];+        if (e->obj == obj)+            return p;+        p = e->hash_next;+    }+    return -1;+}++static void js_object_list_end(JSContext *ctx, JSObjectList *s)+{+    js_free(ctx, s->object_tab);+    js_free(ctx, s->hash_table);+}++/*******************************************************************/+/* binary object writer & reader */++typedef enum BCTagEnum {+    BC_TAG_NULL = 1,+    BC_TAG_UNDEFINED,+    BC_TAG_BOOL_FALSE,+    BC_TAG_BOOL_TRUE,+    BC_TAG_INT32,+    BC_TAG_FLOAT64,+    BC_TAG_STRING,+    BC_TAG_OBJECT,+    BC_TAG_ARRAY,+    BC_TAG_BIG_INT,+    BC_TAG_BIG_FLOAT,+    BC_TAG_BIG_DECIMAL,+    BC_TAG_TEMPLATE_OBJECT,+    BC_TAG_FUNCTION_BYTECODE,+    BC_TAG_MODULE,+    BC_TAG_TYPED_ARRAY,+    BC_TAG_ARRAY_BUFFER,+    BC_TAG_SHARED_ARRAY_BUFFER,+    BC_TAG_DATE,+    BC_TAG_OBJECT_VALUE,+    BC_TAG_OBJECT_REFERENCE,+} BCTagEnum;++#ifdef CONFIG_BIGNUM+#define BC_BASE_VERSION 2+#else+#define BC_BASE_VERSION 1+#endif+#define BC_BE_VERSION 0x40+#ifdef WORDS_BIGENDIAN+#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION)+#else+#define BC_VERSION BC_BASE_VERSION+#endif++typedef struct BCWriterState {+    JSContext *ctx;+    DynBuf dbuf;+    BOOL byte_swap : 8;+    BOOL allow_bytecode : 8;+    BOOL allow_sab : 8;+    BOOL allow_reference : 8;+    uint32_t first_atom;+    uint32_t *atom_to_idx;+    int atom_to_idx_size;+    JSAtom *idx_to_atom;+    int idx_to_atom_count;+    int idx_to_atom_size;+    uint8_t **sab_tab;+    int sab_tab_len;+    int sab_tab_size;+    /* list of referenced objects (used if allow_reference = TRUE) */+    JSObjectList object_list;+} BCWriterState;++#ifdef DUMP_READ_OBJECT+static const char * const bc_tag_str[] = {+    "invalid",+    "null",+    "undefined",+    "false",+    "true",+    "int32",+    "float64",+    "string",+    "object",+    "array",+    "bigint",+    "bigfloat",+    "bigdecimal",+    "template",+    "function",+    "module",+    "TypedArray",+    "ArrayBuffer",+    "SharedArrayBuffer",+    "Date",+    "ObjectValue",+    "ObjectReference",+};+#endif++static void bc_put_u8(BCWriterState *s, uint8_t v)+{+    dbuf_putc(&s->dbuf, v);+}++static void bc_put_u16(BCWriterState *s, uint16_t v)+{+    if (s->byte_swap)+        v = bswap16(v);+    dbuf_put_u16(&s->dbuf, v);+}++static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)+{+    if (s->byte_swap)+        v = bswap32(v);+    dbuf_put_u32(&s->dbuf, v);+}++static void bc_put_u64(BCWriterState *s, uint64_t v)+{+    if (s->byte_swap)+        v = bswap64(v);+    dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));+}++static void bc_put_leb128(BCWriterState *s, uint32_t v)+{+    dbuf_put_leb128(&s->dbuf, v);+}++static void bc_put_sleb128(BCWriterState *s, int32_t v)+{+    dbuf_put_sleb128(&s->dbuf, v);+}++static void bc_set_flags(uint32_t *pflags, int *pidx, uint32_t val, int n)+{+    *pflags = *pflags | (val << *pidx);+    *pidx += n;+}++static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom)+{+    uint32_t v;++    if (atom < s->first_atom || __JS_AtomIsTaggedInt(atom)) {+        *pres = atom;+        return 0;+    }+    atom -= s->first_atom;+    if (atom < s->atom_to_idx_size && s->atom_to_idx[atom] != 0) {+        *pres = s->atom_to_idx[atom];+        return 0;+    }+    if (atom >= s->atom_to_idx_size) {+        int old_size, i;+        old_size = s->atom_to_idx_size;+        if (js_resize_array(s->ctx, (void **)&s->atom_to_idx,+                            sizeof(s->atom_to_idx[0]), &s->atom_to_idx_size,+                            atom + 1))+            return -1;+        /* XXX: could add a specific js_resize_array() function to do it */+        for(i = old_size; i < s->atom_to_idx_size; i++)+            s->atom_to_idx[i] = 0;+    }+    if (js_resize_array(s->ctx, (void **)&s->idx_to_atom,+                        sizeof(s->idx_to_atom[0]),+                        &s->idx_to_atom_size, s->idx_to_atom_count + 1))+        goto fail;++    v = s->idx_to_atom_count++;+    s->idx_to_atom[v] = atom + s->first_atom;+    v += s->first_atom;+    s->atom_to_idx[atom] = v;+    *pres = v;+    return 0;+ fail:+    *pres = 0;+    return -1;+}++static int bc_put_atom(BCWriterState *s, JSAtom atom)+{+    uint32_t v;++    if (__JS_AtomIsTaggedInt(atom)) {+        v = (__JS_AtomToUInt32(atom) << 1) | 1;+    } else {+        if (bc_atom_to_idx(s, &v, atom))+            return -1;+        v <<= 1;+    }+    bc_put_leb128(s, v);+    return 0;+}++static void bc_byte_swap(uint8_t *bc_buf, int bc_len)+{+    int pos, len, op, fmt;++    pos = 0;+    while (pos < bc_len) {+        op = bc_buf[pos];+        len = short_opcode_info(op).size;+        fmt = short_opcode_info(op).fmt;+        switch(fmt) {+        case OP_FMT_u16:+        case OP_FMT_i16:+        case OP_FMT_label16:+        case OP_FMT_npop:+        case OP_FMT_loc:+        case OP_FMT_arg:+        case OP_FMT_var_ref:+            put_u16(bc_buf + pos + 1,+                    bswap16(get_u16(bc_buf + pos + 1)));+            break;+        case OP_FMT_i32:+        case OP_FMT_u32:+        case OP_FMT_const:+        case OP_FMT_label:+        case OP_FMT_atom:+        case OP_FMT_atom_u8:+            put_u32(bc_buf + pos + 1,+                    bswap32(get_u32(bc_buf + pos + 1)));+            break;+        case OP_FMT_atom_u16:+        case OP_FMT_label_u16:+            put_u32(bc_buf + pos + 1,+                    bswap32(get_u32(bc_buf + pos + 1)));+            put_u16(bc_buf + pos + 1 + 4,+                    bswap16(get_u16(bc_buf + pos + 1 + 4)));+            break;+        case OP_FMT_atom_label_u8:+        case OP_FMT_atom_label_u16:+            put_u32(bc_buf + pos + 1,+                    bswap32(get_u32(bc_buf + pos + 1)));+            put_u32(bc_buf + pos + 1 + 4,+                    bswap32(get_u32(bc_buf + pos + 1 + 4)));+            if (fmt == OP_FMT_atom_label_u16) {+                put_u16(bc_buf + pos + 1 + 4 + 4,+                        bswap16(get_u16(bc_buf + pos + 1 + 4 + 4)));+            }+            break;+        case OP_FMT_npop_u16:+            put_u16(bc_buf + pos + 1,+                    bswap16(get_u16(bc_buf + pos + 1)));+            put_u16(bc_buf + pos + 1 + 2,+                    bswap16(get_u16(bc_buf + pos + 1 + 2)));+            break;+        default:+            break;+        }+        pos += len;+    }+}++static int JS_WriteFunctionBytecode(BCWriterState *s,+                                    const uint8_t *bc_buf1, int bc_len)+{+    int pos, len, op;+    JSAtom atom;+    uint8_t *bc_buf;+    uint32_t val;++    bc_buf = js_malloc(s->ctx, bc_len);+    if (!bc_buf)+        return -1;+    memcpy(bc_buf, bc_buf1, bc_len);++    pos = 0;+    while (pos < bc_len) {+        op = bc_buf[pos];+        len = short_opcode_info(op).size;+        switch(short_opcode_info(op).fmt) {+        case OP_FMT_atom:+        case OP_FMT_atom_u8:+        case OP_FMT_atom_u16:+        case OP_FMT_atom_label_u8:+        case OP_FMT_atom_label_u16:+            atom = get_u32(bc_buf + pos + 1);+            if (bc_atom_to_idx(s, &val, atom))+                goto fail;+            put_u32(bc_buf + pos + 1, val);+            break;+        default:+            break;+        }+        pos += len;+    }++    if (s->byte_swap)+        bc_byte_swap(bc_buf, bc_len);++    dbuf_put(&s->dbuf, bc_buf, bc_len);++    js_free(s->ctx, bc_buf);+    return 0;+ fail:+    js_free(s->ctx, bc_buf);+    return -1;+}++static void JS_WriteString(BCWriterState *s, JSString *p)+{+    int i;+    bc_put_leb128(s, ((uint32_t)p->len << 1) | p->is_wide_char);+    if (p->is_wide_char) {+        for(i = 0; i < p->len; i++)+            bc_put_u16(s, p->u.str16[i]);+    } else {+        dbuf_put(&s->dbuf, p->u.str8, p->len);+    }+}++#ifdef CONFIG_BIGNUM+static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj)+{+    uint32_t tag, tag1;+    int64_t e;+    JSBigFloat *bf = JS_VALUE_GET_PTR(obj);+    bf_t *a = &bf->num;+    size_t len, i, n1, j;+    limb_t v;++    tag = JS_VALUE_GET_TAG(obj);+    switch(tag) {+    case JS_TAG_BIG_INT:+        tag1 = BC_TAG_BIG_INT;+        break;+    case JS_TAG_BIG_FLOAT:+        tag1 = BC_TAG_BIG_FLOAT;+        break;+    case JS_TAG_BIG_DECIMAL:+        tag1 = BC_TAG_BIG_DECIMAL;+        break;+    default:+        abort();+    }+    bc_put_u8(s, tag1);++    /* sign + exponent */+    if (a->expn == BF_EXP_ZERO)+        e = 0;+    else if (a->expn == BF_EXP_INF)+        e = 1;+    else if (a->expn == BF_EXP_NAN)+        e = 2;+    else if (a->expn >= 0)+        e = a->expn + 3;+    else+        e = a->expn;+    e = (e << 1) | a->sign;+    if (e < INT32_MIN || e > INT32_MAX) {+        JS_ThrowInternalError(s->ctx, "bignum exponent is too large");+        return -1;+    }+    bc_put_sleb128(s, e);++    /* mantissa */+    if (a->len != 0) {+        if (tag != JS_TAG_BIG_DECIMAL) {+            i = 0;+            while (i < a->len && a->tab[i] == 0)+                i++;+            assert(i < a->len);+            v = a->tab[i];+            n1 = sizeof(limb_t);+            while ((v & 0xff) == 0) {+                n1--;+                v >>= 8;+            }+            i++;+            len = (a->len - i) * sizeof(limb_t) + n1;+            if (len > INT32_MAX) {+                JS_ThrowInternalError(s->ctx, "bignum is too large");+                return -1;+            }+            bc_put_leb128(s, len);+            /* always saved in byte based little endian representation */+            for(j = 0; j < n1; j++) {+                dbuf_putc(&s->dbuf, v >> (j * 8));+            }+            for(; i < a->len; i++) {+                limb_t v = a->tab[i];+#if LIMB_BITS == 32+#ifdef WORDS_BIGENDIAN+                v = bswap32(v);+#endif+                dbuf_put_u32(&s->dbuf, v);+#else+#ifdef WORDS_BIGENDIAN+                v = bswap64(v);+#endif+                dbuf_put_u64(&s->dbuf, v);+#endif+            }+        } else {+            int bpos, d;+            uint8_t v8;+            size_t i0;+            +            /* little endian BCD */+            i = 0;+            while (i < a->len && a->tab[i] == 0)+                i++;+            assert(i < a->len);+            len = a->len * LIMB_DIGITS;+            v = a->tab[i];+            j = 0;+            while ((v % 10) == 0) {+                j++;+                v /= 10;+            }+            len -= j;+            assert(len > 0);+            if (len > INT32_MAX) {+                JS_ThrowInternalError(s->ctx, "bignum is too large");+                return -1;+            }+            bc_put_leb128(s, len);+            +            bpos = 0;+            v8 = 0;+            i0 = i;+            for(; i < a->len; i++) {+                if (i != i0) {+                    v = a->tab[i];+                    j = 0;+                }+                for(; j < LIMB_DIGITS; j++) {+                    d = v % 10;+                    v /= 10;+                    if (bpos == 0) {+                        v8 = d;+                        bpos = 1;+                    } else {+                        dbuf_putc(&s->dbuf, v8 | (d << 4));+                        bpos = 0;+                    }+                }+            }+            /* flush the last digit */+            if (bpos) {+                dbuf_putc(&s->dbuf, v8);+            }+        }+    }+    return 0;+}+#endif /* CONFIG_BIGNUM */++static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj);++static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj)+{+    JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj);+    uint32_t flags;+    int idx, i;+    +    bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE);+    flags = idx = 0;+    bc_set_flags(&flags, &idx, b->has_prototype, 1);+    bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1);+    bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1);+    bc_set_flags(&flags, &idx, b->need_home_object, 1);+    bc_set_flags(&flags, &idx, b->func_kind, 2);+    bc_set_flags(&flags, &idx, b->new_target_allowed, 1);+    bc_set_flags(&flags, &idx, b->super_call_allowed, 1);+    bc_set_flags(&flags, &idx, b->super_allowed, 1);+    bc_set_flags(&flags, &idx, b->arguments_allowed, 1);+    bc_set_flags(&flags, &idx, b->has_debug, 1);+    bc_set_flags(&flags, &idx, b->backtrace_barrier, 1);+    assert(idx <= 16);+    bc_put_u16(s, flags);+    bc_put_u8(s, b->js_mode);+    bc_put_atom(s, b->func_name);+    +    bc_put_leb128(s, b->arg_count);+    bc_put_leb128(s, b->var_count);+    bc_put_leb128(s, b->defined_arg_count);+    bc_put_leb128(s, b->stack_size);+    bc_put_leb128(s, b->closure_var_count);+    bc_put_leb128(s, b->cpool_count);+    bc_put_leb128(s, b->byte_code_len);+    if (b->vardefs) {+        bc_put_leb128(s, b->arg_count + b->var_count);+        for(i = 0; i < b->arg_count + b->var_count; i++) {+            JSVarDef *vd = &b->vardefs[i];+            bc_put_atom(s, vd->var_name);+            bc_put_leb128(s, vd->scope_level);+            bc_put_leb128(s, vd->scope_next + 1);+            flags = idx = 0;+            bc_set_flags(&flags, &idx, vd->var_kind, 4);+            bc_set_flags(&flags, &idx, vd->is_const, 1);+            bc_set_flags(&flags, &idx, vd->is_lexical, 1);+            bc_set_flags(&flags, &idx, vd->is_captured, 1);+            assert(idx <= 8);+            bc_put_u8(s, flags);+        }+    } else {+        bc_put_leb128(s, 0);+    }+    +    for(i = 0; i < b->closure_var_count; i++) {+        JSClosureVar *cv = &b->closure_var[i];+        bc_put_atom(s, cv->var_name);+        bc_put_leb128(s, cv->var_idx);+        flags = idx = 0;+        bc_set_flags(&flags, &idx, cv->is_local, 1);+        bc_set_flags(&flags, &idx, cv->is_arg, 1);+        bc_set_flags(&flags, &idx, cv->is_const, 1);+        bc_set_flags(&flags, &idx, cv->is_lexical, 1);+        bc_set_flags(&flags, &idx, cv->var_kind, 4);+        assert(idx <= 8);+        bc_put_u8(s, flags);+    }+    +    if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len))+        goto fail;+    +    if (b->has_debug) {+        bc_put_atom(s, b->debug.filename);+        bc_put_leb128(s, b->debug.line_num);+        bc_put_leb128(s, b->debug.pc2line_len);+        dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len);+    }+    +    for(i = 0; i < b->cpool_count; i++) {+        if (JS_WriteObjectRec(s, b->cpool[i]))+            goto fail;+    }+    return 0;+ fail:+    return -1;+}++static int JS_WriteModule(BCWriterState *s, JSValueConst obj)+{+    JSModuleDef *m = JS_VALUE_GET_PTR(obj);+    int i;+    +    bc_put_u8(s, BC_TAG_MODULE);+    bc_put_atom(s, m->module_name);+    +    bc_put_leb128(s, m->req_module_entries_count);+    for(i = 0; i < m->req_module_entries_count; i++) {+        JSReqModuleEntry *rme = &m->req_module_entries[i];+        bc_put_atom(s, rme->module_name);+    }+    +    bc_put_leb128(s, m->export_entries_count);+    for(i = 0; i < m->export_entries_count; i++) {+        JSExportEntry *me = &m->export_entries[i];+        bc_put_u8(s, me->export_type);+        if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+            bc_put_leb128(s, me->u.local.var_idx);+        } else {+            bc_put_leb128(s, me->u.req_module_idx);+            bc_put_atom(s, me->local_name);+        }+        bc_put_atom(s, me->export_name);+    }+    +    bc_put_leb128(s, m->star_export_entries_count);+    for(i = 0; i < m->star_export_entries_count; i++) {+        JSStarExportEntry *se = &m->star_export_entries[i];+        bc_put_leb128(s, se->req_module_idx);+    }+    +    bc_put_leb128(s, m->import_entries_count);+    for(i = 0; i < m->import_entries_count; i++) {+        JSImportEntry *mi = &m->import_entries[i];+        bc_put_leb128(s, mi->var_idx);+        bc_put_atom(s, mi->import_name);+        bc_put_leb128(s, mi->req_module_idx);+    }+    +    if (JS_WriteObjectRec(s, m->func_obj))+        goto fail;+    return 0;+ fail:+    return -1;+}++static int JS_WriteArray(BCWriterState *s, JSValueConst obj)+{+    JSObject *p = JS_VALUE_GET_OBJ(obj);+    uint32_t i, len;+    JSValue val;+    int ret;+    BOOL is_template;+    +    if (s->allow_bytecode && !p->extensible) {+        /* not extensible array: we consider it is a+           template when we are saving bytecode */+        bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT);+        is_template = TRUE;+    } else {+        bc_put_u8(s, BC_TAG_ARRAY);+        is_template = FALSE;+    }+    if (js_get_length32(s->ctx, &len, obj))+        goto fail1;+    bc_put_leb128(s, len);+    for(i = 0; i < len; i++) {+        val = JS_GetPropertyUint32(s->ctx, obj, i);+        if (JS_IsException(val))+            goto fail1;+        ret = JS_WriteObjectRec(s, val);+        JS_FreeValue(s->ctx, val);+        if (ret)+            goto fail1;+    }+    if (is_template) {+        val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw);+        if (JS_IsException(val))+            goto fail1;+        ret = JS_WriteObjectRec(s, val);+        JS_FreeValue(s->ctx, val);+        if (ret)+            goto fail1;+    }+    return 0;+ fail1:+    return -1;+}++static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj)+{+    JSObject *p = JS_VALUE_GET_OBJ(obj);+    uint32_t i, prop_count;+    JSShape *sh;+    JSShapeProperty *pr;+    int pass;+    JSAtom atom;++    bc_put_u8(s, BC_TAG_OBJECT);+    prop_count = 0;+    sh = p->shape;+    for(pass = 0; pass < 2; pass++) {+        if (pass == 1)+            bc_put_leb128(s, prop_count);+        for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) {+            atom = pr->atom;+            if (atom != JS_ATOM_NULL &&+                JS_AtomIsString(s->ctx, atom) &&+                (pr->flags & JS_PROP_ENUMERABLE)) {+                if (pr->flags & JS_PROP_TMASK) {+                    JS_ThrowTypeError(s->ctx, "only value properties are supported");+                    goto fail;+                }+                if (pass == 0) {+                    prop_count++;+                } else {+                    bc_put_atom(s, atom);+                    if (JS_WriteObjectRec(s, p->prop[i].u.value))+                        goto fail;+                }+            }+        }+    }+    return 0;+ fail:+    return -1;+}++static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj)+{+    JSObject *p = JS_VALUE_GET_OBJ(obj);+    JSTypedArray *ta = p->u.typed_array;++    bc_put_u8(s, BC_TAG_TYPED_ARRAY);+    bc_put_u8(s, p->class_id - JS_CLASS_UINT8C_ARRAY);+    bc_put_leb128(s, p->u.array.count);+    bc_put_leb128(s, ta->offset);+    if (JS_WriteObjectRec(s, JS_MKPTR(JS_TAG_OBJECT, ta->buffer)))+        return -1;+    return 0;+}++static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj)+{+    JSObject *p = JS_VALUE_GET_OBJ(obj);+    JSArrayBuffer *abuf = p->u.array_buffer;+    if (abuf->detached) {+        JS_ThrowTypeErrorDetachedArrayBuffer(s->ctx);+        return -1;+    }+    bc_put_u8(s, BC_TAG_ARRAY_BUFFER);+    bc_put_leb128(s, abuf->byte_length);+    dbuf_put(&s->dbuf, abuf->data, abuf->byte_length);+    return 0;+}++static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj)+{+    JSObject *p = JS_VALUE_GET_OBJ(obj);+    JSArrayBuffer *abuf = p->u.array_buffer;+    assert(!abuf->detached); /* SharedArrayBuffer are never detached */+    bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER);+    bc_put_leb128(s, abuf->byte_length);+    bc_put_u64(s, (uintptr_t)abuf->data);+    if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]),+                        &s->sab_tab_size, s->sab_tab_len + 1))+        return -1;+    /* keep the SAB pointer so that the user can clone it or free it */+    s->sab_tab[s->sab_tab_len++] = abuf->data;+    return 0;+}++static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj)+{+    uint32_t tag;++    if (js_check_stack_overflow(s->ctx->rt, 0)) {+        JS_ThrowStackOverflow(s->ctx);+        return -1;+    }++    tag = JS_VALUE_GET_NORM_TAG(obj);+    switch(tag) {+    case JS_TAG_NULL:+        bc_put_u8(s, BC_TAG_NULL);+        break;+    case JS_TAG_UNDEFINED:+        bc_put_u8(s, BC_TAG_UNDEFINED);+        break;+    case JS_TAG_BOOL:+        bc_put_u8(s, BC_TAG_BOOL_FALSE + JS_VALUE_GET_INT(obj));+        break;+    case JS_TAG_INT:+        bc_put_u8(s, BC_TAG_INT32);+        bc_put_sleb128(s, JS_VALUE_GET_INT(obj));+        break;+    case JS_TAG_FLOAT64:+        {+            JSFloat64Union u;+            bc_put_u8(s, BC_TAG_FLOAT64);+            u.d = JS_VALUE_GET_FLOAT64(obj);+            bc_put_u64(s, u.u64);+        }+        break;+    case JS_TAG_STRING:+        {+            JSString *p = JS_VALUE_GET_STRING(obj);+            bc_put_u8(s, BC_TAG_STRING);+            JS_WriteString(s, p);+        }+        break;+    case JS_TAG_FUNCTION_BYTECODE:+        if (!s->allow_bytecode)+            goto invalid_tag;+        if (JS_WriteFunctionTag(s, obj))+            goto fail;+        break;+    case JS_TAG_MODULE:+        if (!s->allow_bytecode)+            goto invalid_tag;+        if (JS_WriteModule(s, obj))+            goto fail;+        break;+    case JS_TAG_OBJECT:+        {+            JSObject *p = JS_VALUE_GET_OBJ(obj);+            int ret, idx;+            +            if (s->allow_reference) {+                idx = js_object_list_find(s->ctx, &s->object_list, p);+                if (idx >= 0) {+                    bc_put_u8(s, BC_TAG_OBJECT_REFERENCE);+                    bc_put_leb128(s, idx);+                    break;+                } else {+                    if (js_object_list_add(s->ctx, &s->object_list, p))+                        goto fail;+                }+            } else {+                if (p->tmp_mark) {+                    JS_ThrowTypeError(s->ctx, "circular reference");+                    goto fail;+                }+                p->tmp_mark = 1;+            }+            switch(p->class_id) {+            case JS_CLASS_ARRAY:+                ret = JS_WriteArray(s, obj);+                break;+            case JS_CLASS_OBJECT:+                ret = JS_WriteObjectTag(s, obj);+                break;+            case JS_CLASS_ARRAY_BUFFER:+                ret = JS_WriteArrayBuffer(s, obj);+                break;+            case JS_CLASS_SHARED_ARRAY_BUFFER:+                if (!s->allow_sab)+                    goto invalid_tag;+                ret = JS_WriteSharedArrayBuffer(s, obj);+                break;+            case JS_CLASS_DATE:+                bc_put_u8(s, BC_TAG_DATE);+                ret = JS_WriteObjectRec(s, p->u.object_data);+                break;+            case JS_CLASS_NUMBER:+            case JS_CLASS_STRING:+            case JS_CLASS_BOOLEAN:+#ifdef CONFIG_BIGNUM+            case JS_CLASS_BIG_INT:+            case JS_CLASS_BIG_FLOAT:+            case JS_CLASS_BIG_DECIMAL:+#endif+                bc_put_u8(s, BC_TAG_OBJECT_VALUE);+                ret = JS_WriteObjectRec(s, p->u.object_data);+                break;+            default:+                if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+                    p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+                    ret = JS_WriteTypedArray(s, obj);+                } else {+                    JS_ThrowTypeError(s->ctx, "unsupported object class");+                    ret = -1;+                }+                break;+            }+            p->tmp_mark = 0;+            if (ret)+                goto fail;+        }+        break;+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+    case JS_TAG_BIG_DECIMAL:+        if (JS_WriteBigNum(s, obj))+            goto fail;+        break;+#endif+    default:+    invalid_tag:+        JS_ThrowInternalError(s->ctx, "unsupported tag (%d)", tag);+        goto fail;+    }+    return 0;++ fail:+    return -1;+}++/* create the atom table */+static int JS_WriteObjectAtoms(BCWriterState *s)+{+    JSRuntime *rt = s->ctx->rt;+    DynBuf dbuf1;+    int i, atoms_size;+    uint8_t version;++    dbuf1 = s->dbuf;+    js_dbuf_init(s->ctx, &s->dbuf);++    version = BC_VERSION;+    if (s->byte_swap)+        version ^= BC_BE_VERSION;+    bc_put_u8(s, version);++    bc_put_leb128(s, s->idx_to_atom_count);+    for(i = 0; i < s->idx_to_atom_count; i++) {+        JSAtomStruct *p = rt->atom_array[s->idx_to_atom[i]];+        JS_WriteString(s, p);+    }+    /* XXX: should check for OOM in above phase */++    /* move the atoms at the start */+    /* XXX: could just append dbuf1 data, but it uses more memory if+       dbuf1 is larger than dbuf */+    atoms_size = s->dbuf.size;+    if (dbuf_realloc(&dbuf1, dbuf1.size + atoms_size))+        goto fail;+    memmove(dbuf1.buf + atoms_size, dbuf1.buf, dbuf1.size);+    memcpy(dbuf1.buf, s->dbuf.buf, atoms_size);+    dbuf1.size += atoms_size;+    dbuf_free(&s->dbuf);+    s->dbuf = dbuf1;+    return 0;+ fail:+    dbuf_free(&dbuf1);+    return -1;+}++uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,+                         int flags, uint8_t ***psab_tab, size_t *psab_tab_len)+{+    BCWriterState ss, *s = &ss;++    memset(s, 0, sizeof(*s));+    s->ctx = ctx;+    /* XXX: byte swapped output is untested */+    s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);+    s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);+    s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);+    s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);+    /* XXX: could use a different version when bytecode is included */+    if (s->allow_bytecode)+        s->first_atom = JS_ATOM_END;+    else+        s->first_atom = 1;+    js_dbuf_init(ctx, &s->dbuf);+    js_object_list_init(&s->object_list);+    +    if (JS_WriteObjectRec(s, obj))+        goto fail;+    if (JS_WriteObjectAtoms(s))+        goto fail;+    js_object_list_end(ctx, &s->object_list);+    js_free(ctx, s->atom_to_idx);+    js_free(ctx, s->idx_to_atom);+    *psize = s->dbuf.size;+    if (psab_tab)+        *psab_tab = s->sab_tab;+    if (psab_tab_len)+        *psab_tab_len = s->sab_tab_len;+    return s->dbuf.buf;+ fail:+    js_object_list_end(ctx, &s->object_list);+    js_free(ctx, s->atom_to_idx);+    js_free(ctx, s->idx_to_atom);+    dbuf_free(&s->dbuf);+    *psize = 0;+    if (psab_tab)+        *psab_tab = NULL;+    if (psab_tab_len)+        *psab_tab_len = 0;+    return NULL;+}++uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,+                        int flags)+{+    return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL);+}++typedef struct BCReaderState {+    JSContext *ctx;+    const uint8_t *buf_start, *ptr, *buf_end;+    uint32_t first_atom;+    uint32_t idx_to_atom_count;+    JSAtom *idx_to_atom;+    int error_state;+    BOOL allow_sab : 8;+    BOOL allow_bytecode : 8;+    BOOL is_rom_data : 8;+    BOOL allow_reference : 8;+    /* object references */+    JSObject **objects;+    int objects_count;+    int objects_size;+    +#ifdef DUMP_READ_OBJECT+    const uint8_t *ptr_last;+    int level;+#endif+} BCReaderState;++#ifdef DUMP_READ_OBJECT+static void __attribute__((format(printf, 2, 3))) bc_read_trace(BCReaderState *s, const char *fmt, ...) {+    va_list ap;+    int i, n, n0;++    if (!s->ptr_last)+        s->ptr_last = s->buf_start;++    n = n0 = 0;+    if (s->ptr > s->ptr_last || s->ptr == s->buf_start) {+        n0 = printf("%04x: ", (int)(s->ptr_last - s->buf_start));+        n += n0;+    }+    for (i = 0; s->ptr_last < s->ptr; i++) {+        if ((i & 7) == 0 && i > 0) {+            printf("\n%*s", n0, "");+            n = n0;+        }+        n += printf(" %02x", *s->ptr_last++);+    }+    if (*fmt == '}')+        s->level--;+    if (n < 32 + s->level * 2) {+        printf("%*s", 32 + s->level * 2 - n, "");+    }+    va_start(ap, fmt);+    vfprintf(stdout, fmt, ap);+    va_end(ap);+    if (strchr(fmt, '{'))+        s->level++;+}+#else+#define bc_read_trace(...)+#endif++static int bc_read_error_end(BCReaderState *s)+{+    if (!s->error_state) {+        JS_ThrowSyntaxError(s->ctx, "read after the end of the buffer");+    }+    return s->error_state = -1;+}++static int bc_get_u8(BCReaderState *s, uint8_t *pval)+{+    if (unlikely(s->buf_end - s->ptr < 1)) {+        *pval = 0; /* avoid warning */+        return bc_read_error_end(s);+    }+    *pval = *s->ptr++;+    return 0;+}++static int bc_get_u16(BCReaderState *s, uint16_t *pval)+{+    if (unlikely(s->buf_end - s->ptr < 2)) {+        *pval = 0; /* avoid warning */+        return bc_read_error_end(s);+    }+    *pval = get_u16(s->ptr);+    s->ptr += 2;+    return 0;+}++static __maybe_unused int bc_get_u32(BCReaderState *s, uint32_t *pval)+{+    if (unlikely(s->buf_end - s->ptr < 4)) {+        *pval = 0; /* avoid warning */+        return bc_read_error_end(s);+    }+    *pval = get_u32(s->ptr);+    s->ptr += 4;+    return 0;+}++static int bc_get_u64(BCReaderState *s, uint64_t *pval)+{+    if (unlikely(s->buf_end - s->ptr < 8)) {+        *pval = 0; /* avoid warning */+        return bc_read_error_end(s);+    }+    *pval = get_u64(s->ptr);+    s->ptr += 8;+    return 0;+}++static int bc_get_leb128(BCReaderState *s, uint32_t *pval)+{+    int ret;+    ret = get_leb128(pval, s->ptr, s->buf_end);+    if (unlikely(ret < 0))+        return bc_read_error_end(s);+    s->ptr += ret;+    return 0;+}++static int bc_get_sleb128(BCReaderState *s, int32_t *pval)+{+    int ret;+    ret = get_sleb128(pval, s->ptr, s->buf_end);+    if (unlikely(ret < 0))+        return bc_read_error_end(s);+    s->ptr += ret;+    return 0;+}++/* XXX: used to read an `int` with a positive value */+static int bc_get_leb128_int(BCReaderState *s, int *pval)+{+    return bc_get_leb128(s, (uint32_t *)pval);+}++static int bc_get_leb128_u16(BCReaderState *s, uint16_t *pval)+{+    uint32_t val;+    if (bc_get_leb128(s, &val)) {+        *pval = 0;+        return -1;+    }+    *pval = val;+    return 0;+}++static int bc_get_buf(BCReaderState *s, uint8_t *buf, uint32_t buf_len)+{+    if (buf_len != 0) {+        if (unlikely(!buf || s->buf_end - s->ptr < buf_len))+            return bc_read_error_end(s);+        memcpy(buf, s->ptr, buf_len);+        s->ptr += buf_len;+    }+    return 0;+}++static int bc_idx_to_atom(BCReaderState *s, JSAtom *patom, uint32_t idx)+{+    JSAtom atom;++    if (__JS_AtomIsTaggedInt(idx)) {+        atom = idx;+    } else if (idx < s->first_atom) {+        atom = JS_DupAtom(s->ctx, idx);+    } else {+        idx -= s->first_atom;+        if (idx >= s->idx_to_atom_count) {+            JS_ThrowSyntaxError(s->ctx, "invalid atom index (pos=%u)",+                                (unsigned int)(s->ptr - s->buf_start));+            *patom = JS_ATOM_NULL;+            return s->error_state = -1;+        }+        atom = JS_DupAtom(s->ctx, s->idx_to_atom[idx]);+    }+    *patom = atom;+    return 0;+}++static int bc_get_atom(BCReaderState *s, JSAtom *patom)+{+    uint32_t v;+    if (bc_get_leb128(s, &v))+        return -1;+    if (v & 1) {+        *patom = __JS_AtomFromUInt32(v >> 1);+        return 0;+    } else {+        return bc_idx_to_atom(s, patom, v >> 1);+    }+}++static JSString *JS_ReadString(BCReaderState *s)+{+    uint32_t len;+    size_t size;+    BOOL is_wide_char;+    JSString *p;++    if (bc_get_leb128(s, &len))+        return NULL;+    is_wide_char = len & 1;+    len >>= 1;+    p = js_alloc_string(s->ctx, len, is_wide_char);+    if (!p) {+        s->error_state = -1;+        return NULL;+    }+    size = (size_t)len << is_wide_char;+    if ((s->buf_end - s->ptr) < size) {+        bc_read_error_end(s);+        js_free_string(s->ctx->rt, p);+        return NULL;+    }+    memcpy(p->u.str8, s->ptr, size);+    s->ptr += size;+    if (!is_wide_char) {+        p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */+    }+#ifdef DUMP_READ_OBJECT+    JS_DumpString(s->ctx->rt, p); printf("\n");+#endif+    return p;+}++static uint32_t bc_get_flags(uint32_t flags, int *pidx, int n)+{+    uint32_t val;+    /* XXX: this does not work for n == 32 */+    val = (flags >> *pidx) & ((1U << n) - 1);+    *pidx += n;+    return val;+}++static int JS_ReadFunctionBytecode(BCReaderState *s, JSFunctionBytecode *b,+                                   int byte_code_offset, uint32_t bc_len)+{+    uint8_t *bc_buf;+    int pos, len, op;+    JSAtom atom;+    uint32_t idx;++    if (s->is_rom_data) {+        /* directly use the input buffer */+        if (unlikely(s->buf_end - s->ptr < bc_len))+            return bc_read_error_end(s);+        bc_buf = (uint8_t *)s->ptr;+        s->ptr += bc_len;+    } else {+        bc_buf = (void *)((uint8_t*)b + byte_code_offset);+        if (bc_get_buf(s, bc_buf, bc_len))+            return -1;+    }+    b->byte_code_buf = bc_buf;++    pos = 0;+    while (pos < bc_len) {+        op = bc_buf[pos];+        len = short_opcode_info(op).size;+        switch(short_opcode_info(op).fmt) {+        case OP_FMT_atom:+        case OP_FMT_atom_u8:+        case OP_FMT_atom_u16:+        case OP_FMT_atom_label_u8:+        case OP_FMT_atom_label_u16:+            idx = get_u32(bc_buf + pos + 1);+            if (s->is_rom_data) {+                /* just increment the reference count of the atom */+                JS_DupAtom(s->ctx, (JSAtom)idx);+            } else {+                if (bc_idx_to_atom(s, &atom, idx)) {+                    /* Note: the atoms will be freed up to this position */+                    b->byte_code_len = pos;+                    return -1;+                }+                put_u32(bc_buf + pos + 1, atom);+#ifdef DUMP_READ_OBJECT+                bc_read_trace(s, "at %d, fixup atom: ", pos + 1); print_atom(s->ctx, atom); printf("\n");+#endif+            }+            break;+        default:+            break;+        }+        pos += len;+    }+    return 0;+}++#ifdef CONFIG_BIGNUM+static JSValue JS_ReadBigNum(BCReaderState *s, int tag)+{+    JSValue obj = JS_UNDEFINED;+    uint8_t v8;+    int32_t e;+    uint32_t len;+    limb_t l, i, n, j;+    JSBigFloat *p;+    limb_t v;+    bf_t *a;+    int bpos, d;+    +    p = js_new_bf(s->ctx);+    if (!p)+        goto fail;+    switch(tag) {+    case BC_TAG_BIG_INT:+        obj = JS_MKPTR(JS_TAG_BIG_INT, p);+        break;+    case BC_TAG_BIG_FLOAT:+        obj = JS_MKPTR(JS_TAG_BIG_FLOAT, p);+        break;+    case BC_TAG_BIG_DECIMAL:+        obj = JS_MKPTR(JS_TAG_BIG_DECIMAL, p);+        break;+    default:+        abort();+    }++    /* sign + exponent */+    if (bc_get_sleb128(s, &e))+        goto fail;++    a = &p->num;+    a->sign = e & 1;+    e >>= 1;+    if (e == 0)+        a->expn = BF_EXP_ZERO;+    else if (e == 1)+        a->expn = BF_EXP_INF;+    else if (e == 2)+        a->expn = BF_EXP_NAN;+    else if (e >= 3)+        a->expn = e - 3;+    else+        a->expn = e;++    /* mantissa */+    if (a->expn != BF_EXP_ZERO &&+        a->expn != BF_EXP_INF &&+        a->expn != BF_EXP_NAN) {+        if (bc_get_leb128(s, &len))+            goto fail;+        bc_read_trace(s, "len=%" PRId64 "\n", (int64_t)len);+        if (len == 0) {+            JS_ThrowInternalError(s->ctx, "invalid bignum length");+            goto fail;+        }+        if (tag != BC_TAG_BIG_DECIMAL)+            l = (len + sizeof(limb_t) - 1) / sizeof(limb_t);+        else+            l = (len + LIMB_DIGITS - 1) / LIMB_DIGITS;+        if (bf_resize(a, l)) {+            JS_ThrowOutOfMemory(s->ctx);+            goto fail;+        }+        if (tag != BC_TAG_BIG_DECIMAL) {+            n = len & (sizeof(limb_t) - 1);+            if (n != 0) {+                v = 0;+                for(i = 0; i < n; i++) {+                    if (bc_get_u8(s, &v8))+                        goto fail;+                    v |= (limb_t)v8 << ((sizeof(limb_t) - n + i) * 8);+                }+                a->tab[0] = v;+                i = 1;+            } else {+                i = 0;+            }+            for(; i < l; i++) {+#if LIMB_BITS == 32+                if (bc_get_u32(s, &v))+                    goto fail;+#ifdef WORDS_BIGENDIAN+                v = bswap32(v);+#endif+#else+                if (bc_get_u64(s, &v))+                    goto fail;+#ifdef WORDS_BIGENDIAN+                v = bswap64(v);+#endif+#endif+                a->tab[i] = v;+            }+        } else {+            bpos = 0;+            for(i = 0; i < l; i++) {+                if (i == 0 && (n = len % LIMB_DIGITS) != 0) {+                    j = LIMB_DIGITS - n;+                } else {+                    j = 0;+                }+                v = 0;+                for(; j < LIMB_DIGITS; j++) {+                    if (bpos == 0) {+                        if (bc_get_u8(s, &v8))+                            goto fail;+                        d = v8 & 0xf;+                        bpos = 1;+                    } else {+                        d = v8 >> 4;+                        bpos = 0;+                    }+                    if (d >= 10) {+                        JS_ThrowInternalError(s->ctx, "invalid digit");+                        goto fail;+                    }+                    v += mp_pow_dec[j] * d;+                }+                a->tab[i] = v;+            }+        }+    }+    bc_read_trace(s, "}\n");+    return obj;+ fail:+    JS_FreeValue(s->ctx, obj);+    return JS_EXCEPTION;+}+#endif /* CONFIG_BIGNUM */++static JSValue JS_ReadObjectRec(BCReaderState *s);++static int BC_add_object_ref1(BCReaderState *s, JSObject *p)+{+    if (s->allow_reference) {+        if (js_resize_array(s->ctx, (void *)&s->objects,+                            sizeof(s->objects[0]),+                            &s->objects_size, s->objects_count + 1))+            return -1;+        s->objects[s->objects_count++] = p;+    }+    return 0;+}++static int BC_add_object_ref(BCReaderState *s, JSValueConst obj)+{+    return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj));+}++static JSValue JS_ReadFunctionTag(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSFunctionBytecode bc, *b;+    JSValue obj = JS_UNDEFINED;+    uint16_t v16;+    uint8_t v8;+    int idx, i, local_count;+    int function_size, cpool_offset, byte_code_offset;+    int closure_var_offset, vardefs_offset;++    memset(&bc, 0, sizeof(bc));+    bc.header.ref_count = 1;+    //bc.gc_header.mark = 0;++    if (bc_get_u16(s, &v16))+        goto fail;+    idx = 0;+    bc.has_prototype = bc_get_flags(v16, &idx, 1);+    bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1);+    bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1);+    bc.need_home_object = bc_get_flags(v16, &idx, 1);+    bc.func_kind = bc_get_flags(v16, &idx, 2);+    bc.new_target_allowed = bc_get_flags(v16, &idx, 1);+    bc.super_call_allowed = bc_get_flags(v16, &idx, 1);+    bc.super_allowed = bc_get_flags(v16, &idx, 1);+    bc.arguments_allowed = bc_get_flags(v16, &idx, 1);+    bc.has_debug = bc_get_flags(v16, &idx, 1);+    bc.backtrace_barrier = bc_get_flags(v16, &idx, 1);+    bc.read_only_bytecode = s->is_rom_data;+    if (bc_get_u8(s, &v8))+        goto fail;+    bc.js_mode = v8;+    if (bc_get_atom(s, &bc.func_name))  //@ atom leak if failure+        goto fail;+    if (bc_get_leb128_u16(s, &bc.arg_count))+        goto fail;+    if (bc_get_leb128_u16(s, &bc.var_count))+        goto fail;+    if (bc_get_leb128_u16(s, &bc.defined_arg_count))+        goto fail;+    if (bc_get_leb128_u16(s, &bc.stack_size))+        goto fail;+    if (bc_get_leb128_int(s, &bc.closure_var_count))+        goto fail;+    if (bc_get_leb128_int(s, &bc.cpool_count))+        goto fail;+    if (bc_get_leb128_int(s, &bc.byte_code_len))+        goto fail;+    if (bc_get_leb128_int(s, &local_count))+        goto fail;++    if (bc.has_debug) {+        function_size = sizeof(*b);+    } else {+        function_size = offsetof(JSFunctionBytecode, debug);+    }+    cpool_offset = function_size;+    function_size += bc.cpool_count * sizeof(*bc.cpool);+    vardefs_offset = function_size;+    function_size += local_count * sizeof(*bc.vardefs);+    closure_var_offset = function_size;+    function_size += bc.closure_var_count * sizeof(*bc.closure_var);+    byte_code_offset = function_size;+    if (!bc.read_only_bytecode) {+        function_size += bc.byte_code_len;+    }++    b = js_mallocz(ctx, function_size);+    if (!b)+        return JS_EXCEPTION;+            +    memcpy(b, &bc, offsetof(JSFunctionBytecode, debug));+    b->header.ref_count = 1;+    add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);+            +    obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b);++#ifdef DUMP_READ_OBJECT+    bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n");+#endif+    bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n",+                  b->arg_count, b->var_count, b->defined_arg_count,+                  b->closure_var_count, b->cpool_count);+    bc_read_trace(s, "stack=%d bclen=%d locals=%d\n",+                  b->stack_size, b->byte_code_len, local_count);++    if (local_count != 0) {+        bc_read_trace(s, "vars {\n");+        b->vardefs = (void *)((uint8_t*)b + vardefs_offset);+        for(i = 0; i < local_count; i++) {+            JSVarDef *vd = &b->vardefs[i];+            if (bc_get_atom(s, &vd->var_name))+                goto fail;+            if (bc_get_leb128_int(s, &vd->scope_level))+                goto fail;+            if (bc_get_leb128_int(s, &vd->scope_next))+                goto fail;+            vd->scope_next--;+            if (bc_get_u8(s, &v8))+                goto fail;+            idx = 0;+            vd->var_kind = bc_get_flags(v8, &idx, 4);+            vd->is_const = bc_get_flags(v8, &idx, 1);+            vd->is_lexical = bc_get_flags(v8, &idx, 1);+            vd->is_captured = bc_get_flags(v8, &idx, 1);+#ifdef DUMP_READ_OBJECT+            bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n");+#endif+        }+        bc_read_trace(s, "}\n");+    }+    if (b->closure_var_count != 0) {+        bc_read_trace(s, "closure vars {\n");+        b->closure_var = (void *)((uint8_t*)b + closure_var_offset);+        for(i = 0; i < b->closure_var_count; i++) {+            JSClosureVar *cv = &b->closure_var[i];+            int var_idx;+            if (bc_get_atom(s, &cv->var_name))+                goto fail;+            if (bc_get_leb128_int(s, &var_idx))+                goto fail;+            cv->var_idx = var_idx;+            if (bc_get_u8(s, &v8))+                goto fail;+            idx = 0;+            cv->is_local = bc_get_flags(v8, &idx, 1);+            cv->is_arg = bc_get_flags(v8, &idx, 1);+            cv->is_const = bc_get_flags(v8, &idx, 1);+            cv->is_lexical = bc_get_flags(v8, &idx, 1);+            cv->var_kind = bc_get_flags(v8, &idx, 4);+#ifdef DUMP_READ_OBJECT+            bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n");+#endif+        }+        bc_read_trace(s, "}\n");+    }+    {+        bc_read_trace(s, "bytecode {\n");+        if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len))+            goto fail;+        bc_read_trace(s, "}\n");+    }+    if (b->has_debug) {+        /* read optional debug information */+        bc_read_trace(s, "debug {\n");+        if (bc_get_atom(s, &b->debug.filename))+            goto fail;+        if (bc_get_leb128_int(s, &b->debug.line_num))+            goto fail;+        if (bc_get_leb128_int(s, &b->debug.pc2line_len))+            goto fail;+        if (b->debug.pc2line_len) {+            b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len);+            if (!b->debug.pc2line_buf)+                goto fail;+            if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len))+                goto fail;+        }+#ifdef DUMP_READ_OBJECT+        bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n");+#endif+        bc_read_trace(s, "}\n");+    }+    if (b->cpool_count != 0) {+        bc_read_trace(s, "cpool {\n");+        b->cpool = (void *)((uint8_t*)b + cpool_offset);+        for(i = 0; i < b->cpool_count; i++) {+            JSValue val;+            val = JS_ReadObjectRec(s);+            if (JS_IsException(val))+                goto fail;+            b->cpool[i] = val;+        }+        bc_read_trace(s, "}\n");+    }+    b->realm = JS_DupContext(ctx);+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadModule(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSValue obj;+    JSModuleDef *m = NULL;+    JSAtom module_name;+    int i;+    uint8_t v8;+    +    if (bc_get_atom(s, &module_name))+        goto fail;+#ifdef DUMP_READ_OBJECT+    bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n");+#endif+    m = js_new_module_def(ctx, module_name);+    if (!m)+        goto fail;+    obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));+    if (bc_get_leb128_int(s, &m->req_module_entries_count))+        goto fail;+    if (m->req_module_entries_count != 0) {+        m->req_module_entries_size = m->req_module_entries_count;+        m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size);+        if (!m->req_module_entries)+            goto fail;+        for(i = 0; i < m->req_module_entries_count; i++) {+            JSReqModuleEntry *rme = &m->req_module_entries[i];+            if (bc_get_atom(s, &rme->module_name))+                goto fail;+        }+    }++    if (bc_get_leb128_int(s, &m->export_entries_count))+        goto fail;+    if (m->export_entries_count != 0) {+        m->export_entries_size = m->export_entries_count;+        m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size);+        if (!m->export_entries)+            goto fail;+        for(i = 0; i < m->export_entries_count; i++) {+            JSExportEntry *me = &m->export_entries[i];+            if (bc_get_u8(s, &v8))+                goto fail;+            me->export_type = v8;+            if (me->export_type == JS_EXPORT_TYPE_LOCAL) {+                if (bc_get_leb128_int(s, &me->u.local.var_idx))+                    goto fail;+            } else {+                if (bc_get_leb128_int(s, &me->u.req_module_idx))+                    goto fail;+                if (bc_get_atom(s, &me->local_name))+                    goto fail;+            }+            if (bc_get_atom(s, &me->export_name))+                goto fail;+        }+    }++    if (bc_get_leb128_int(s, &m->star_export_entries_count))+        goto fail;+    if (m->star_export_entries_count != 0) {+        m->star_export_entries_size = m->star_export_entries_count;+        m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size);+        if (!m->star_export_entries)+            goto fail;+        for(i = 0; i < m->star_export_entries_count; i++) {+            JSStarExportEntry *se = &m->star_export_entries[i];+            if (bc_get_leb128_int(s, &se->req_module_idx))+                goto fail;+        }+    }++    if (bc_get_leb128_int(s, &m->import_entries_count))+        goto fail;+    if (m->import_entries_count != 0) {+        m->import_entries_size = m->import_entries_count;+        m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size);+        if (!m->import_entries)+            goto fail;+        for(i = 0; i < m->import_entries_count; i++) {+            JSImportEntry *mi = &m->import_entries[i];+            if (bc_get_leb128_int(s, &mi->var_idx))+                goto fail;+            if (bc_get_atom(s, &mi->import_name))+                goto fail;+            if (bc_get_leb128_int(s, &mi->req_module_idx))+                goto fail;+        }+    }++    m->func_obj = JS_ReadObjectRec(s);+    if (JS_IsException(m->func_obj))+        goto fail;+    return obj;+ fail:+    if (m) {+        js_free_module_def(ctx, m);+    }+    return JS_EXCEPTION;+}++static JSValue JS_ReadObjectTag(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSValue obj;+    uint32_t prop_count, i;+    JSAtom atom;+    JSValue val;+    int ret;+    +    obj = JS_NewObject(ctx);+    if (BC_add_object_ref(s, obj))+        goto fail;+    if (bc_get_leb128(s, &prop_count))+        goto fail;+    for(i = 0; i < prop_count; i++) {+        if (bc_get_atom(s, &atom))+            goto fail;+#ifdef DUMP_READ_OBJECT+        bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n");+#endif+        val = JS_ReadObjectRec(s);+        if (JS_IsException(val)) {+            JS_FreeAtom(ctx, atom);+            goto fail;+        }+        ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E);+        JS_FreeAtom(ctx, atom);+        if (ret < 0)+            goto fail;+    }+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadArray(BCReaderState *s, int tag)+{+    JSContext *ctx = s->ctx;+    JSValue obj;+    uint32_t len, i;+    JSValue val;+    int ret, prop_flags;+    BOOL is_template;++    obj = JS_NewArray(ctx);+    if (BC_add_object_ref(s, obj))+        goto fail;+    is_template = (tag == BC_TAG_TEMPLATE_OBJECT);+    if (bc_get_leb128(s, &len))+        goto fail;+    for(i = 0; i < len; i++) {+        val = JS_ReadObjectRec(s);+        if (JS_IsException(val))+            goto fail;+        if (is_template)+            prop_flags = JS_PROP_ENUMERABLE;+        else+            prop_flags = JS_PROP_C_W_E;+        ret = JS_DefinePropertyValueUint32(ctx, obj, i, val,+                                           prop_flags);+        if (ret < 0)+            goto fail;+    }+    if (is_template) {+        val = JS_ReadObjectRec(s);+        if (JS_IsException(val))+            goto fail;+        if (!JS_IsUndefined(val)) {+            ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0);+            if (ret < 0)+                goto fail;+        }+        JS_PreventExtensions(ctx, obj);+    }+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadTypedArray(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED;+    uint8_t array_tag;+    JSValueConst args[3];+    uint32_t offset, len, idx;+    +    if (bc_get_u8(s, &array_tag))+        return JS_EXCEPTION;+    if (array_tag >= JS_TYPED_ARRAY_COUNT)+        return JS_ThrowTypeError(ctx, "invalid typed array");+    if (bc_get_leb128(s, &len))+        return JS_EXCEPTION;+    if (bc_get_leb128(s, &offset))+        return JS_EXCEPTION;+    /* XXX: this hack could be avoided if the typed array could be+       created before the array buffer */+    idx = s->objects_count;+    if (BC_add_object_ref1(s, NULL))+        goto fail;+    array_buffer = JS_ReadObjectRec(s);+    if (JS_IsException(array_buffer))+        return JS_EXCEPTION;+    if (!js_get_array_buffer(ctx, array_buffer)) {+        JS_FreeValue(ctx, array_buffer);+        return JS_EXCEPTION;+    }+    args[0] = array_buffer;+    args[1] = JS_NewInt64(ctx, offset);+    args[2] = JS_NewInt64(ctx, len);+    obj = js_typed_array_constructor(ctx, JS_UNDEFINED,+                                     3, args,+                                     JS_CLASS_UINT8C_ARRAY + array_tag);+    if (JS_IsException(obj))+        goto fail;+    if (s->allow_reference) {+        s->objects[idx] = JS_VALUE_GET_OBJ(obj);+    }+    JS_FreeValue(ctx, array_buffer);+    return obj;+ fail:+    JS_FreeValue(ctx, array_buffer);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadArrayBuffer(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    uint32_t byte_length;+    JSValue obj;+    +    if (bc_get_leb128(s, &byte_length))+        return JS_EXCEPTION;+    if (unlikely(s->buf_end - s->ptr < byte_length)) {+        bc_read_error_end(s);+        return JS_EXCEPTION;+    }+    obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length);+    if (JS_IsException(obj))+        goto fail;+    if (BC_add_object_ref(s, obj))+        goto fail;+    s->ptr += byte_length;+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    uint32_t byte_length;+    uint8_t *data_ptr;+    JSValue obj;+    uint64_t u64;+    +    if (bc_get_leb128(s, &byte_length))+        return JS_EXCEPTION;+    if (bc_get_u64(s, &u64))+        return JS_EXCEPTION;+    data_ptr = (uint8_t *)(uintptr_t)u64;+    /* the SharedArrayBuffer is cloned */+    obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length,+                                       JS_CLASS_SHARED_ARRAY_BUFFER,+                                       data_ptr,+                                       NULL, NULL, FALSE);+    if (JS_IsException(obj))+        goto fail;+    if (BC_add_object_ref(s, obj))+        goto fail;+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadDate(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSValue val, obj = JS_UNDEFINED;++    val = JS_ReadObjectRec(s);+    if (JS_IsException(val))+        goto fail;+    if (!JS_IsNumber(val)) {+        JS_ThrowTypeError(ctx, "Number tag expected for date");+        goto fail;+    }+    obj = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_DATE],+                                 JS_CLASS_DATE);+    if (JS_IsException(obj))+        goto fail;+    if (BC_add_object_ref(s, obj))+        goto fail;+    JS_SetObjectData(ctx, obj, val);+    return obj;+ fail:+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadObjectValue(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    JSValue val, obj = JS_UNDEFINED;++    val = JS_ReadObjectRec(s);+    if (JS_IsException(val))+        goto fail;+    obj = JS_ToObject(ctx, val);+    if (JS_IsException(obj))+        goto fail;+    if (BC_add_object_ref(s, obj))+        goto fail;+    JS_FreeValue(ctx, val);+    return obj;+ fail:+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue JS_ReadObjectRec(BCReaderState *s)+{+    JSContext *ctx = s->ctx;+    uint8_t tag;+    JSValue obj = JS_UNDEFINED;++    if (js_check_stack_overflow(ctx->rt, 0))+        return JS_ThrowStackOverflow(ctx);++    if (bc_get_u8(s, &tag))+        return JS_EXCEPTION;++    bc_read_trace(s, "%s {\n", bc_tag_str[tag]);++    switch(tag) {+    case BC_TAG_NULL:+        obj = JS_NULL;+        break;+    case BC_TAG_UNDEFINED:+        obj = JS_UNDEFINED;+        break;+    case BC_TAG_BOOL_FALSE:+    case BC_TAG_BOOL_TRUE:+        obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE);+        break;+    case BC_TAG_INT32:+        {+            int32_t val;+            if (bc_get_sleb128(s, &val))+                return JS_EXCEPTION;+            bc_read_trace(s, "%d\n", val);+            obj = JS_NewInt32(ctx, val);+        }+        break;+    case BC_TAG_FLOAT64:+        {+            JSFloat64Union u;+            if (bc_get_u64(s, &u.u64))+                return JS_EXCEPTION;+            bc_read_trace(s, "%g\n", u.d);+            obj = __JS_NewFloat64(ctx, u.d);+        }+        break;+    case BC_TAG_STRING:+        {+            JSString *p;+            p = JS_ReadString(s);+            if (!p)+                return JS_EXCEPTION;+            obj = JS_MKPTR(JS_TAG_STRING, p);+        }+        break;+    case BC_TAG_FUNCTION_BYTECODE:+        if (!s->allow_bytecode)+            goto invalid_tag;+        obj = JS_ReadFunctionTag(s);+        break;+    case BC_TAG_MODULE:+        if (!s->allow_bytecode)+            goto invalid_tag;+        obj = JS_ReadModule(s);+        break;+    case BC_TAG_OBJECT:+        obj = JS_ReadObjectTag(s);+        break;+    case BC_TAG_ARRAY:+    case BC_TAG_TEMPLATE_OBJECT:+        obj = JS_ReadArray(s, tag);+        break;+    case BC_TAG_TYPED_ARRAY:+        obj = JS_ReadTypedArray(s);+        break;+    case BC_TAG_ARRAY_BUFFER:+        obj = JS_ReadArrayBuffer(s);+        break;+    case BC_TAG_SHARED_ARRAY_BUFFER:+        if (!s->allow_sab || !ctx->rt->sab_funcs.sab_dup)+            goto invalid_tag;+        obj = JS_ReadSharedArrayBuffer(s);+        break;+    case BC_TAG_DATE:+        obj = JS_ReadDate(s);+        break;+    case BC_TAG_OBJECT_VALUE:+        obj = JS_ReadObjectValue(s);+        break;+#ifdef CONFIG_BIGNUM+    case BC_TAG_BIG_INT:+    case BC_TAG_BIG_FLOAT:+    case BC_TAG_BIG_DECIMAL:+        obj = JS_ReadBigNum(s, tag);+        break;+#endif+    case BC_TAG_OBJECT_REFERENCE:+        {+            uint32_t val;+            if (!s->allow_reference)+                return JS_ThrowSyntaxError(ctx, "object references are not allowed");+            if (bc_get_leb128(s, &val))+                return JS_EXCEPTION;+            bc_read_trace(s, "%u\n", val);+            if (val >= s->objects_count) {+                return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)",+                                           val, s->objects_count);+            }+            obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val]));+        }+        break;+    default:+    invalid_tag:+        return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)",+                                   tag, (unsigned int)(s->ptr - s->buf_start));+    }+    bc_read_trace(s, "}\n");+    return obj;+}++static int JS_ReadObjectAtoms(BCReaderState *s)+{+    uint8_t v8;+    JSString *p;+    int i;+    JSAtom atom;++    if (bc_get_u8(s, &v8))+        return -1;+    /* XXX: could support byte swapped input */+    if (v8 != BC_VERSION) {+        JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",+                            v8, BC_VERSION);+        return -1;+    }+    if (bc_get_leb128(s, &s->idx_to_atom_count))+        return -1;++    bc_read_trace(s, "%d atom indexes {\n", s->idx_to_atom_count);++    if (s->idx_to_atom_count != 0) {+        s->idx_to_atom = js_mallocz(s->ctx, s->idx_to_atom_count *+                                    sizeof(s->idx_to_atom[0]));+        if (!s->idx_to_atom)+            return s->error_state = -1;+    }+    for(i = 0; i < s->idx_to_atom_count; i++) {+        p = JS_ReadString(s);+        if (!p)+            return -1;+        atom = JS_NewAtomStr(s->ctx, p);+        if (atom == JS_ATOM_NULL)+            return s->error_state = -1;+        s->idx_to_atom[i] = atom;+        if (s->is_rom_data && (atom != (i + s->first_atom)))+            s->is_rom_data = FALSE; /* atoms must be relocated */+    }+    bc_read_trace(s, "}\n");+    return 0;+}++static void bc_reader_free(BCReaderState *s)+{+    int i;+    if (s->idx_to_atom) {+        for(i = 0; i < s->idx_to_atom_count; i++) {+            JS_FreeAtom(s->ctx, s->idx_to_atom[i]);+        }+        js_free(s->ctx, s->idx_to_atom);+    }+    js_free(s->ctx, s->objects);+}++JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,+                       int flags)+{+    BCReaderState ss, *s = &ss;+    JSValue obj;++    ctx->binary_object_count += 1;+    ctx->binary_object_size += buf_len;++    memset(s, 0, sizeof(*s));+    s->ctx = ctx;+    s->buf_start = buf;+    s->buf_end = buf + buf_len;+    s->ptr = buf;+    s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0);+    s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0);+    s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0);+    s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0);+    if (s->allow_bytecode)+        s->first_atom = JS_ATOM_END;+    else+        s->first_atom = 1;+    if (JS_ReadObjectAtoms(s)) {+        obj = JS_EXCEPTION;+    } else {+        obj = JS_ReadObjectRec(s);+    }+    bc_reader_free(s);+    return obj;+}++/*******************************************************************/+/* runtime functions & objects */++static JSValue js_string_constructor(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv);+static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv);+static JSValue js_number_constructor(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv);++static int check_function(JSContext *ctx, JSValueConst obj)+{+    if (likely(JS_IsFunction(ctx, obj)))+        return 0;+    JS_ThrowTypeError(ctx, "not a function");+    return -1;+}++static int check_exception_free(JSContext *ctx, JSValue obj)+{+    JS_FreeValue(ctx, obj);+    return JS_IsException(obj);+}++static JSAtom find_atom(JSContext *ctx, const char *name)+{+    JSAtom atom;+    int len;++    if (*name == '[') {+        name++;+        len = strlen(name) - 1;+        /* We assume 8 bit non null strings, which is the case for these+           symbols */+        for(atom = JS_ATOM_Symbol_toPrimitive; atom < JS_ATOM_END; atom++) {+            JSAtomStruct *p = ctx->rt->atom_array[atom];+            JSString *str = p;+            if (str->len == len && !memcmp(str->u.str8, name, len))+                return JS_DupAtom(ctx, atom);+        }+        abort();+    } else {+        atom = JS_NewAtom(ctx, name);+    }+    return atom;+}++static JSValue JS_InstantiateFunctionListItem2(JSContext *ctx, JSObject *p,+                                               JSAtom atom, void *opaque)+{+    const JSCFunctionListEntry *e = opaque;+    JSValue val;++    switch(e->def_type) {+    case JS_DEF_CFUNC:+        val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,+                               e->name, e->u.func.length, e->u.func.cproto, e->magic);+        break;+    case JS_DEF_PROP_STRING:+        val = JS_NewAtomString(ctx, e->u.str);+        break;+    case JS_DEF_OBJECT:+        val = JS_NewObject(ctx);+        JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);+        break;+    default:+        abort();+    }+    return val;+}++static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,+                                          JSAtom atom,+                                          const JSCFunctionListEntry *e)+{+    JSValue val;+    int prop_flags = e->prop_flags;++    switch(e->def_type) {+    case JS_DEF_ALIAS: /* using autoinit for aliases is not safe */+        {+            JSAtom atom1 = find_atom(ctx, e->u.alias.name);+            switch (e->u.alias.base) {+            case -1:+                val = JS_GetProperty(ctx, obj, atom1);+                break;+            case 0:+                val = JS_GetProperty(ctx, ctx->global_obj, atom1);+                break;+            case 1:+                val = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], atom1);+                break;+            default:+                abort();+            }+            JS_FreeAtom(ctx, atom1);+            if (atom == JS_ATOM_Symbol_toPrimitive) {+                /* Symbol.toPrimitive functions are not writable */+                prop_flags = JS_PROP_CONFIGURABLE;+            } else if (atom == JS_ATOM_Symbol_hasInstance) {+                /* Function.prototype[Symbol.hasInstance] is not writable nor configurable */+                prop_flags = 0;+            }+        }+        break;+    case JS_DEF_CFUNC:+        if (atom == JS_ATOM_Symbol_toPrimitive) {+            /* Symbol.toPrimitive functions are not writable */+            prop_flags = JS_PROP_CONFIGURABLE;+        } else if (atom == JS_ATOM_Symbol_hasInstance) {+            /* Function.prototype[Symbol.hasInstance] is not writable nor configurable */+            prop_flags = 0;+        }+        JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,+                                  (void *)e, prop_flags);+        return 0;+    case JS_DEF_CGETSET: /* XXX: use autoinit again ? */+    case JS_DEF_CGETSET_MAGIC:+        {+            JSValue getter, setter;+            char buf[64];++            getter = JS_UNDEFINED;+            if (e->u.getset.get.generic) {+                snprintf(buf, sizeof(buf), "get %s", e->name);+                getter = JS_NewCFunction2(ctx, e->u.getset.get.generic,+                                          buf, 0, e->def_type == JS_DEF_CGETSET_MAGIC ? JS_CFUNC_getter_magic : JS_CFUNC_getter,+                                          e->magic);+            }+            setter = JS_UNDEFINED;+            if (e->u.getset.set.generic) {+                snprintf(buf, sizeof(buf), "set %s", e->name);+                setter = JS_NewCFunction2(ctx, e->u.getset.set.generic,+                                          buf, 1, e->def_type == JS_DEF_CGETSET_MAGIC ? JS_CFUNC_setter_magic : JS_CFUNC_setter,+                                          e->magic);+            }+            JS_DefinePropertyGetSet(ctx, obj, atom, getter, setter, prop_flags);+            return 0;+        }+        break;+    case JS_DEF_PROP_INT32:+        val = JS_NewInt32(ctx, e->u.i32);+        break;+    case JS_DEF_PROP_INT64:+        val = JS_NewInt64(ctx, e->u.i64);+        break;+    case JS_DEF_PROP_DOUBLE:+        val = __JS_NewFloat64(ctx, e->u.f64);+        break;+    case JS_DEF_PROP_UNDEFINED:+        val = JS_UNDEFINED;+        break;+    case JS_DEF_PROP_STRING:+    case JS_DEF_OBJECT:+        JS_DefineAutoInitProperty(ctx, obj, atom, JS_AUTOINIT_ID_PROP,+                                  (void *)e, prop_flags);+        return 0;+    default:+        abort();+    }+    JS_DefinePropertyValue(ctx, obj, atom, val, prop_flags);+    return 0;+}++void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,+                                const JSCFunctionListEntry *tab, int len)+{+    int i;++    for (i = 0; i < len; i++) {+        const JSCFunctionListEntry *e = &tab[i];+        JSAtom atom = find_atom(ctx, e->name);+        JS_InstantiateFunctionListItem(ctx, obj, atom, e);+        JS_FreeAtom(ctx, atom);+    }+}++int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,+                           const JSCFunctionListEntry *tab, int len)+{+    int i;+    for(i = 0; i < len; i++) {+        if (JS_AddModuleExport(ctx, m, tab[i].name))+            return -1;+    }+    return 0;+}++int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,+                           const JSCFunctionListEntry *tab, int len)+{+    int i;+    JSValue val;++    for(i = 0; i < len; i++) {+        const JSCFunctionListEntry *e = &tab[i];+        switch(e->def_type) {+        case JS_DEF_CFUNC:+            val = JS_NewCFunction2(ctx, e->u.func.cfunc.generic,+                                   e->name, e->u.func.length, e->u.func.cproto, e->magic);+            break;+        case JS_DEF_PROP_STRING:+            val = JS_NewString(ctx, e->u.str);+            break;+        case JS_DEF_PROP_INT32:+            val = JS_NewInt32(ctx, e->u.i32);+            break;+        case JS_DEF_PROP_INT64:+            val = JS_NewInt64(ctx, e->u.i64);+            break;+        case JS_DEF_PROP_DOUBLE:+            val = __JS_NewFloat64(ctx, e->u.f64);+            break;+        case JS_DEF_OBJECT:+            val = JS_NewObject(ctx);+            JS_SetPropertyFunctionList(ctx, val, e->u.prop_list.tab, e->u.prop_list.len);+            break;+        default:+            abort();+        }+        if (JS_SetModuleExport(ctx, m, e->name, val))+            return -1;+    }+    return 0;+}++/* Note: 'func_obj' is not necessarily a constructor */+static void JS_SetConstructor2(JSContext *ctx,+                               JSValueConst func_obj,+                               JSValueConst proto,+                               int proto_flags, int ctor_flags)+{+    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_prototype,+                           JS_DupValue(ctx, proto), proto_flags);+    JS_DefinePropertyValue(ctx, proto, JS_ATOM_constructor,+                           JS_DupValue(ctx, func_obj),+                           ctor_flags);+    set_cycle_flag(ctx, func_obj);+    set_cycle_flag(ctx, proto);+}++void JS_SetConstructor(JSContext *ctx, JSValueConst func_obj, +                       JSValueConst proto)+{+    JS_SetConstructor2(ctx, func_obj, proto,+                       0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+}++static void JS_NewGlobalCConstructor2(JSContext *ctx,+                                      JSValue func_obj,+                                      const char *name,+                                      JSValueConst proto)+{+    JS_DefinePropertyValueStr(ctx, ctx->global_obj, name,+                           JS_DupValue(ctx, func_obj),+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    JS_SetConstructor(ctx, func_obj, proto);+    JS_FreeValue(ctx, func_obj);+}++static JSValueConst JS_NewGlobalCConstructor(JSContext *ctx, const char *name,+                                             JSCFunction *func, int length,+                                             JSValueConst proto)+{+    JSValue func_obj;+    func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0);+    JS_NewGlobalCConstructor2(ctx, func_obj, name, proto);+    return func_obj;+}++static JSValueConst JS_NewGlobalCConstructorOnly(JSContext *ctx, const char *name,+                                                 JSCFunction *func, int length,+                                                 JSValueConst proto)+{+    JSValue func_obj;+    func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor, 0);+    JS_NewGlobalCConstructor2(ctx, func_obj, name, proto);+    return func_obj;+}++static JSValue js_global_eval(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    return JS_EvalObject(ctx, ctx->global_obj, argv[0], JS_EVAL_TYPE_INDIRECT, -1);+}++static JSValue js_global_isNaN(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    double d;++    /* XXX: does this work for bigfloat? */+    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))+        return JS_EXCEPTION;+    return JS_NewBool(ctx, isnan(d));+}++static JSValue js_global_isFinite(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    BOOL res;+    double d;+    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))+        return JS_EXCEPTION;+    res = isfinite(d);+    return JS_NewBool(ctx, res);+}++/* Object class */++static JSValue JS_ToObject(JSContext *ctx, JSValueConst val)+{+    int tag = JS_VALUE_GET_NORM_TAG(val);+    JSValue obj;++    switch(tag) {+    default:+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+        return JS_ThrowTypeError(ctx, "cannot convert to object");+    case JS_TAG_OBJECT:+    case JS_TAG_EXCEPTION:+        return JS_DupValue(ctx, val);+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_INT);+        goto set_value;+    case JS_TAG_BIG_FLOAT:+        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_FLOAT);+        goto set_value;+    case JS_TAG_BIG_DECIMAL:+        obj = JS_NewObjectClass(ctx, JS_CLASS_BIG_DECIMAL);+        goto set_value;+#endif+    case JS_TAG_INT:+    case JS_TAG_FLOAT64:+        obj = JS_NewObjectClass(ctx, JS_CLASS_NUMBER);+        goto set_value;+    case JS_TAG_STRING:+        /* XXX: should call the string constructor */+        {+            JSString *p1 = JS_VALUE_GET_STRING(val);+            obj = JS_NewObjectClass(ctx, JS_CLASS_STRING);+            JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);+        }+        goto set_value;+    case JS_TAG_BOOL:+        obj = JS_NewObjectClass(ctx, JS_CLASS_BOOLEAN);+        goto set_value;+    case JS_TAG_SYMBOL:+        obj = JS_NewObjectClass(ctx, JS_CLASS_SYMBOL);+    set_value:+        if (!JS_IsException(obj))+            JS_SetObjectData(ctx, obj, JS_DupValue(ctx, val));+        return obj;+    }+}++static JSValue JS_ToObjectFree(JSContext *ctx, JSValue val)+{+    JSValue obj = JS_ToObject(ctx, val);+    JS_FreeValue(ctx, val);+    return obj;+}++static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,+                          JSValueConst desc)+{+    JSValue val, getter, setter;+    int flags;++    if (!JS_IsObject(desc)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    flags = 0;+    val = JS_UNDEFINED;+    getter = JS_UNDEFINED;+    setter = JS_UNDEFINED;+    if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) {+        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable);+        if (JS_IsException(prop))+            goto fail;+        flags |= JS_PROP_HAS_CONFIGURABLE;+        if (JS_ToBoolFree(ctx, prop))+            flags |= JS_PROP_CONFIGURABLE;+    }+    if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) {+        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable);+        if (JS_IsException(prop))+            goto fail;+        flags |= JS_PROP_HAS_WRITABLE;+        if (JS_ToBoolFree(ctx, prop))+            flags |= JS_PROP_WRITABLE;+    }+    if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) {+        JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);+        if (JS_IsException(prop))+            goto fail;+        flags |= JS_PROP_HAS_ENUMERABLE;+        if (JS_ToBoolFree(ctx, prop))+            flags |= JS_PROP_ENUMERABLE;+    }+    if (JS_HasProperty(ctx, desc, JS_ATOM_value)) {+        flags |= JS_PROP_HAS_VALUE;+        val = JS_GetProperty(ctx, desc, JS_ATOM_value);+        if (JS_IsException(val))+            goto fail;+    }+    if (JS_HasProperty(ctx, desc, JS_ATOM_get)) {+        flags |= JS_PROP_HAS_GET;+        getter = JS_GetProperty(ctx, desc, JS_ATOM_get);+        if (JS_IsException(getter) ||+            !(JS_IsUndefined(getter) || JS_IsFunction(ctx, getter))) {+            JS_ThrowTypeError(ctx, "invalid getter");+            goto fail;+        }+    }+    if (JS_HasProperty(ctx, desc, JS_ATOM_set)) {+        flags |= JS_PROP_HAS_SET;+        setter = JS_GetProperty(ctx, desc, JS_ATOM_set);+        if (JS_IsException(setter) ||+            !(JS_IsUndefined(setter) || JS_IsFunction(ctx, setter))) {+            JS_ThrowTypeError(ctx, "invalid setter");+            goto fail;+        }+    }+    if ((flags & (JS_PROP_HAS_SET | JS_PROP_HAS_GET)) &&+        (flags & (JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE))) {+        JS_ThrowTypeError(ctx, "cannot have setter/getter and value or writable");+        goto fail;+    }+    d->flags = flags;+    d->value = val;+    d->getter = getter;+    d->setter = setter;+    return 0;+ fail:+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, getter);+    JS_FreeValue(ctx, setter);+    return -1;+}++static __exception int JS_DefinePropertyDesc(JSContext *ctx, JSValueConst obj,+                                             JSAtom prop, JSValueConst desc,+                                             int flags)+{+    JSPropertyDescriptor d;+    int ret;++    if (js_obj_to_desc(ctx, &d, desc) < 0)+        return -1;++    ret = JS_DefineProperty(ctx, obj, prop,+                            d.value, d.getter, d.setter, d.flags | flags);+    js_free_desc(ctx, &d);+    return ret;+}++static __exception int JS_ObjectDefineProperties(JSContext *ctx,+                                                 JSValueConst obj,+                                                 JSValueConst properties)+{+    JSValue props, desc;+    JSObject *p;+    JSPropertyEnum *atoms;+    uint32_t len, i;+    int ret = -1;++    if (!JS_IsObject(obj)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    desc = JS_UNDEFINED;+    props = JS_ToObject(ctx, properties);+    if (JS_IsException(props))+        return -1;+    p = JS_VALUE_GET_OBJ(props);+    if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0)+        goto exception;+    for(i = 0; i < len; i++) {+        JS_FreeValue(ctx, desc);+        desc = JS_GetProperty(ctx, props, atoms[i].atom);+        if (JS_IsException(desc))+            goto exception;+        if (JS_DefinePropertyDesc(ctx, obj, atoms[i].atom, desc, JS_PROP_THROW) < 0)+            goto exception;+    }+    ret = 0;++exception:+    js_free_prop_enum(ctx, atoms, len);+    JS_FreeValue(ctx, props);+    JS_FreeValue(ctx, desc);+    return ret;+}++static JSValue js_object_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue ret;+    if (!JS_IsUndefined(new_target) &&+        JS_VALUE_GET_OBJ(new_target) !=+        JS_VALUE_GET_OBJ(JS_GetActiveFunction(ctx))) {+        ret = js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);+    } else {+        int tag = JS_VALUE_GET_NORM_TAG(argv[0]);+        switch(tag) {+        case JS_TAG_NULL:+        case JS_TAG_UNDEFINED:+            ret = JS_NewObject(ctx);+            break;+        default:+            ret = JS_ToObject(ctx, argv[0]);+            break;+        }+    }+    return ret;+}++static JSValue js_object_create(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValueConst proto, props;+    JSValue obj;++    proto = argv[0];+    if (!JS_IsObject(proto) && !JS_IsNull(proto))+        return JS_ThrowTypeError(ctx, "not a prototype");+    obj = JS_NewObjectProto(ctx, proto);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    props = argv[1];+    if (!JS_IsUndefined(props)) {+        if (JS_ObjectDefineProperties(ctx, obj, props)) {+            JS_FreeValue(ctx, obj);+            return JS_EXCEPTION;+        }+    }+    return obj;+}++static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv, int magic)+{+    JSValueConst val;++    val = argv[0];+    if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) {+        /* ES6 feature non compatible with ES5.1: primitive types are+           accepted */+        if (magic || JS_VALUE_GET_TAG(val) == JS_TAG_NULL ||+            JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED)+            return JS_ThrowTypeErrorNotAnObject(ctx);+    }+    return JS_GetPrototype(ctx, val);+}++static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    JSValueConst obj;+    obj = argv[0];+    if (JS_SetPrototypeInternal(ctx, obj, argv[1], TRUE) < 0)+        return JS_EXCEPTION;+    return JS_DupValue(ctx, obj);+}++/* magic = 1 if called as Reflect.defineProperty */+static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv, int magic)+{+    JSValueConst obj, prop, desc;+    int ret, flags;+    JSAtom atom;++    obj = argv[0];+    prop = argv[1];+    desc = argv[2];++    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    flags = 0;+    if (!magic)+        flags |= JS_PROP_THROW;+    ret = JS_DefinePropertyDesc(ctx, obj, atom, desc, flags);+    JS_FreeAtom(ctx, atom);+    if (ret < 0) {+        return JS_EXCEPTION;+    } else if (magic) {+        return JS_NewBool(ctx, ret);+    } else {+        return JS_DupValue(ctx, obj);+    }+}++static JSValue js_object_defineProperties(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv)+{+    // defineProperties(obj, properties)+    JSValueConst obj = argv[0];++    if (JS_ObjectDefineProperties(ctx, obj, argv[1]))+        return JS_EXCEPTION;+    else+        return JS_DupValue(ctx, obj);+}++/* magic = 1 if called as __defineSetter__ */+static JSValue js_object___defineGetter__(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv, int magic)+{+    JSValue obj;+    JSValueConst prop, value, get, set;+    int ret, flags;+    JSAtom atom;++    prop = argv[0];+    value = argv[1];++    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        return JS_EXCEPTION;++    if (check_function(ctx, value)) {+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL)) {+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    flags = JS_PROP_THROW |+        JS_PROP_HAS_ENUMERABLE | JS_PROP_ENUMERABLE |+        JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE;+    if (magic) {+        get = JS_UNDEFINED;+        set = value;+        flags |= JS_PROP_HAS_SET;+    } else {+        get = value;+        set = JS_UNDEFINED;+        flags |= JS_PROP_HAS_GET;+    }+    ret = JS_DefineProperty(ctx, obj, atom, JS_UNDEFINED, get, set, flags);+    JS_FreeValue(ctx, obj);+    JS_FreeAtom(ctx, atom);+    if (ret < 0) {+        return JS_EXCEPTION;+    } else {+        return JS_UNDEFINED;+    }+}++static JSValue js_object_getOwnPropertyDescriptor(JSContext *ctx, JSValueConst this_val,+                                                  int argc, JSValueConst *argv, int magic)+{+    JSValueConst prop;+    JSAtom atom;+    JSValue ret, obj;+    JSPropertyDescriptor desc;+    int res, flags;++    if (magic) {+        /* Reflect.getOwnPropertyDescriptor case */+        if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)+            return JS_ThrowTypeErrorNotAnObject(ctx);+        obj = JS_DupValue(ctx, argv[0]);+    } else {+        obj = JS_ToObject(ctx, argv[0]);+        if (JS_IsException(obj))+            return obj;+    }+    prop = argv[1];+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL))+        goto exception;+    ret = JS_UNDEFINED;+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), atom);+        if (res < 0)+            goto exception;+        if (res) {+            ret = JS_NewObject(ctx);+            if (JS_IsException(ret))+                goto exception1;+            flags = JS_PROP_C_W_E | JS_PROP_THROW;+            if (desc.flags & JS_PROP_GETSET) {+                if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, desc.getter), flags) < 0+                ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, desc.setter), flags) < 0)+                    goto exception1;+            } else {+                if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, desc.value), flags) < 0+                ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,+                                           JS_NewBool(ctx, (desc.flags & JS_PROP_WRITABLE) != 0), flags) < 0)+                    goto exception1;+            }+            if (JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,+                                       JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0), flags) < 0+            ||  JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,+                                       JS_NewBool(ctx, (desc.flags & JS_PROP_CONFIGURABLE) != 0), flags) < 0)+                goto exception1;+            js_free_desc(ctx, &desc);+        }+    }+    JS_FreeAtom(ctx, atom);+    JS_FreeValue(ctx, obj);+    return ret;++exception1:+    js_free_desc(ctx, &desc);+    JS_FreeValue(ctx, ret);+exception:+    JS_FreeAtom(ctx, atom);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst this_val,+                                                   int argc, JSValueConst *argv)+{+    //getOwnPropertyDescriptors(obj)+    JSValue obj, r;+    JSObject *p;+    JSPropertyEnum *props;+    uint32_t len, i;++    r = JS_UNDEFINED;+    obj = JS_ToObject(ctx, argv[0]);+    if (JS_IsException(obj))+        return JS_EXCEPTION;++    p = JS_VALUE_GET_OBJ(obj);+    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p,+                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK))+        goto exception;+    r = JS_NewObject(ctx);+    if (JS_IsException(r))+        goto exception;+    for(i = 0; i < len; i++) {+        JSValue atomValue, desc;+        JSValueConst args[2];++        atomValue = JS_AtomToValue(ctx, props[i].atom);+        if (JS_IsException(atomValue))+            goto exception;+        args[0] = obj;+        args[1] = atomValue;+        desc = js_object_getOwnPropertyDescriptor(ctx, JS_UNDEFINED, 2, args, 0);+        JS_FreeValue(ctx, atomValue);+        if (JS_IsException(desc))+            goto exception;+        if (!JS_IsUndefined(desc)) {+            if (JS_DefinePropertyValue(ctx, r, props[i].atom, desc,+                                       JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    js_free_prop_enum(ctx, props, len);+    JS_FreeValue(ctx, obj);+    return r;++exception:+    js_free_prop_enum(ctx, props, len);+    JS_FreeValue(ctx, obj);+    JS_FreeValue(ctx, r);+    return JS_EXCEPTION;+}++static JSValue JS_GetOwnPropertyNames2(JSContext *ctx, JSValueConst obj1,+                                       int flags, int kind)+{+    JSValue obj, r, val, key, value;+    JSObject *p;+    JSPropertyEnum *atoms;+    uint32_t len, i, j;++    r = JS_UNDEFINED;+    val = JS_UNDEFINED;+    obj = JS_ToObject(ctx, obj1);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    p = JS_VALUE_GET_OBJ(obj);+    if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, flags & ~JS_GPN_ENUM_ONLY))+        goto exception;+    r = JS_NewArray(ctx);+    if (JS_IsException(r))+        goto exception;+    for(j = i = 0; i < len; i++) {+        JSAtom atom = atoms[i].atom;+        if (flags & JS_GPN_ENUM_ONLY) {+            JSPropertyDescriptor desc;+            int res;++            /* Check if property is still enumerable */+            res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);+            if (res < 0)+                goto exception;+            if (!res)+                continue;+            js_free_desc(ctx, &desc);+            if (!(desc.flags & JS_PROP_ENUMERABLE))+                continue;+        }+        switch(kind) {+        default:+        case JS_ITERATOR_KIND_KEY:+            val = JS_AtomToValue(ctx, atom);+            if (JS_IsException(val))+                goto exception;+            break;+        case JS_ITERATOR_KIND_VALUE:+            val = JS_GetProperty(ctx, obj, atom);+            if (JS_IsException(val))+                goto exception;+            break;+        case JS_ITERATOR_KIND_KEY_AND_VALUE:+            val = JS_NewArray(ctx);+            if (JS_IsException(val))+                goto exception;+            key = JS_AtomToValue(ctx, atom);+            if (JS_IsException(key))+                goto exception1;+            if (JS_CreateDataPropertyUint32(ctx, val, 0, key, JS_PROP_THROW) < 0)+                goto exception1;+            value = JS_GetProperty(ctx, obj, atom);+            if (JS_IsException(value))+                goto exception1;+            if (JS_CreateDataPropertyUint32(ctx, val, 1, value, JS_PROP_THROW) < 0)+                goto exception1;+            break;+        }+        if (JS_CreateDataPropertyUint32(ctx, r, j++, val, 0) < 0)+            goto exception;+    }+    goto done;++exception1:+    JS_FreeValue(ctx, val);+exception:+    JS_FreeValue(ctx, r);+    r = JS_EXCEPTION;+done:+    js_free_prop_enum(ctx, atoms, len);+    JS_FreeValue(ctx, obj);+    return r;+}++static JSValue js_object_getOwnPropertyNames(JSContext *ctx, JSValueConst this_val,+                                             int argc, JSValueConst *argv)+{+    return JS_GetOwnPropertyNames2(ctx, argv[0],+                                   JS_GPN_STRING_MASK, JS_ITERATOR_KIND_KEY);+}++static JSValue js_object_getOwnPropertySymbols(JSContext *ctx, JSValueConst this_val,+                                             int argc, JSValueConst *argv)+{+    return JS_GetOwnPropertyNames2(ctx, argv[0],+                                   JS_GPN_SYMBOL_MASK, JS_ITERATOR_KIND_KEY);+}++static JSValue js_object_keys(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int kind)+{+    return JS_GetOwnPropertyNames2(ctx, argv[0],+                                   JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK, kind);+}++static JSValue js_object_isExtensible(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv, int reflect)+{+    JSValueConst obj;+    int ret;++    obj = argv[0];+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {+        if (reflect)+            return JS_ThrowTypeErrorNotAnObject(ctx);+        else+            return JS_FALSE;+    }+    ret = JS_IsExtensible(ctx, obj);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_object_preventExtensions(JSContext *ctx, JSValueConst this_val,+                                           int argc, JSValueConst *argv, int reflect)+{+    JSValueConst obj;+    int ret;++    obj = argv[0];+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) {+        if (reflect)+            return JS_ThrowTypeErrorNotAnObject(ctx);+        else+            return JS_DupValue(ctx, obj);+    }+    ret = JS_PreventExtensions(ctx, obj);+    if (ret < 0)+        return JS_EXCEPTION;+    if (reflect) {+        return JS_NewBool(ctx, ret);+    } else {+        if (!ret)+            return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");+        return JS_DupValue(ctx, obj);+    }+}++static JSValue js_object_hasOwnProperty(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    JSValue obj;+    JSAtom atom;+    JSObject *p;+    BOOL ret;++    atom = JS_ValueToAtom(ctx, argv[0]); /* must be done first */+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj)) {+        JS_FreeAtom(ctx, atom);+        return obj;+    }+    p = JS_VALUE_GET_OBJ(obj);+    ret = JS_GetOwnPropertyInternal(ctx, NULL, p, atom);+    JS_FreeAtom(ctx, atom);+    JS_FreeValue(ctx, obj);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_object_valueOf(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return JS_ToObject(ctx, this_val);+}++static JSValue js_object_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValue obj, tag;+    int is_array;+    JSAtom atom;+    JSObject *p;++    if (JS_IsNull(this_val)) {+        tag = JS_NewString(ctx, "Null");+    } else if (JS_IsUndefined(this_val)) {+        tag = JS_NewString(ctx, "Undefined");+    } else {+        obj = JS_ToObject(ctx, this_val);+        if (JS_IsException(obj))+            return obj;+        is_array = JS_IsArray(ctx, obj);+        if (is_array < 0) {+            JS_FreeValue(ctx, obj);+            return JS_EXCEPTION;+        }+        if (is_array) {+            atom = JS_ATOM_Array;+        } else if (JS_IsFunction(ctx, obj)) {+            atom = JS_ATOM_Function;+        } else {+            p = JS_VALUE_GET_OBJ(obj);+            switch(p->class_id) {+            case JS_CLASS_STRING:+            case JS_CLASS_ARGUMENTS:+            case JS_CLASS_MAPPED_ARGUMENTS:+            case JS_CLASS_ERROR:+            case JS_CLASS_BOOLEAN:+            case JS_CLASS_NUMBER:+            case JS_CLASS_DATE:+            case JS_CLASS_REGEXP:+                atom = ctx->rt->class_array[p->class_id].class_name;+                break;+            default:+                atom = JS_ATOM_Object;+                break;+            }+        }+        tag = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_toStringTag);+        JS_FreeValue(ctx, obj);+        if (JS_IsException(tag))+            return JS_EXCEPTION;+        if (!JS_IsString(tag)) {+            JS_FreeValue(ctx, tag);+            tag = JS_AtomToString(ctx, atom);+        }+    }+    return JS_ConcatString3(ctx, "[object ", tag, "]");+}++static JSValue js_object_toLocaleString(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    return JS_Invoke(ctx, this_val, JS_ATOM_toString, 0, NULL);+}++static JSValue js_object_assign(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    // Object.assign(obj, source1)+    JSValue obj, s;+    int i;++    s = JS_UNDEFINED;+    obj = JS_ToObject(ctx, argv[0]);+    if (JS_IsException(obj))+        goto exception;+    for (i = 1; i < argc; i++) {+        if (!JS_IsNull(argv[i]) && !JS_IsUndefined(argv[i])) {+            s = JS_ToObject(ctx, argv[i]);+            if (JS_IsException(s))+                goto exception;+            if (JS_CopyDataProperties(ctx, obj, s, JS_UNDEFINED, TRUE))+                goto exception;+            JS_FreeValue(ctx, s);+        }+    }+    return obj;+exception:+    JS_FreeValue(ctx, obj);+    JS_FreeValue(ctx, s);+    return JS_EXCEPTION;+}++static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int freeze_flag)+{+    JSValueConst obj = argv[0];+    JSObject *p;+    JSPropertyEnum *props;+    uint32_t len, i;+    int flags, desc_flags, res;++    if (!JS_IsObject(obj))+        return JS_DupValue(ctx, obj);++    res = JS_PreventExtensions(ctx, obj);+    if (res < 0)+        return JS_EXCEPTION;+    if (!res) {+        return JS_ThrowTypeError(ctx, "proxy preventExtensions handler returned false");+    }+    +    p = JS_VALUE_GET_OBJ(obj);+    flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;+    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))+        return JS_EXCEPTION;++    for(i = 0; i < len; i++) {+        JSPropertyDescriptor desc;+        JSAtom prop = props[i].atom;++        desc_flags = JS_PROP_THROW | JS_PROP_HAS_CONFIGURABLE;+        if (freeze_flag) {+            res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);+            if (res < 0)+                goto exception;+            if (res) {+                if (desc.flags & JS_PROP_WRITABLE)+                    desc_flags |= JS_PROP_HAS_WRITABLE;+                js_free_desc(ctx, &desc);+            }+        }+        if (JS_DefineProperty(ctx, obj, prop, JS_UNDEFINED,+                              JS_UNDEFINED, JS_UNDEFINED, desc_flags) < 0)+            goto exception;+    }+    js_free_prop_enum(ctx, props, len);+    return JS_DupValue(ctx, obj);++ exception:+    js_free_prop_enum(ctx, props, len);+    return JS_EXCEPTION;+}++static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv, int is_frozen)+{+    JSValueConst obj = argv[0];+    JSObject *p;+    JSPropertyEnum *props;+    uint32_t len, i;+    int flags, res;+    +    if (!JS_IsObject(obj))+        return JS_TRUE;++    p = JS_VALUE_GET_OBJ(obj);+    flags = JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK;+    if (JS_GetOwnPropertyNamesInternal(ctx, &props, &len, p, flags))+        return JS_EXCEPTION;++    for(i = 0; i < len; i++) {+        JSPropertyDescriptor desc;+        JSAtom prop = props[i].atom;++        res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);+        if (res < 0)+            goto exception;+        if (res) {+            js_free_desc(ctx, &desc);+            if ((desc.flags & JS_PROP_CONFIGURABLE)+            ||  (is_frozen && (desc.flags & JS_PROP_WRITABLE))) {+                res = FALSE;+                goto done;+            }+        }+    }+    res = JS_IsExtensible(ctx, obj);+    if (res < 0)+        return JS_EXCEPTION;+    res ^= 1;+done:        +    js_free_prop_enum(ctx, props, len);+    return JS_NewBool(ctx, res);++exception:+    js_free_prop_enum(ctx, props, len);+    return JS_EXCEPTION;+}++static JSValue js_object_fromEntries(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue obj, iter, next_method = JS_UNDEFINED;+    JSValueConst iterable;+    BOOL done;++    /*  RequireObjectCoercible() not necessary because it is tested in+        JS_GetIterator() by JS_GetProperty() */+    iterable = argv[0];++    obj = JS_NewObject(ctx);+    if (JS_IsException(obj))+        return obj;+    +    iter = JS_GetIterator(ctx, iterable, FALSE);+    if (JS_IsException(iter))+        goto fail;+    next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);+    if (JS_IsException(next_method))+        goto fail;+    +    for(;;) {+        JSValue key, value, item;+        item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);+        if (JS_IsException(item))+            goto fail;+        if (done) {+            JS_FreeValue(ctx, item);+            break;+        }+        +        key = JS_UNDEFINED;+        value = JS_UNDEFINED;+        if (!JS_IsObject(item)) {+            JS_ThrowTypeErrorNotAnObject(ctx);+            goto fail1;+        }+        key = JS_GetPropertyUint32(ctx, item, 0);+        if (JS_IsException(key))+            goto fail1;+        value = JS_GetPropertyUint32(ctx, item, 1);+        if (JS_IsException(value)) {+            JS_FreeValue(ctx, key);+            goto fail1;+        }+        if (JS_DefinePropertyValueValue(ctx, obj, key, value,+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0) {+        fail1:+            JS_FreeValue(ctx, item);+            goto fail;+        }+        JS_FreeValue(ctx, item);+    }+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    return obj;+ fail:+    if (JS_IsObject(iter)) {+        /* close the iterator object, preserving pending exception */+        JS_IteratorClose(ctx, iter, TRUE);+    }+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++#if 0+/* Note: corresponds to ECMA spec: CreateDataPropertyOrThrow() */+static JSValue js_object___setOwnProperty(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv)+{+    int ret;+    ret = JS_DefinePropertyValueValue(ctx, argv[0], JS_DupValue(ctx, argv[1]),+                                      JS_DupValue(ctx, argv[2]),+                                      JS_PROP_C_W_E | JS_PROP_THROW);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_object___toObject(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    return JS_ToObject(ctx, argv[0]);+}++static JSValue js_object___toPrimitive(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    int hint = HINT_NONE;++    if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT)+        hint = JS_VALUE_GET_INT(argv[1]);++    return JS_ToPrimitive(ctx, argv[0], hint);+}+#endif++/* return an empty string if not an object */+static JSValue js_object___getClass(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSAtom atom;+    JSObject *p;+    uint32_t tag;+    int class_id;++    tag = JS_VALUE_GET_NORM_TAG(argv[0]);+    if (tag == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(argv[0]);+        class_id = p->class_id;+        if (class_id == JS_CLASS_PROXY && JS_IsFunction(ctx, argv[0]))+            class_id = JS_CLASS_BYTECODE_FUNCTION;+        atom = ctx->rt->class_array[class_id].class_name;+    } else {+        atom = JS_ATOM_empty_string;+    }+    return JS_AtomToString(ctx, atom);+}++static JSValue js_object_is(JSContext *ctx, JSValueConst this_val,+                            int argc, JSValueConst *argv)+{+    return JS_NewBool(ctx, js_same_value(ctx, argv[0], argv[1]));+}++#if 0+static JSValue js_object___getObjectData(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    return JS_GetObjectData(ctx, argv[0]);+}++static JSValue js_object___setObjectData(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    if (JS_SetObjectData(ctx, argv[0], JS_DupValue(ctx, argv[1])))+        return JS_EXCEPTION;+    return JS_DupValue(ctx, argv[1]);+}++static JSValue js_object___toPropertyKey(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    return JS_ToPropertyKey(ctx, argv[0]);+}++static JSValue js_object___isObject(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    return JS_NewBool(ctx, JS_IsObject(argv[0]));+}++static JSValue js_object___isSameValueZero(JSContext *ctx, JSValueConst this_val,+                                           int argc, JSValueConst *argv)+{+    return JS_NewBool(ctx, js_same_value_zero(ctx, argv[0], argv[1]));+}++static JSValue js_object___isConstructor(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    return JS_NewBool(ctx, JS_IsConstructor(ctx, argv[0]));+}+#endif++static JSValue JS_SpeciesConstructor(JSContext *ctx, JSValueConst obj,+                                     JSValueConst defaultConstructor)+{+    JSValue ctor, species;++    if (!JS_IsObject(obj))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    ctor = JS_GetProperty(ctx, obj, JS_ATOM_constructor);+    if (JS_IsException(ctor))+        return ctor;+    if (JS_IsUndefined(ctor))+        return JS_DupValue(ctx, defaultConstructor);+    if (!JS_IsObject(ctor)) {+        JS_FreeValue(ctx, ctor);+        return JS_ThrowTypeErrorNotAnObject(ctx);+    }+    species = JS_GetProperty(ctx, ctor, JS_ATOM_Symbol_species);+    JS_FreeValue(ctx, ctor);+    if (JS_IsException(species))+        return species;+    if (JS_IsUndefined(species) || JS_IsNull(species))+        return JS_DupValue(ctx, defaultConstructor);+    if (!JS_IsConstructor(ctx, species)) {+        JS_FreeValue(ctx, species);+        return JS_ThrowTypeError(ctx, "not a constructor");+    }+    return species;+}++#if 0+static JSValue js_object___speciesConstructor(JSContext *ctx, JSValueConst this_val,+                                              int argc, JSValueConst *argv)+{+    return JS_SpeciesConstructor(ctx, argv[0], argv[1]);+}+#endif++static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val)+{+    JSValue val, ret;++    val = JS_ToObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    ret = JS_GetPrototype(ctx, val);+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val,+                                       JSValueConst proto)+{+    if (JS_IsUndefined(this_val) || JS_IsNull(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    if (!JS_IsObject(proto) && !JS_IsNull(proto))+        return JS_UNDEFINED;+    if (JS_SetPrototypeInternal(ctx, this_val, proto, TRUE) < 0)+        return JS_EXCEPTION;+    else+        return JS_UNDEFINED;+}++static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValue obj, v1;+    JSValueConst v;+    int res;++    v = argv[0];+    if (!JS_IsObject(v))+        return JS_FALSE;+    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    v1 = JS_DupValue(ctx, v);+    for(;;) {+        v1 = JS_GetPrototypeFree(ctx, v1);+        if (JS_IsException(v1))+            goto exception;+        if (JS_IsNull(v1)) {+            res = FALSE;+            break;+        }+        if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) {+            res = TRUE;+            break;+        }+        /* avoid infinite loop (possible with proxies) */+        if (js_poll_interrupts(ctx))+            goto exception;+    }+    JS_FreeValue(ctx, v1);+    JS_FreeValue(ctx, obj);+    return JS_NewBool(ctx, res);++exception:+    JS_FreeValue(ctx, v1);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_object_propertyIsEnumerable(JSContext *ctx, JSValueConst this_val,+                                              int argc, JSValueConst *argv)+{+    JSValue obj, res = JS_EXCEPTION;+    JSAtom prop = JS_ATOM_NULL;+    JSPropertyDescriptor desc;+    int has_prop;++    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        goto exception;+    prop = JS_ValueToAtom(ctx, argv[0]);+    if (unlikely(prop == JS_ATOM_NULL))+        goto exception;++    has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop);+    if (has_prop < 0)+        goto exception;+    if (has_prop) {+        res = JS_NewBool(ctx, (desc.flags & JS_PROP_ENUMERABLE) != 0);+        js_free_desc(ctx, &desc);+    } else {+        res = JS_FALSE;+    }++exception:+    JS_FreeAtom(ctx, prop);+    JS_FreeValue(ctx, obj);+    return res;+}++static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv, int setter)+{+    JSValue obj, res = JS_EXCEPTION;+    JSAtom prop = JS_ATOM_NULL;+    JSPropertyDescriptor desc;+    int has_prop;++    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        goto exception;+    prop = JS_ValueToAtom(ctx, argv[0]);+    if (unlikely(prop == JS_ATOM_NULL))+        goto exception;++    for (;;) {+        has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop);+        if (has_prop < 0)+            goto exception;+        if (has_prop) {+            if (desc.flags & JS_PROP_GETSET)+                res = JS_DupValue(ctx, setter ? desc.setter : desc.getter);+            else+                res = JS_UNDEFINED;+            js_free_desc(ctx, &desc);+            break;+        }+        obj = JS_GetPrototypeFree(ctx, obj);+        if (JS_IsException(obj))+            goto exception;+        if (JS_IsNull(obj)) {+            res = JS_UNDEFINED;+            break;+        }+        /* avoid infinite loop (possible with proxies) */+        if (js_poll_interrupts(ctx))+            goto exception;+    }++exception:+    JS_FreeAtom(ctx, prop);+    JS_FreeValue(ctx, obj);+    return res;+}++static const JSCFunctionListEntry js_object_funcs[] = {+    JS_CFUNC_DEF("create", 2, js_object_create ),+    JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 0 ),+    JS_CFUNC_DEF("setPrototypeOf", 2, js_object_setPrototypeOf ),+    JS_CFUNC_MAGIC_DEF("defineProperty", 3, js_object_defineProperty, 0 ),+    JS_CFUNC_DEF("defineProperties", 2, js_object_defineProperties ),+    JS_CFUNC_DEF("getOwnPropertyNames", 1, js_object_getOwnPropertyNames ),+    JS_CFUNC_DEF("getOwnPropertySymbols", 1, js_object_getOwnPropertySymbols ),+    JS_CFUNC_MAGIC_DEF("keys", 1, js_object_keys, JS_ITERATOR_KIND_KEY ),+    JS_CFUNC_MAGIC_DEF("values", 1, js_object_keys, JS_ITERATOR_KIND_VALUE ),+    JS_CFUNC_MAGIC_DEF("entries", 1, js_object_keys, JS_ITERATOR_KIND_KEY_AND_VALUE ),+    JS_CFUNC_MAGIC_DEF("isExtensible", 1, js_object_isExtensible, 0 ),+    JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 0 ),+    JS_CFUNC_MAGIC_DEF("getOwnPropertyDescriptor", 2, js_object_getOwnPropertyDescriptor, 0 ),+    JS_CFUNC_DEF("getOwnPropertyDescriptors", 1, js_object_getOwnPropertyDescriptors ),+    JS_CFUNC_DEF("is", 2, js_object_is ),+    JS_CFUNC_DEF("assign", 2, js_object_assign ),+    JS_CFUNC_MAGIC_DEF("seal", 1, js_object_seal, 0 ),+    JS_CFUNC_MAGIC_DEF("freeze", 1, js_object_seal, 1 ),+    JS_CFUNC_MAGIC_DEF("isSealed", 1, js_object_isSealed, 0 ),+    JS_CFUNC_MAGIC_DEF("isFrozen", 1, js_object_isSealed, 1 ),+    JS_CFUNC_DEF("__getClass", 1, js_object___getClass ),+    //JS_CFUNC_DEF("__isObject", 1, js_object___isObject ),+    //JS_CFUNC_DEF("__isConstructor", 1, js_object___isConstructor ),+    //JS_CFUNC_DEF("__toObject", 1, js_object___toObject ),+    //JS_CFUNC_DEF("__setOwnProperty", 3, js_object___setOwnProperty ),+    //JS_CFUNC_DEF("__toPrimitive", 2, js_object___toPrimitive ),+    //JS_CFUNC_DEF("__toPropertyKey", 1, js_object___toPropertyKey ),+    //JS_CFUNC_DEF("__speciesConstructor", 2, js_object___speciesConstructor ),+    //JS_CFUNC_DEF("__isSameValueZero", 2, js_object___isSameValueZero ),+    //JS_CFUNC_DEF("__getObjectData", 1, js_object___getObjectData ),+    //JS_CFUNC_DEF("__setObjectData", 2, js_object___setObjectData ),+    JS_CFUNC_DEF("fromEntries", 1, js_object_fromEntries ),+};++static const JSCFunctionListEntry js_object_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_object_toString ),+    JS_CFUNC_DEF("toLocaleString", 0, js_object_toLocaleString ),+    JS_CFUNC_DEF("valueOf", 0, js_object_valueOf ),+    JS_CFUNC_DEF("hasOwnProperty", 1, js_object_hasOwnProperty ),+    JS_CFUNC_DEF("isPrototypeOf", 1, js_object_isPrototypeOf ),+    JS_CFUNC_DEF("propertyIsEnumerable", 1, js_object_propertyIsEnumerable ),+    JS_CGETSET_DEF("__proto__", js_object_get___proto__, js_object_set___proto__ ),+    JS_CFUNC_MAGIC_DEF("__defineGetter__", 2, js_object___defineGetter__, 0 ),+    JS_CFUNC_MAGIC_DEF("__defineSetter__", 2, js_object___defineGetter__, 1 ),+    JS_CFUNC_MAGIC_DEF("__lookupGetter__", 1, js_object___lookupGetter__, 0 ),+    JS_CFUNC_MAGIC_DEF("__lookupSetter__", 1, js_object___lookupGetter__, 1 ),+};++/* Function class */++static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return JS_UNDEFINED;+}++/* XXX: add a specific eval mode so that Function("}), ({") is rejected */+static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,+                                       int argc, JSValueConst *argv, int magic)+{+    JSFunctionKindEnum func_kind = magic;+    int i, n, ret;+    JSValue s, proto, obj = JS_UNDEFINED;+    StringBuffer b_s, *b = &b_s;++    string_buffer_init(ctx, b, 0);+    string_buffer_putc8(b, '(');+    +    if (func_kind == JS_FUNC_ASYNC || func_kind == JS_FUNC_ASYNC_GENERATOR) {+        string_buffer_puts8(b, "async ");+    }+    string_buffer_puts8(b, "function");++    if (func_kind == JS_FUNC_GENERATOR || func_kind == JS_FUNC_ASYNC_GENERATOR) {+        string_buffer_putc8(b, '*');+    }+    string_buffer_puts8(b, " anonymous(");++    n = argc - 1;+    for(i = 0; i < n; i++) {+        if (i != 0) {+            string_buffer_putc8(b, ',');+        }+        if (string_buffer_concat_value(b, argv[i]))+            goto fail;+    }+    string_buffer_puts8(b, "\n) {\n");+    if (n >= 0) {+        if (string_buffer_concat_value(b, argv[n]))+            goto fail;+    }+    string_buffer_puts8(b, "\n})");+    s = string_buffer_end(b);+    if (JS_IsException(s))+        goto fail1;++    obj = JS_EvalObject(ctx, ctx->global_obj, s, JS_EVAL_TYPE_INDIRECT, -1);+    JS_FreeValue(ctx, s);+    if (JS_IsException(obj))+        goto fail1;+    if (!JS_IsUndefined(new_target)) {+        /* set the prototype */+        proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);+        if (JS_IsException(proto))+            goto fail1;+        if (!JS_IsObject(proto)) {+            JSContext *realm;+            JS_FreeValue(ctx, proto);+            realm = JS_GetFunctionRealm(ctx, new_target);+            if (!realm)+                goto fail1;+            proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]);+        }+        ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);+        JS_FreeValue(ctx, proto);+        if (ret < 0)+            goto fail1;+    }+    return obj;++ fail:+    string_buffer_free(b);+ fail1:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static __exception int js_get_length32(JSContext *ctx, uint32_t *pres,+                                       JSValueConst obj)+{+    JSValue len_val;+    len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);+    if (JS_IsException(len_val)) {+        *pres = 0;+        return -1;+    }+    return JS_ToUint32Free(ctx, pres, len_val);+}++static __exception int js_get_length64(JSContext *ctx, int64_t *pres,+                                       JSValueConst obj)+{+    JSValue len_val;+    len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);+    if (JS_IsException(len_val)) {+        *pres = 0;+        return -1;+    }+    return JS_ToLengthFree(ctx, pres, len_val);+}++static void free_arg_list(JSContext *ctx, JSValue *tab, uint32_t len)+{+    uint32_t i;+    for(i = 0; i < len; i++) {+        JS_FreeValue(ctx, tab[i]);+    }+    js_free(ctx, tab);+}++/* XXX: should use ValueArray */+static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen,+                               JSValueConst array_arg)+{+    uint32_t len, i;+    JSValue *tab, ret;+    JSObject *p;++    if (JS_VALUE_GET_TAG(array_arg) != JS_TAG_OBJECT) {+        JS_ThrowTypeError(ctx, "not a object");+        return NULL;+    }+    if (js_get_length32(ctx, &len, array_arg))+        return NULL;+    /* avoid allocating 0 bytes */+    tab = js_mallocz(ctx, sizeof(tab[0]) * max_uint32(1, len));+    if (!tab)+        return NULL;+    p = JS_VALUE_GET_OBJ(array_arg);+    if ((p->class_id == JS_CLASS_ARRAY || p->class_id == JS_CLASS_ARGUMENTS) &&+        p->fast_array &&+        len == p->u.array.count) {+        for(i = 0; i < len; i++) {+            tab[i] = JS_DupValue(ctx, p->u.array.u.values[i]);+        }+    } else {+        for(i = 0; i < len; i++) {+            ret = JS_GetPropertyUint32(ctx, array_arg, i);+            if (JS_IsException(ret)) {+                free_arg_list(ctx, tab, i);+                return NULL;+            }+            tab[i] = ret;+        }+    }+    *plen = len;+    return tab;+}++/* magic value: 0 = normal apply, 1 = apply for constructor, 2 =+   Reflect.apply */+static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv, int magic)+{+    JSValueConst this_arg, array_arg;+    uint32_t len;+    JSValue *tab, ret;++    if (check_function(ctx, this_val))+        return JS_EXCEPTION;+    this_arg = argv[0];+    array_arg = argv[1];+    if ((JS_VALUE_GET_TAG(array_arg) == JS_TAG_UNDEFINED ||+         JS_VALUE_GET_TAG(array_arg) == JS_TAG_NULL) && magic != 2) {+        return JS_Call(ctx, this_val, this_arg, 0, NULL);+    }+    tab = build_arg_list(ctx, &len, array_arg);+    if (!tab)+        return JS_EXCEPTION;+    if (magic & 1) {+        ret = JS_CallConstructor2(ctx, this_val, this_arg, len, (JSValueConst *)tab);+    } else {+        ret = JS_Call(ctx, this_val, this_arg, len, (JSValueConst *)tab);+    }+    free_arg_list(ctx, tab, len);+    return ret;+}++static JSValue js_function_call(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    if (argc <= 0) {+        return JS_Call(ctx, this_val, JS_UNDEFINED, 0, NULL);+    } else {+        return JS_Call(ctx, this_val, argv[0], argc - 1, argv + 1);+    }+}++static JSValue js_function_bind(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSBoundFunction *bf;+    JSValue func_obj, name1, len_val;+    JSObject *p;+    int arg_count, i, ret;++    if (check_function(ctx, this_val))+        return JS_EXCEPTION;++    func_obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,+                                 JS_CLASS_BOUND_FUNCTION);+    if (JS_IsException(func_obj))+        return JS_EXCEPTION;+    p = JS_VALUE_GET_OBJ(func_obj);+    p->is_constructor = JS_IsConstructor(ctx, this_val);+    arg_count = max_int(0, argc - 1);+    bf = js_malloc(ctx, sizeof(*bf) + arg_count * sizeof(JSValue));+    if (!bf)+        goto exception;+    bf->func_obj = JS_DupValue(ctx, this_val);+    bf->this_val = JS_DupValue(ctx, argv[0]);+    bf->argc = arg_count;+    for(i = 0; i < arg_count; i++) {+        bf->argv[i] = JS_DupValue(ctx, argv[i + 1]);+    }+    p->u.bound_function = bf;++    /* XXX: the spec could be simpler by only using GetOwnProperty */+    ret = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_length);+    if (ret < 0)+        goto exception;+    if (!ret) {+        len_val = JS_NewInt32(ctx, 0);+    } else {+        len_val = JS_GetProperty(ctx, this_val, JS_ATOM_length);+        if (JS_IsException(len_val))+            goto exception;+        if (JS_VALUE_GET_TAG(len_val) == JS_TAG_INT) {+            /* most common case */+            int len1 = JS_VALUE_GET_INT(len_val);+            if (len1 <= arg_count)+                len1 = 0;+            else+                len1 -= arg_count;+            len_val = JS_NewInt32(ctx, len1);+        } else if (JS_VALUE_GET_NORM_TAG(len_val) == JS_TAG_FLOAT64) {+            double d = JS_VALUE_GET_FLOAT64(len_val);+            if (isnan(d)) {+                d = 0.0;+            } else {+                d = trunc(d);+                if (d <= (double)arg_count)+                    d = 0.0;+                else+                    d -= (double)arg_count; /* also converts -0 to +0 */+            }+            len_val = JS_NewFloat64(ctx, d);+        } else {+            JS_FreeValue(ctx, len_val);+            len_val = JS_NewInt32(ctx, 0);+        }+    }+    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_length,+                           len_val, JS_PROP_CONFIGURABLE);++    name1 = JS_GetProperty(ctx, this_val, JS_ATOM_name);+    if (JS_IsException(name1))+        goto exception;+    if (!JS_IsString(name1)) {+        JS_FreeValue(ctx, name1);+        name1 = JS_AtomToString(ctx, JS_ATOM_empty_string);+    }+    name1 = JS_ConcatString3(ctx, "bound ", name1, "");+    if (JS_IsException(name1))+        goto exception;+    JS_DefinePropertyValue(ctx, func_obj, JS_ATOM_name, name1,+                           JS_PROP_CONFIGURABLE);+    return func_obj;+ exception:+    JS_FreeValue(ctx, func_obj);+    return JS_EXCEPTION;+}++static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSObject *p;+    JSFunctionKindEnum func_kind = JS_FUNC_NORMAL;++    if (check_function(ctx, this_val))+        return JS_EXCEPTION;++    p = JS_VALUE_GET_OBJ(this_val);+    if (js_class_has_bytecode(p->class_id)) {+        JSFunctionBytecode *b = p->u.func.function_bytecode;+        if (b->has_debug && b->debug.source) {+            return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);+        }+        func_kind = b->func_kind;+    }+    {+        JSValue name;+        const char *pref, *suff;++        switch(func_kind) {+        default:+        case JS_FUNC_NORMAL:+            pref = "function ";+            break;+        case JS_FUNC_GENERATOR:+            pref = "function *";+            break;+        case JS_FUNC_ASYNC:+            pref = "async function ";+            break;+        case JS_FUNC_ASYNC_GENERATOR:+            pref = "async function *";+            break;+        }+        suff = "() {\n    [native code]\n}";+        name = JS_GetProperty(ctx, this_val, JS_ATOM_name);+        if (JS_IsUndefined(name))+            name = JS_AtomToString(ctx, JS_ATOM_empty_string);+        return JS_ConcatString3(ctx, pref, name, suff);+    }+}++static JSValue js_function_hasInstance(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    int ret;+    ret = JS_OrdinaryIsInstanceOf(ctx, argv[0], this_val);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static const JSCFunctionListEntry js_function_proto_funcs[] = {+    JS_CFUNC_DEF("call", 1, js_function_call ),+    JS_CFUNC_MAGIC_DEF("apply", 2, js_function_apply, 0 ),+    JS_CFUNC_DEF("bind", 1, js_function_bind ),+    JS_CFUNC_DEF("toString", 0, js_function_toString ),+    JS_CFUNC_DEF("[Symbol.hasInstance]", 1, js_function_hasInstance ),+    JS_CGETSET_DEF("fileName", js_function_proto_fileName, NULL ),+    JS_CGETSET_DEF("lineNumber", js_function_proto_lineNumber, NULL ),+};++/* Error class */++static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)+{+    JSValue iter, next_method = JS_UNDEFINED;+    JSValue v, r = JS_UNDEFINED;+    int64_t k;+    BOOL done;+    +    iter = JS_GetIterator(ctx, items, FALSE);+    if (JS_IsException(iter))+        goto exception;+    next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);+    if (JS_IsException(next_method))+        goto exception;+    r = JS_NewArray(ctx);+    if (JS_IsException(r))+        goto exception;+    for (k = 0;; k++) {+        v = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);+        if (JS_IsException(v))+            goto exception_close;+        if (done)+            break;+        if (JS_DefinePropertyValueInt64(ctx, r, k, v,+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)+            goto exception_close;+    }+ done:+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    return r;+ exception_close:+    JS_IteratorClose(ctx, iter, TRUE);+ exception:+    JS_FreeValue(ctx, r);+    r = JS_EXCEPTION;+    goto done;+}++static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,+                                    int argc, JSValueConst *argv, int magic)+{+    JSValue obj, msg, proto;+    JSValueConst message;++    if (JS_IsUndefined(new_target))+        new_target = JS_GetActiveFunction(ctx);+    proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);+    if (JS_IsException(proto))+        return proto;+    if (!JS_IsObject(proto)) {+        JSContext *realm;+        JSValueConst proto1;+        +        JS_FreeValue(ctx, proto);+        realm = JS_GetFunctionRealm(ctx, new_target);+        if (!realm)+            return JS_EXCEPTION;+        if (magic < 0) {+            proto1 = realm->class_proto[JS_CLASS_ERROR];+        } else {+            proto1 = realm->native_error_proto[magic];+        }+        proto = JS_DupValue(ctx, proto1);+    }+    obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR);+    JS_FreeValue(ctx, proto);+    if (JS_IsException(obj))+        return obj;+    if (magic == JS_AGGREGATE_ERROR) {+        message = argv[1];+    } else {+        message = argv[0];+    }++    if (!JS_IsUndefined(message)) {+        msg = JS_ToString(ctx, message);+        if (unlikely(JS_IsException(msg)))+            goto exception;+        JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg,+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    }++    if (magic == JS_AGGREGATE_ERROR) {+        JSValue error_list = iterator_to_array(ctx, argv[0]);+        if (JS_IsException(error_list))+            goto exception;+        JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, error_list,+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    }++    /* skip the Error() function in the backtrace */+    build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL);+    return obj;+ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue name, msg;++    if (!JS_IsObject(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    name = JS_GetProperty(ctx, this_val, JS_ATOM_name);+    if (JS_IsUndefined(name))+        name = JS_AtomToString(ctx, JS_ATOM_Error);+    else+        name = JS_ToStringFree(ctx, name);+    if (JS_IsException(name))+        return JS_EXCEPTION;++    msg = JS_GetProperty(ctx, this_val, JS_ATOM_message);+    if (JS_IsUndefined(msg))+        msg = JS_AtomToString(ctx, JS_ATOM_empty_string);+    else+        msg = JS_ToStringFree(ctx, msg);+    if (JS_IsException(msg)) {+        JS_FreeValue(ctx, name);+        return JS_EXCEPTION;+    }+    if (!JS_IsEmptyString(name) && !JS_IsEmptyString(msg))+        name = JS_ConcatString3(ctx, "", name, ": ");+    return JS_ConcatString(ctx, name, msg);+}++static const JSCFunctionListEntry js_error_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_error_toString ),+    JS_PROP_STRING_DEF("name", "Error", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),+    JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),+};++/* AggregateError */++/* used by C code. */+static JSValue js_aggregate_error_constructor(JSContext *ctx,+                                              JSValueConst errors)+{+    JSValue obj;+    +    obj = JS_NewObjectProtoClass(ctx,+                                 ctx->native_error_proto[JS_AGGREGATE_ERROR],+                                 JS_CLASS_ERROR);+    if (JS_IsException(obj))+        return obj;+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors),+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    return obj;+}++/* Array */++static int JS_CopySubArray(JSContext *ctx,+                           JSValueConst obj, int64_t to_pos,+                           int64_t from_pos, int64_t count, int dir)+{+    int64_t i, from, to;+    JSValue val;+    int fromPresent;++    /* XXX: should special case fast arrays */+    for (i = 0; i < count; i++) {+        if (dir < 0) {+            from = from_pos + count - i - 1;+            to = to_pos + count - i - 1;+        } else {+            from = from_pos + i;+            to = to_pos + i;+        }+        fromPresent = JS_TryGetPropertyInt64(ctx, obj, from, &val);+        if (fromPresent < 0)+            goto exception;++        if (fromPresent) {+            if (JS_SetPropertyInt64(ctx, obj, to, val) < 0)+                goto exception;+        } else {+            if (JS_DeletePropertyInt64(ctx, obj, to, JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    return 0;++ exception:+    return -1;+}++static JSValue js_array_constructor(JSContext *ctx, JSValueConst new_target,+                                    int argc, JSValueConst *argv)+{+    JSValue obj;+    int i;++    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_ARRAY);+    if (JS_IsException(obj))+        return obj;+    if (argc == 1 && JS_IsNumber(argv[0])) {+        uint32_t len;+        if (JS_ToArrayLengthFree(ctx, &len, JS_DupValue(ctx, argv[0]), TRUE))+            goto fail;+        if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, len)) < 0)+            goto fail;+    } else {+        for(i = 0; i < argc; i++) {+            if (JS_SetPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i])) < 0)+                goto fail;+        }+    }+    return obj;+fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_from(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    // from(items, mapfn = void 0, this_arg = void 0)+    JSValueConst items = argv[0], mapfn, this_arg;+    JSValueConst args[2];+    JSValue stack[2];+    JSValue iter, r, v, v2, arrayLike;+    int64_t k, len;+    int done, mapping;++    mapping = FALSE;+    mapfn = JS_UNDEFINED;+    this_arg = JS_UNDEFINED;+    r = JS_UNDEFINED;+    arrayLike = JS_UNDEFINED;+    stack[0] = JS_UNDEFINED;+    stack[1] = JS_UNDEFINED;++    if (argc > 1) {+        mapfn = argv[1];+        if (!JS_IsUndefined(mapfn)) {+            if (check_function(ctx, mapfn))+                goto exception;+            mapping = 1;+            if (argc > 2)+                this_arg = argv[2];+        }+    }+    iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator);+    if (JS_IsException(iter))+        goto exception;+    if (!JS_IsUndefined(iter)) {+        JS_FreeValue(ctx, iter);+        if (JS_IsConstructor(ctx, this_val))+            r = JS_CallConstructor(ctx, this_val, 0, NULL);+        else+            r = JS_NewArray(ctx);+        if (JS_IsException(r))+            goto exception;+        stack[0] = JS_DupValue(ctx, items);+        if (js_for_of_start(ctx, &stack[1], FALSE))+            goto exception;+        for (k = 0;; k++) {+            v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done);+            if (JS_IsException(v))+                goto exception_close;+            if (done)+                break;+            if (mapping) {+                args[0] = v;+                args[1] = JS_NewInt32(ctx, k);+                v2 = JS_Call(ctx, mapfn, this_arg, 2, args);+                JS_FreeValue(ctx, v);+                v = v2;+                if (JS_IsException(v))+                    goto exception_close;+            }+            if (JS_DefinePropertyValueInt64(ctx, r, k, v,+                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception_close;+        }+    } else {+        arrayLike = JS_ToObject(ctx, items);+        if (JS_IsException(arrayLike))+            goto exception;+        if (js_get_length64(ctx, &len, arrayLike) < 0)+            goto exception;+        v = JS_NewInt64(ctx, len);+        args[0] = v;+        if (JS_IsConstructor(ctx, this_val)) {+            r = JS_CallConstructor(ctx, this_val, 1, args);+        } else {+            r = js_array_constructor(ctx, JS_UNDEFINED, 1, args);+        }+        JS_FreeValue(ctx, v);+        if (JS_IsException(r))+            goto exception;+        for(k = 0; k < len; k++) {+            v = JS_GetPropertyInt64(ctx, arrayLike, k);+            if (JS_IsException(v))+                goto exception;+            if (mapping) {+                args[0] = v;+                args[1] = JS_NewInt32(ctx, k);+                v2 = JS_Call(ctx, mapfn, this_arg, 2, args);+                JS_FreeValue(ctx, v);+                v = v2;+                if (JS_IsException(v))+                    goto exception;+            }+            if (JS_DefinePropertyValueInt64(ctx, r, k, v,+                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    if (JS_SetProperty(ctx, r, JS_ATOM_length, JS_NewUint32(ctx, k)) < 0)+        goto exception;+    goto done;++ exception_close:+    if (!JS_IsUndefined(stack[0]))+        JS_IteratorClose(ctx, stack[0], TRUE);+ exception:+    JS_FreeValue(ctx, r);+    r = JS_EXCEPTION;+ done:+    JS_FreeValue(ctx, arrayLike);+    JS_FreeValue(ctx, stack[0]);+    JS_FreeValue(ctx, stack[1]);+    return r;+}++static JSValue js_array_of(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv)+{+    JSValue obj, args[1];+    int i;++    if (JS_IsConstructor(ctx, this_val)) {+        args[0] = JS_NewInt32(ctx, argc);+        obj = JS_CallConstructor(ctx, this_val, 1, (JSValueConst *)args);+    } else {+        obj = JS_NewArray(ctx);+    }+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    for(i = 0; i < argc; i++) {+        if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, argv[i]),+                                        JS_PROP_THROW) < 0) {+            goto fail;+        }+    }+    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewUint32(ctx, argc)) < 0) {+    fail:+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    return obj;+}++static JSValue js_array_isArray(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    int ret;+    ret = JS_IsArray(ctx, argv[0]);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_get_this(JSContext *ctx,+                           JSValueConst this_val)+{+    return JS_DupValue(ctx, this_val);+}++static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,+                                     JSValueConst len_val)+{+    JSValue ctor, ret, species;+    int res;+    JSContext *realm;+    +    res = JS_IsArray(ctx, obj);+    if (res < 0)+        return JS_EXCEPTION;+    if (!res)+        return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);+    ctor = JS_GetProperty(ctx, obj, JS_ATOM_constructor);+    if (JS_IsException(ctor))+        return ctor;+    if (JS_IsConstructor(ctx, ctor)) {+        /* legacy web compatibility */+        realm = JS_GetFunctionRealm(ctx, ctor);+        if (!realm) {+            JS_FreeValue(ctx, ctor);+            return JS_EXCEPTION;+        }+        if (realm != ctx &&+            js_same_value(ctx, ctor, realm->array_ctor)) {+            JS_FreeValue(ctx, ctor);+            ctor = JS_UNDEFINED;+        }+    }+    if (JS_IsObject(ctor)) {+        species = JS_GetProperty(ctx, ctor, JS_ATOM_Symbol_species);+        JS_FreeValue(ctx, ctor);+        if (JS_IsException(species))+            return species;+        ctor = species;+        if (JS_IsNull(ctor))+            ctor = JS_UNDEFINED;+    }+    if (JS_IsUndefined(ctor)) {+        return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);+    } else {+        ret = JS_CallConstructor(ctx, ctor, 1, &len_val);+        JS_FreeValue(ctx, ctor);+        return ret;+    }+}++static const JSCFunctionListEntry js_array_funcs[] = {+    JS_CFUNC_DEF("isArray", 1, js_array_isArray ),+    JS_CFUNC_DEF("from", 1, js_array_from ),+    JS_CFUNC_DEF("of", 0, js_array_of ),+    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),+};++static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj)+{+    JSValue val;++    if (!JS_IsObject(obj))+        return FALSE;+    val = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_isConcatSpreadable);+    if (JS_IsException(val))+        return -1;+    if (!JS_IsUndefined(val))+        return JS_ToBoolFree(ctx, val);+    return JS_IsArray(ctx, obj);+}++static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    JSValue obj, arr, val;+    JSValueConst e;+    int64_t len, k, n;+    int i, res;++    arr = JS_UNDEFINED;+    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        goto exception;++    arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));+    if (JS_IsException(arr))+        goto exception;+    n = 0;+    for (i = -1; i < argc; i++) {+        if (i < 0)+            e = obj;+        else+            e = argv[i];++        res = JS_isConcatSpreadable(ctx, e);+        if (res < 0)+            goto exception;+        if (res) {+            if (js_get_length64(ctx, &len, e))+                goto exception;+            if (n + len > MAX_SAFE_INTEGER) {+                JS_ThrowTypeError(ctx, "Array loo long");+                goto exception;+            }+            for (k = 0; k < len; k++, n++) {+                res = JS_TryGetPropertyInt64(ctx, e, k, &val);+                if (res < 0)+                    goto exception;+                if (res) {+                    if (JS_DefinePropertyValueInt64(ctx, arr, n, val,+                                                    JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                        goto exception;+                }+            }+        } else {+            if (n >= MAX_SAFE_INTEGER) {+                JS_ThrowTypeError(ctx, "Array loo long");+                goto exception;+            }+            if (JS_DefinePropertyValueInt64(ctx, arr, n, JS_DupValue(ctx, e),+                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+            n++;+        }+    }+    if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)+        goto exception;++    JS_FreeValue(ctx, obj);+    return arr;++exception:+    JS_FreeValue(ctx, arr);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++#define special_every    0+#define special_some     1+#define special_forEach  2+#define special_map      3+#define special_filter   4+#define special_TA       8++static int js_typed_array_get_length_internal(JSContext *ctx, JSValueConst obj);++static JSValue js_typed_array___speciesCreate(JSContext *ctx,+                                              JSValueConst this_val,+                                              int argc, JSValueConst *argv);++static JSValue js_array_every(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int special)+{+    JSValue obj, val, index_val, res, ret;+    JSValueConst args[3];+    JSValueConst func, this_arg;+    int64_t len, k, n;+    int present;++    ret = JS_UNDEFINED;+    val = JS_UNDEFINED;+    if (special & special_TA) {+        obj = JS_DupValue(ctx, this_val);+        len = js_typed_array_get_length_internal(ctx, obj);+        if (len < 0)+            goto exception;+    } else {+        obj = JS_ToObject(ctx, this_val);+        if (js_get_length64(ctx, &len, obj))+            goto exception;+    }+    func = argv[0];+    this_arg = JS_UNDEFINED;+    if (argc > 1)+        this_arg = argv[1];+        +    if (check_function(ctx, func))+        goto exception;++    switch (special) {+    case special_every:+    case special_every | special_TA:+        ret = JS_TRUE;+        break;+    case special_some:+    case special_some | special_TA:+        ret = JS_FALSE;+        break;+    case special_map:+        /* XXX: JS_ArraySpeciesCreate should take int64_t */+        ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt64(ctx, len));+        if (JS_IsException(ret))+            goto exception;+        break;+    case special_filter:+        ret = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));+        if (JS_IsException(ret))+            goto exception;+        break;+    case special_map | special_TA:+        args[0] = obj;+        args[1] = JS_NewInt32(ctx, len);+        ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);+        if (JS_IsException(ret))+            goto exception;+        break;+    case special_filter | special_TA:+        ret = JS_NewArray(ctx);+        if (JS_IsException(ret))+            goto exception;+        break;+    }+    n = 0;++    for(k = 0; k < len; k++) {+        present = JS_TryGetPropertyInt64(ctx, obj, k, &val);+        if (present < 0)+            goto exception;+        if (present) {+            index_val = JS_NewInt64(ctx, k);+            if (JS_IsException(index_val))+                goto exception;+            args[0] = val;+            args[1] = index_val;+            args[2] = obj;+            res = JS_Call(ctx, func, this_arg, 3, args);+            JS_FreeValue(ctx, index_val);+            if (JS_IsException(res))+                goto exception;+            switch (special) {+            case special_every:+            case special_every | special_TA:+                if (!JS_ToBoolFree(ctx, res)) {+                    ret = JS_FALSE;+                    goto done;+                }+                break;+            case special_some:+            case special_some | special_TA:+                if (JS_ToBoolFree(ctx, res)) {+                    ret = JS_TRUE;+                    goto done;+                }+                break;+            case special_map:+                if (JS_DefinePropertyValueInt64(ctx, ret, k, res,+                                                JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                    goto exception;+                break;+            case special_map | special_TA:+                if (JS_SetPropertyValue(ctx, ret, JS_NewInt32(ctx, k), res, JS_PROP_THROW) < 0)+                    goto exception;+                break;+            case special_filter:+            case special_filter | special_TA:+                if (JS_ToBoolFree(ctx, res)) {+                    if (JS_DefinePropertyValueInt64(ctx, ret, n++, JS_DupValue(ctx, val),+                                                    JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                        goto exception;+                }+                break;+            default:+                JS_FreeValue(ctx, res);+                break;+            }+            JS_FreeValue(ctx, val);+            val = JS_UNDEFINED;+        }+    }+done:+    if (special == (special_filter | special_TA)) {+        JSValue arr;+        args[0] = obj;+        args[1] = JS_NewInt32(ctx, n);+        arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args);+        if (JS_IsException(arr))+            goto exception;+        args[0] = ret;+        res = JS_Invoke(ctx, arr, JS_ATOM_set, 1, args);+        if (check_exception_free(ctx, res))+            goto exception;+        JS_FreeValue(ctx, ret);+        ret = arr;+    }+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return ret;++exception:+    JS_FreeValue(ctx, ret);+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++#define special_reduce       0+#define special_reduceRight  1++static JSValue js_array_reduce(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv, int special)+{+    JSValue obj, val, index_val, acc, acc1;+    JSValueConst args[4];+    JSValueConst func;+    int64_t len, k, k1;+    int present;++    acc = JS_UNDEFINED;+    val = JS_UNDEFINED;+    if (special & special_TA) {+        obj = JS_DupValue(ctx, this_val);+        len = js_typed_array_get_length_internal(ctx, obj);+        if (len < 0)+            goto exception;+    } else {+        obj = JS_ToObject(ctx, this_val);+        if (js_get_length64(ctx, &len, obj))+            goto exception;+    }+    func = argv[0];++    if (check_function(ctx, func))+        goto exception;++    k = 0;+    if (argc > 1) {+        acc = JS_DupValue(ctx, argv[1]);+    } else {+        for(;;) {+            if (k >= len) {+                JS_ThrowTypeError(ctx, "empty array");+                goto exception;+            }+            k1 = (special & special_reduceRight) ? len - k - 1 : k;+            k++;+            present = JS_TryGetPropertyInt64(ctx, obj, k1, &acc);+            if (present < 0)+                goto exception;+            if (present)+                break;+        }+    }+    for (; k < len; k++) {+        k1 = (special & special_reduceRight) ? len - k - 1 : k;+        present = JS_TryGetPropertyInt64(ctx, obj, k1, &val);+        if (present < 0)+            goto exception;+        if (present) {+            index_val = JS_NewInt64(ctx, k1);+            if (JS_IsException(index_val))+                goto exception;+            args[0] = acc;+            args[1] = val;+            args[2] = index_val;+            args[3] = obj;+            acc1 = JS_Call(ctx, func, JS_UNDEFINED, 4, args);+            JS_FreeValue(ctx, index_val);+            JS_FreeValue(ctx, val);+            val = JS_UNDEFINED;+            if (JS_IsException(acc1))+                goto exception;+            JS_FreeValue(ctx, acc);+            acc = acc1;+        }+    }+    JS_FreeValue(ctx, obj);+    return acc;++exception:+    JS_FreeValue(ctx, acc);+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_fill(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    JSValue obj;+    int64_t len, start, end;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    start = 0;+    if (argc > 1 && !JS_IsUndefined(argv[1])) {+        if (JS_ToInt64Clamp(ctx, &start, argv[1], 0, len, len))+            goto exception;+    }++    end = len;+    if (argc > 2 && !JS_IsUndefined(argv[2])) {+        if (JS_ToInt64Clamp(ctx, &end, argv[2], 0, len, len))+            goto exception;+    }++    /* XXX: should special case fast arrays */+    while (start < end) {+        if (JS_SetPropertyInt64(ctx, obj, start,+                                JS_DupValue(ctx, argv[0])) < 0)+            goto exception;+        start++;+    }+    return obj;++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue obj, val;+    int64_t len, n, res;+    JSValue *arrp;+    uint32_t count;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    res = FALSE;+    if (len > 0) {+        n = 0;+        if (argc > 1) {+            if (JS_ToInt64Clamp(ctx, &n, argv[1], 0, len, len))+                goto exception;+        }+        if (js_get_fast_array(ctx, obj, &arrp, &count)) {+            for (; n < count; n++) {+                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),+                                  JS_DupValue(ctx, arrp[n]),+                                  JS_EQ_SAME_VALUE_ZERO)) {+                    res = TRUE;+                    goto done;+                }+            }+        }+        for (; n < len; n++) {+            val = JS_GetPropertyInt64(ctx, obj, n);+            if (JS_IsException(val))+                goto exception;+            if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val,+                              JS_EQ_SAME_VALUE_ZERO)) {+                res = TRUE;+                break;+            }+        }+    }+ done:+    JS_FreeValue(ctx, obj);+    return JS_NewBool(ctx, res);++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_indexOf(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue obj, val;+    int64_t len, n, res;+    JSValue *arrp;+    uint32_t count;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    res = -1;+    if (len > 0) {+        n = 0;+        if (argc > 1) {+            if (JS_ToInt64Clamp(ctx, &n, argv[1], 0, len, len))+                goto exception;+        }+        if (js_get_fast_array(ctx, obj, &arrp, &count)) {+            for (; n < count; n++) {+                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]),+                                  JS_DupValue(ctx, arrp[n]), JS_EQ_STRICT)) {+                    res = n;+                    goto done;+                }+            }+        }+        for (; n < len; n++) {+            int present = JS_TryGetPropertyInt64(ctx, obj, n, &val);+            if (present < 0)+                goto exception;+            if (present) {+                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {+                    res = n;+                    break;+                }+            }+        }+    }+ done:+    JS_FreeValue(ctx, obj);+    return JS_NewInt64(ctx, res);++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_lastIndexOf(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValue obj, val;+    int64_t len, n, res;+    int present;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    res = -1;+    if (len > 0) {+        n = len - 1;+        if (argc > 1) {+            if (JS_ToInt64Clamp(ctx, &n, argv[1], -1, len - 1, len))+                goto exception;+        }+        /* XXX: should special case fast arrays */+        for (; n >= 0; n--) {+            present = JS_TryGetPropertyInt64(ctx, obj, n, &val);+            if (present < 0)+                goto exception;+            if (present) {+                if (js_strict_eq2(ctx, JS_DupValue(ctx, argv[0]), val, JS_EQ_STRICT)) {+                    res = n;+                    break;+                }+            }+        }+    }+    JS_FreeValue(ctx, obj);+    return JS_NewInt64(ctx, res);++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_find(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv, int findIndex)+{+    JSValueConst func, this_arg;+    JSValueConst args[3];+    JSValue obj, val, index_val, res;+    int64_t len, k;++    index_val = JS_UNDEFINED;+    val = JS_UNDEFINED;+    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    func = argv[0];+    if (check_function(ctx, func))+        goto exception;++    this_arg = JS_UNDEFINED;+    if (argc > 1)+        this_arg = argv[1];++    for(k = 0; k < len; k++) {+        index_val = JS_NewInt64(ctx, k);+        if (JS_IsException(index_val))+            goto exception;+        val = JS_GetPropertyValue(ctx, obj, index_val);+        if (JS_IsException(val))+            goto exception;+        args[0] = val;+        args[1] = index_val;+        args[2] = this_val;+        res = JS_Call(ctx, func, this_arg, 3, args);+        if (JS_IsException(res))+            goto exception;+        if (JS_ToBoolFree(ctx, res)) {+            if (findIndex) {+                JS_FreeValue(ctx, val);+                JS_FreeValue(ctx, obj);+                return index_val;+            } else {+                JS_FreeValue(ctx, index_val);+                JS_FreeValue(ctx, obj);+                return val;+            }+        }+        JS_FreeValue(ctx, val);+        JS_FreeValue(ctx, index_val);+    }+    JS_FreeValue(ctx, obj);+    if (findIndex)+        return JS_NewInt32(ctx, -1);+    else+        return JS_UNDEFINED;++exception:+    JS_FreeValue(ctx, index_val);+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_toString(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue obj, method, ret;++    obj = JS_ToObject(ctx, this_val);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    method = JS_GetProperty(ctx, obj, JS_ATOM_join);+    if (JS_IsException(method)) {+        ret = JS_EXCEPTION;+    } else+    if (!JS_IsFunction(ctx, method)) {+        /* Use intrinsic Object.prototype.toString */+        JS_FreeValue(ctx, method);+        ret = js_object_toString(ctx, obj, 0, NULL);+    } else {+        ret = JS_CallFree(ctx, method, obj, 0, NULL);+    }+    JS_FreeValue(ctx, obj);+    return ret;+}++static JSValue js_array_join(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv, int toLocaleString)+{+    JSValue obj, sep = JS_UNDEFINED, el;+    StringBuffer b_s, *b = &b_s;+    JSString *p = NULL;+    int64_t i, n;+    int c;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &n, obj))+        goto exception;++    c = ',';    /* default separator */+    if (!toLocaleString && argc > 0 && !JS_IsUndefined(argv[0])) {+        sep = JS_ToString(ctx, argv[0]);+        if (JS_IsException(sep))+            goto exception;+        p = JS_VALUE_GET_STRING(sep);+        if (p->len == 1 && !p->is_wide_char)+            c = p->u.str8[0];+        else+            c = -1;+    }+    string_buffer_init(ctx, b, 0);++    for(i = 0; i < n; i++) {+        if (i > 0) {+            if (c >= 0) {+                string_buffer_putc8(b, c);+            } else {+                string_buffer_concat(b, p, 0, p->len);+            }+        }+        el = JS_GetPropertyUint32(ctx, obj, i);+        if (JS_IsException(el))+            goto fail;+        if (!JS_IsNull(el) && !JS_IsUndefined(el)) {+            if (toLocaleString) {+                el = JS_ToLocaleStringFree(ctx, el);+            }+            if (string_buffer_concat_value_free(b, el))+                goto fail;+        }+    }+    JS_FreeValue(ctx, sep);+    JS_FreeValue(ctx, obj);+    return string_buffer_end(b);++fail:+    string_buffer_free(b);+    JS_FreeValue(ctx, sep);+exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_pop(JSContext *ctx, JSValueConst this_val,+                            int argc, JSValueConst *argv, int shift)+{+    JSValue obj, res = JS_UNDEFINED;+    int64_t len, newLen;+    JSValue *arrp;+    uint32_t count32;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;+    newLen = 0;+    if (len > 0) {+        newLen = len - 1;+        /* Special case fast arrays */+        if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {+            JSObject *p = JS_VALUE_GET_OBJ(obj);+            if (shift) {+                res = arrp[0];+                memmove(arrp, arrp + 1, (count32 - 1) * sizeof(*arrp));+                p->u.array.count--;+            } else {+                res = arrp[count32 - 1];+                p->u.array.count--;+            }+        } else {+            if (shift) {+                res = JS_GetPropertyInt64(ctx, obj, 0);+                if (JS_IsException(res))+                    goto exception;+                if (JS_CopySubArray(ctx, obj, 0, 1, len - 1, +1))+                    goto exception;+            } else {+                res = JS_GetPropertyInt64(ctx, obj, newLen);+                if (JS_IsException(res))+                    goto exception;+            }+            if (JS_DeletePropertyInt64(ctx, obj, newLen, JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)+        goto exception;++    JS_FreeValue(ctx, obj);+    return res;++ exception:+    JS_FreeValue(ctx, res);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_push(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv, int unshift)+{+    JSValue obj;+    int i;+    int64_t len, from, newLen;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;+    newLen = len + argc;+    if (newLen > MAX_SAFE_INTEGER) {+        JS_ThrowTypeError(ctx, "Array loo long");+        goto exception;+    }+    from = len;+    if (unshift && argc > 0) {+        if (JS_CopySubArray(ctx, obj, argc, 0, len, -1))+            goto exception;+        from = 0;+    }+    for(i = 0; i < argc; i++) {+        if (JS_SetPropertyInt64(ctx, obj, from + i,+                                JS_DupValue(ctx, argv[i])) < 0)+            goto exception;+    }+    if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, newLen)) < 0)+        goto exception;++    JS_FreeValue(ctx, obj);+    return JS_NewInt64(ctx, newLen);++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_reverse(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue obj, lval, hval;+    JSValue *arrp;+    int64_t len, l, h;+    int l_present, h_present;+    uint32_t count32;++    lval = JS_UNDEFINED;+    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    /* Special case fast arrays */+    if (js_get_fast_array(ctx, obj, &arrp, &count32) && count32 == len) {+        uint32_t ll, hh;++        if (count32 > 1) {+            for (ll = 0, hh = count32 - 1; ll < hh; ll++, hh--) {+                lval = arrp[ll];+                arrp[ll] = arrp[hh];+                arrp[hh] = lval;+            }+        }+        return obj;+    }++    for (l = 0, h = len - 1; l < h; l++, h--) {+        l_present = JS_TryGetPropertyInt64(ctx, obj, l, &lval);+        if (l_present < 0)+            goto exception;+        h_present = JS_TryGetPropertyInt64(ctx, obj, h, &hval);+        if (h_present < 0)+            goto exception;+        if (h_present) {+            if (JS_SetPropertyInt64(ctx, obj, l, hval) < 0)+                goto exception;++            if (l_present) {+                if (JS_SetPropertyInt64(ctx, obj, h, lval) < 0) {+                    lval = JS_UNDEFINED;+                    goto exception;+                }+                lval = JS_UNDEFINED;+            } else {+                if (JS_DeletePropertyInt64(ctx, obj, h, JS_PROP_THROW) < 0)+                    goto exception;+            }+        } else {+            if (l_present) {+                if (JS_DeletePropertyInt64(ctx, obj, l, JS_PROP_THROW) < 0)+                    goto exception;+                if (JS_SetPropertyInt64(ctx, obj, h, lval) < 0) {+                    lval = JS_UNDEFINED;+                    goto exception;+                }+                lval = JS_UNDEFINED;+            }+        }+    }+    return obj;++ exception:+    JS_FreeValue(ctx, lval);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_array_slice(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int splice)+{+    JSValue obj, arr, val, len_val;+    int64_t len, start, k, final, n, count, del_count, new_len;+    int kPresent;+    JSValue *arrp;+    uint32_t count32, i, item_count;++    arr = JS_UNDEFINED;+    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    if (JS_ToInt64Clamp(ctx, &start, argv[0], 0, len, len))+        goto exception;++    if (splice) {+        if (argc == 0) {+            item_count = 0;+            del_count = 0;+        } else+        if (argc == 1) {+            item_count = 0;+            del_count = len - start;+        } else {+            item_count = argc - 2;+            if (JS_ToInt64Clamp(ctx, &del_count, argv[1], 0, len - start, 0))+                goto exception;+        }+        if (len + item_count - del_count > MAX_SAFE_INTEGER) {+            JS_ThrowTypeError(ctx, "Array loo long");+            goto exception;+        }+        count = del_count;+    } else {+        item_count = 0; /* avoid warning */+        final = len;+        if (!JS_IsUndefined(argv[1])) {+            if (JS_ToInt64Clamp(ctx, &final, argv[1], 0, len, len))+                goto exception;+        }+        count = max_int64(final - start, 0);+    }+    len_val = JS_NewInt64(ctx, count);+    arr = JS_ArraySpeciesCreate(ctx, obj, len_val);+    JS_FreeValue(ctx, len_val);+    if (JS_IsException(arr))+        goto exception;++    k = start;+    final = start + count;+    n = 0;+    /* The fast array test on arr ensures that+       JS_CreateDataPropertyUint32() won't modify obj in case arr is+       an exotic object */+    /* Special case fast arrays */+    if (js_get_fast_array(ctx, obj, &arrp, &count32) &&+        js_is_fast_array(ctx, arr)) {+        /* XXX: should share code with fast array constructor */+        for (; k < final && k < count32; k++, n++) {+            if (JS_CreateDataPropertyUint32(ctx, arr, n, JS_DupValue(ctx, arrp[k]), JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    /* Copy the remaining elements if any (handle case of inherited properties) */+    for (; k < final; k++, n++) {+        kPresent = JS_TryGetPropertyInt64(ctx, obj, k, &val);+        if (kPresent < 0)+            goto exception;+        if (kPresent) {+            if (JS_CreateDataPropertyUint32(ctx, arr, n, val, JS_PROP_THROW) < 0)+                goto exception;+        }+    }+    if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0)+        goto exception;++    if (splice) {+        new_len = len + item_count - del_count;+        if (item_count != del_count) {+            if (JS_CopySubArray(ctx, obj, start + item_count,+                                start + del_count, len - (start + del_count),+                                item_count <= del_count ? +1 : -1) < 0)+                goto exception;++            for (k = len; k-- > new_len; ) {+                if (JS_DeletePropertyInt64(ctx, obj, k, JS_PROP_THROW) < 0)+                    goto exception;+            }+        }+        for (i = 0; i < item_count; i++) {+            if (JS_SetPropertyInt64(ctx, obj, start + i, JS_DupValue(ctx, argv[i + 2])) < 0)+                goto exception;+        }+        if (JS_SetProperty(ctx, obj, JS_ATOM_length, JS_NewInt64(ctx, new_len)) < 0)+            goto exception;+    }+    JS_FreeValue(ctx, obj);+    return arr;++ exception:+    JS_FreeValue(ctx, obj);+    JS_FreeValue(ctx, arr);+    return JS_EXCEPTION;+}++static JSValue js_array_copyWithin(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    JSValue obj;+    int64_t len, from, to, final, count;++    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    if (JS_ToInt64Clamp(ctx, &to, argv[0], 0, len, len))+        goto exception;++    if (JS_ToInt64Clamp(ctx, &from, argv[1], 0, len, len))+        goto exception;++    final = len;+    if (argc > 2 && !JS_IsUndefined(argv[2])) {+        if (JS_ToInt64Clamp(ctx, &final, argv[2], 0, len, len))+            goto exception;+    }++    count = min_int64(final - from, len - to);++    if (JS_CopySubArray(ctx, obj, to, from, count,+                        (from < to && to < from + count) ? -1 : +1))+        goto exception;++    return obj;++ exception:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static int64_t JS_FlattenIntoArray(JSContext *ctx, JSValueConst target,+                                   JSValueConst source, int64_t sourceLen,+                                   int64_t targetIndex, int depth,+                                   JSValueConst mapperFunction,+                                   JSValueConst thisArg)+{+    JSValue element;+    int64_t sourceIndex, elementLen;+    int present, is_array;++    for (sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {+        present = JS_TryGetPropertyInt64(ctx, source, sourceIndex, &element);+        if (present < 0)+            return -1;+        if (!present)+            continue;+        if (!JS_IsUndefined(mapperFunction)) {+            JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex), source };+            element = JS_Call(ctx, mapperFunction, thisArg, 3, args);+            JS_FreeValue(ctx, (JSValue)args[0]);+            JS_FreeValue(ctx, (JSValue)args[1]);+            if (JS_IsException(element))+                return -1;+        }+        if (depth > 0) {+            is_array = JS_IsArray(ctx, element);+            if (is_array < 0)+                goto fail;+            if (is_array) {+                if (js_get_length64(ctx, &elementLen, element) < 0)+                    goto fail;+                targetIndex = JS_FlattenIntoArray(ctx, target, element,+                                                  elementLen, targetIndex,+                                                  depth - 1,+                                                  JS_UNDEFINED, JS_UNDEFINED);+                if (targetIndex < 0)+                    goto fail;+                JS_FreeValue(ctx, element);+                continue;+            }+        }+        if (targetIndex >= MAX_SAFE_INTEGER) {+            JS_ThrowTypeError(ctx, "Array too long");+            goto fail;+        }+        if (JS_DefinePropertyValueInt64(ctx, target, targetIndex, element,+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)+            return -1;+        targetIndex++;+    }+    return targetIndex;++fail:+    JS_FreeValue(ctx, element);+    return -1;+}++static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv, int map)+{+    JSValue obj, arr;+    JSValueConst mapperFunction, thisArg;+    int64_t sourceLen;+    int depthNum;++    arr = JS_UNDEFINED;+    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &sourceLen, obj))+        goto exception;++    depthNum = 1;+    mapperFunction = JS_UNDEFINED;+    thisArg = JS_UNDEFINED;+    if (map) {+        mapperFunction = argv[0];+        if (argc > 1) {+            thisArg = argv[1];+        }+        if (check_function(ctx, mapperFunction))+            goto exception;+    } else {+        if (argc > 0 && !JS_IsUndefined(argv[0])) {+            if (JS_ToInt32Sat(ctx, &depthNum, argv[0]) < 0)+                goto exception;+        }+    }+    arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0));+    if (JS_IsException(arr))+        goto exception;+    if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum,+                            mapperFunction, thisArg) < 0)+        goto exception;+    JS_FreeValue(ctx, obj);+    return arr;++exception:+    JS_FreeValue(ctx, obj);+    JS_FreeValue(ctx, arr);+    return JS_EXCEPTION;+}++/* Array sort */++typedef struct ValueSlot {+    JSValue val;+    JSString *str;+    int64_t pos;+} ValueSlot;++struct array_sort_context {+    JSContext *ctx;+    int exception;+    int has_method;+    JSValueConst method;+};++static int js_array_cmp_generic(const void *a, const void *b, void *opaque) {+    struct array_sort_context *psc = opaque;+    JSContext *ctx = psc->ctx;+    JSValueConst argv[2];+    JSValue res;+    ValueSlot *ap = (ValueSlot *)(void *)a;+    ValueSlot *bp = (ValueSlot *)(void *)b;+    int cmp;++    if (psc->exception)+        return 0;++    if (psc->has_method) {+        /* custom sort function is specified as returning 0 for identical+         * objects: avoid method call overhead.+         */+        if (!memcmp(&ap->val, &bp->val, sizeof(ap->val)))+            goto cmp_same;+        argv[0] = ap->val;+        argv[1] = bp->val;+        res = JS_Call(ctx, psc->method, JS_UNDEFINED, 2, argv);+        if (JS_IsException(res))+            goto exception;+        if (JS_VALUE_GET_TAG(res) == JS_TAG_INT) {+            int val = JS_VALUE_GET_INT(res);+            cmp = (val > 0) - (val < 0);+        } else {+            double val;+            if (JS_ToFloat64Free(ctx, &val, res) < 0)+                goto exception;+            cmp = (val > 0) - (val < 0);+        }+    } else {+        /* Not supposed to bypass ToString even for identical objects as+         * tested in test262/test/built-ins/Array/prototype/sort/bug_596_1.js+         */+        if (!ap->str) {+            JSValue str = JS_ToString(ctx, ap->val);+            if (JS_IsException(str))+                goto exception;+            ap->str = JS_VALUE_GET_STRING(str);+        }+        if (!bp->str) {+            JSValue str = JS_ToString(ctx, bp->val);+            if (JS_IsException(str))+                goto exception;+            bp->str = JS_VALUE_GET_STRING(str);+        }+        cmp = js_string_compare(ctx, ap->str, bp->str);+    }+    if (cmp != 0)+        return cmp;+cmp_same:+    /* make sort stable: compare array offsets */+    return (ap->pos > bp->pos) - (ap->pos < bp->pos);++exception:+    psc->exception = 1;+    return 0;+}++static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    struct array_sort_context asc = { ctx, 0, 0, argv[0] };+    JSValue obj = JS_UNDEFINED;+    ValueSlot *array = NULL;+    size_t array_size = 0, pos = 0, n = 0;+    int64_t i, len, undefined_count = 0;+    int present;++    if (!JS_IsUndefined(asc.method)) {+        if (check_function(ctx, asc.method))+            goto exception;+        asc.has_method = 1;+    }+    obj = JS_ToObject(ctx, this_val);+    if (js_get_length64(ctx, &len, obj))+        goto exception;++    /* XXX: should special case fast arrays */+    for (i = 0; i < len; i++) {+        if (pos >= array_size) {+            size_t new_size, slack;+            ValueSlot *new_array;+            new_size = (array_size + (array_size >> 1) + 31) & ~15;+            new_array = js_realloc2(ctx, array, new_size * sizeof(*array), &slack);+            if (new_array == NULL)+                goto exception;+            new_size += slack / sizeof(*new_array);+            array = new_array;+            array_size = new_size;+        }+        present = JS_TryGetPropertyInt64(ctx, obj, i, &array[pos].val);+        if (present < 0)+            goto exception;+        if (present == 0)+            continue;+        if (JS_IsUndefined(array[pos].val)) {+            undefined_count++;+            continue;+        }+        array[pos].str = NULL;+        array[pos].pos = i;+        pos++;+    }+    rqsort(array, pos, sizeof(*array), js_array_cmp_generic, &asc);+    if (asc.exception)+        goto exception;++    /* XXX: should special case fast arrays */+    while (n < pos) {+        if (array[n].str)+            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, array[n].str));+        if (array[n].pos == n) {+            JS_FreeValue(ctx, array[n].val);+        } else {+            if (JS_SetPropertyInt64(ctx, obj, n, array[n].val) < 0) {+                n++;+                goto exception;+            }+        }+        n++;+    }+    js_free(ctx, array);+    for (i = n; undefined_count-- > 0; i++) {+        if (JS_SetPropertyInt64(ctx, obj, i, JS_UNDEFINED) < 0)+            goto fail;+    }+    for (; i < len; i++) {+        if (JS_DeletePropertyInt64(ctx, obj, i, JS_PROP_THROW) < 0)+            goto fail;+    }+    return obj;++exception:+    for (; n < pos; n++) {+        JS_FreeValue(ctx, array[n].val);+        if (array[n].str)+            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, array[n].str));+    }+    js_free(ctx, array);+fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++typedef struct JSArrayIteratorData {+    JSValue obj;+    JSIteratorKindEnum kind;+    uint32_t idx;+} JSArrayIteratorData;++static void js_array_iterator_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSArrayIteratorData *it = p->u.array_iterator_data;+    if (it) {+        JS_FreeValueRT(rt, it->obj);+        js_free_rt(rt, it);+    }+}++static void js_array_iterator_mark(JSRuntime *rt, JSValueConst val,+                                   JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSArrayIteratorData *it = p->u.array_iterator_data;+    if (it) {+        JS_MarkValue(rt, it->obj, mark_func);+    }+}++static JSValue js_create_array(JSContext *ctx, int len, JSValueConst *tab)+{+    JSValue obj;+    int i;++    obj = JS_NewArray(ctx);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    for(i = 0; i < len; i++) {+        if (JS_CreateDataPropertyUint32(ctx, obj, i, JS_DupValue(ctx, tab[i]), 0) < 0) {+            JS_FreeValue(ctx, obj);+            return JS_EXCEPTION;+        }+    }+    return obj;+}++static JSValue js_create_array_iterator(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv, int magic)+{+    JSValue enum_obj, arr;+    JSArrayIteratorData *it;+    JSIteratorKindEnum kind;+    int class_id;++    kind = magic & 3;+    if (magic & 4) {+        /* string iterator case */+        arr = JS_ToStringCheckObject(ctx, this_val);+        class_id = JS_CLASS_STRING_ITERATOR;+    } else {+        arr = JS_ToObject(ctx, this_val);+        class_id = JS_CLASS_ARRAY_ITERATOR;+    }+    if (JS_IsException(arr))+        goto fail;+    enum_obj = JS_NewObjectClass(ctx, class_id);+    if (JS_IsException(enum_obj))+        goto fail;+    it = js_malloc(ctx, sizeof(*it));+    if (!it)+        goto fail1;+    it->obj = arr;+    it->kind = kind;+    it->idx = 0;+    JS_SetOpaque(enum_obj, it);+    return enum_obj;+ fail1:+    JS_FreeValue(ctx, enum_obj);+ fail:+    JS_FreeValue(ctx, arr);+    return JS_EXCEPTION;+}++static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv,+                                      BOOL *pdone, int magic)+{+    JSArrayIteratorData *it;+    uint32_t len, idx;+    JSValue val, obj;+    JSObject *p;++    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_ITERATOR);+    if (!it)+        goto fail1;+    if (JS_IsUndefined(it->obj))+        goto done;+    p = JS_VALUE_GET_OBJ(it->obj);+    if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+        p->class_id <= JS_CLASS_FLOAT64_ARRAY) {+        if (typed_array_is_detached(ctx, p)) {+            JS_ThrowTypeErrorDetachedArrayBuffer(ctx);+            goto fail1;+        }+        len = p->u.array.count;+    } else {+        if (js_get_length32(ctx, &len, it->obj)) {+        fail1:+            *pdone = FALSE;+            return JS_EXCEPTION;+        }+    }+    idx = it->idx;+    if (idx >= len) {+        JS_FreeValue(ctx, it->obj);+        it->obj = JS_UNDEFINED;+    done:+        *pdone = TRUE;+        return JS_UNDEFINED;+    }+    it->idx = idx + 1;+    *pdone = FALSE;+    if (it->kind == JS_ITERATOR_KIND_KEY) {+        return JS_NewUint32(ctx, idx);+    } else {+        val = JS_GetPropertyUint32(ctx, it->obj, idx);+        if (JS_IsException(val))+            return JS_EXCEPTION;+        if (it->kind == JS_ITERATOR_KIND_VALUE) {+            return val;+        } else {+            JSValueConst args[2];+            JSValue num;+            num = JS_NewUint32(ctx, idx);+            args[0] = num;+            args[1] = val;+            obj = js_create_array(ctx, 2, args);+            JS_FreeValue(ctx, val);+            JS_FreeValue(ctx, num);+            return obj;+        }+    }+}++static JSValue js_iterator_proto_iterator(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv)+{+    return JS_DupValue(ctx, this_val);+}++static const JSCFunctionListEntry js_iterator_proto_funcs[] = {+    JS_CFUNC_DEF("[Symbol.iterator]", 0, js_iterator_proto_iterator ),+};++static const JSCFunctionListEntry js_array_proto_funcs[] = {+    JS_CFUNC_DEF("concat", 1, js_array_concat ),+    JS_CFUNC_MAGIC_DEF("every", 1, js_array_every, special_every ),+    JS_CFUNC_MAGIC_DEF("some", 1, js_array_every, special_some ),+    JS_CFUNC_MAGIC_DEF("forEach", 1, js_array_every, special_forEach ),+    JS_CFUNC_MAGIC_DEF("map", 1, js_array_every, special_map ),+    JS_CFUNC_MAGIC_DEF("filter", 1, js_array_every, special_filter ),+    JS_CFUNC_MAGIC_DEF("reduce", 1, js_array_reduce, special_reduce ),+    JS_CFUNC_MAGIC_DEF("reduceRight", 1, js_array_reduce, special_reduceRight ),+    JS_CFUNC_DEF("fill", 1, js_array_fill ),+    JS_CFUNC_MAGIC_DEF("find", 1, js_array_find, 0 ),+    JS_CFUNC_MAGIC_DEF("findIndex", 1, js_array_find, 1 ),+    JS_CFUNC_DEF("indexOf", 1, js_array_indexOf ),+    JS_CFUNC_DEF("lastIndexOf", 1, js_array_lastIndexOf ),+    JS_CFUNC_DEF("includes", 1, js_array_includes ),+    JS_CFUNC_MAGIC_DEF("join", 1, js_array_join, 0 ),+    JS_CFUNC_DEF("toString", 0, js_array_toString ),+    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_array_join, 1 ),+    JS_CFUNC_MAGIC_DEF("pop", 0, js_array_pop, 0 ),+    JS_CFUNC_MAGIC_DEF("push", 1, js_array_push, 0 ),+    JS_CFUNC_MAGIC_DEF("shift", 0, js_array_pop, 1 ),+    JS_CFUNC_MAGIC_DEF("unshift", 1, js_array_push, 1 ),+    JS_CFUNC_DEF("reverse", 0, js_array_reverse ),+    JS_CFUNC_DEF("sort", 1, js_array_sort ),+    JS_CFUNC_MAGIC_DEF("slice", 2, js_array_slice, 0 ),+    JS_CFUNC_MAGIC_DEF("splice", 2, js_array_slice, 1 ),+    JS_CFUNC_DEF("copyWithin", 2, js_array_copyWithin ),+    JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ),+    JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ),+    JS_CFUNC_MAGIC_DEF("values", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE ),+    JS_ALIAS_DEF("[Symbol.iterator]", "values" ),+    JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ),+    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY_AND_VALUE ),+};++static const JSCFunctionListEntry js_array_iterator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 0, js_array_iterator_next, 0 ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Array Iterator", JS_PROP_CONFIGURABLE ),+};++/* Number */++static JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue val, obj;+    if (argc == 0) {+        val = JS_NewInt32(ctx, 0);+    } else {+        val = JS_ToNumeric(ctx, argv[0]);+        if (JS_IsException(val))+            return val;+        switch(JS_VALUE_GET_TAG(val)) {+#ifdef CONFIG_BIGNUM+        case JS_TAG_BIG_INT:+        case JS_TAG_BIG_FLOAT:+            {+                JSBigFloat *p = JS_VALUE_GET_PTR(val);+                double d;+                bf_get_float64(&p->num, &d, BF_RNDN);+                JS_FreeValue(ctx, val);+                val = __JS_NewFloat64(ctx, d);+            }+            break;+        case JS_TAG_BIG_DECIMAL:+            val = JS_ToStringFree(ctx, val);+            if (JS_IsException(val))+                return val;+            val = JS_ToNumberFree(ctx, val);+            if (JS_IsException(val))+                return val;+            break;+#endif+        default:+            break;+        }+    }+    if (!JS_IsUndefined(new_target)) {+        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_NUMBER);+        if (!JS_IsException(obj))+            JS_SetObjectData(ctx, obj, val);+        return obj;+    } else {+        return val;+    }+}++#if 0+static JSValue js_number___toInteger(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    return JS_ToIntegerFree(ctx, JS_DupValue(ctx, argv[0]));+}++static JSValue js_number___toLength(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    int64_t v;+    if (JS_ToLengthFree(ctx, &v, JS_DupValue(ctx, argv[0])))+        return JS_EXCEPTION;+    return JS_NewInt64(ctx, v);+}+#endif++static JSValue js_number_isNaN(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    if (!JS_IsNumber(argv[0]))+        return JS_FALSE;+    return js_global_isNaN(ctx, this_val, argc, argv);+}++static JSValue js_number_isFinite(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    if (!JS_IsNumber(argv[0]))+        return JS_FALSE;+    return js_global_isFinite(ctx, this_val, argc, argv);+}++static JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    int ret;+    ret = JS_NumberIsInteger(ctx, argv[0]);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    double d;+    if (!JS_IsNumber(argv[0]))+        return JS_FALSE;+    if (unlikely(JS_ToFloat64(ctx, &d, argv[0])))+        return JS_EXCEPTION;+    return JS_NewBool(ctx, is_safe_integer(d));+}++static const JSCFunctionListEntry js_number_funcs[] = {+    /* global ParseInt and parseFloat should be defined already or delayed */+    JS_ALIAS_BASE_DEF("parseInt", "parseInt", 0 ),+    JS_ALIAS_BASE_DEF("parseFloat", "parseFloat", 0 ),+    JS_CFUNC_DEF("isNaN", 1, js_number_isNaN ),+    JS_CFUNC_DEF("isFinite", 1, js_number_isFinite ),+    JS_CFUNC_DEF("isInteger", 1, js_number_isInteger ),+    JS_CFUNC_DEF("isSafeInteger", 1, js_number_isSafeInteger ),+    JS_PROP_DOUBLE_DEF("MAX_VALUE", 1.7976931348623157e+308, 0 ),+    JS_PROP_DOUBLE_DEF("MIN_VALUE", 5e-324, 0 ),+    JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),+    JS_PROP_DOUBLE_DEF("NEGATIVE_INFINITY", -INFINITY, 0 ),+    JS_PROP_DOUBLE_DEF("POSITIVE_INFINITY", INFINITY, 0 ),+    JS_PROP_DOUBLE_DEF("EPSILON", 2.220446049250313e-16, 0 ), /* ES6 */+    JS_PROP_DOUBLE_DEF("MAX_SAFE_INTEGER", 9007199254740991.0, 0 ), /* ES6 */+    JS_PROP_DOUBLE_DEF("MIN_SAFE_INTEGER", -9007199254740991.0, 0 ), /* ES6 */+    //JS_CFUNC_DEF("__toInteger", 1, js_number___toInteger ),+    //JS_CFUNC_DEF("__toLength", 1, js_number___toLength ),+};++static JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_IsNumber(this_val))+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_NUMBER) {+            if (JS_IsNumber(p->u.object_data))+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a number");+}++static JSValue js_number_valueOf(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return js_thisNumberValue(ctx, this_val);+}++static int js_get_radix(JSContext *ctx, JSValueConst val)+{+    int radix;+    if (JS_ToInt32Sat(ctx, &radix, val))+        return -1;+    if (radix < 2 || radix > 36) {+        JS_ThrowRangeError(ctx, "radix must be between 2 and 36");+        return -1;+    }+    return radix;+}++static JSValue js_number_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv, int magic)+{+    JSValue val;+    int base;+    double d;++    val = js_thisNumberValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (magic || JS_IsUndefined(argv[0])) {+        base = 10;+    } else {+        base = js_get_radix(ctx, argv[0]);+        if (base < 0)+            goto fail;+    }+    if (JS_ToFloat64Free(ctx, &d, val))+        return JS_EXCEPTION;+    return js_dtoa(ctx, d, base, 0, JS_DTOA_VAR_FORMAT);+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue val;+    int f;+    double d;++    val = js_thisNumberValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToFloat64Free(ctx, &d, val))+        return JS_EXCEPTION;+    if (JS_ToInt32Sat(ctx, &f, argv[0]))+        return JS_EXCEPTION;+    if (f < 0 || f > 100)+        return JS_ThrowRangeError(ctx, "invalid number of digits");+    if (fabs(d) >= 1e21) {+        return JS_ToStringFree(ctx, __JS_NewFloat64(ctx, d));+    } else {+        return js_dtoa(ctx, d, 10, f, JS_DTOA_FRAC_FORMAT);+    }+}++static JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValue val;+    int f, flags;+    double d;++    val = js_thisNumberValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToFloat64Free(ctx, &d, val))+        return JS_EXCEPTION;+    if (JS_ToInt32Sat(ctx, &f, argv[0]))+        return JS_EXCEPTION;+    if (!isfinite(d)) {+        return JS_ToStringFree(ctx,  __JS_NewFloat64(ctx, d));+    }+    if (JS_IsUndefined(argv[0])) {+        flags = 0;+        f = 0;+    } else {+        if (f < 0 || f > 100)+            return JS_ThrowRangeError(ctx, "invalid number of digits");+        f++;+        flags = JS_DTOA_FIXED_FORMAT;+    }+    return js_dtoa(ctx, d, 10, f, flags | JS_DTOA_FORCE_EXP);+}++static JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue val;+    int p;+    double d;++    val = js_thisNumberValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToFloat64Free(ctx, &d, val))+        return JS_EXCEPTION;+    if (JS_IsUndefined(argv[0]))+        goto to_string;+    if (JS_ToInt32Sat(ctx, &p, argv[0]))+        return JS_EXCEPTION;+    if (!isfinite(d)) {+    to_string:+        return JS_ToStringFree(ctx,  __JS_NewFloat64(ctx, d));+    }+    if (p < 1 || p > 100)+        return JS_ThrowRangeError(ctx, "invalid number of digits");+    return js_dtoa(ctx, d, 10, p, JS_DTOA_FIXED_FORMAT);+}++static const JSCFunctionListEntry js_number_proto_funcs[] = {+    JS_CFUNC_DEF("toExponential", 1, js_number_toExponential ),+    JS_CFUNC_DEF("toFixed", 1, js_number_toFixed ),+    JS_CFUNC_DEF("toPrecision", 1, js_number_toPrecision ),+    JS_CFUNC_MAGIC_DEF("toString", 1, js_number_toString, 0 ),+    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, js_number_toString, 1 ),+    JS_CFUNC_DEF("valueOf", 0, js_number_valueOf ),+};++static JSValue js_parseInt(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv)+{+    const char *str, *p;+    int radix, flags;+    JSValue ret;++    str = JS_ToCString(ctx, argv[0]);+    if (!str)+        return JS_EXCEPTION;+    if (JS_ToInt32(ctx, &radix, argv[1])) {+        JS_FreeCString(ctx, str);+        return JS_EXCEPTION;+    }+    if (radix != 0 && (radix < 2 || radix > 36)) {+        ret = JS_NAN;+    } else {+        p = str;+        p += skip_spaces(p);+        flags = ATOD_INT_ONLY | ATOD_ACCEPT_PREFIX_AFTER_SIGN;+        ret = js_atof(ctx, p, NULL, radix, flags);+    }+    JS_FreeCString(ctx, str);+    return ret;+}++static JSValue js_parseFloat(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    const char *str, *p;+    JSValue ret;++    str = JS_ToCString(ctx, argv[0]);+    if (!str)+        return JS_EXCEPTION;+    p = str;+    p += skip_spaces(p);+    ret = js_atof(ctx, p, NULL, 10, 0);+    JS_FreeCString(ctx, str);+    return ret;+}++/* Boolean */+static JSValue js_boolean_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue val, obj;+    val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0]));+    if (!JS_IsUndefined(new_target)) {+        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_BOOLEAN);+        if (!JS_IsException(obj))+            JS_SetObjectData(ctx, obj, val);+        return obj;+    } else {+        return val;+    }+}++static JSValue js_thisBooleanValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL)+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_BOOLEAN) {+            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_BOOL)+                return p->u.object_data;+        }+    }+    return JS_ThrowTypeError(ctx, "not a boolean");+}++static JSValue js_boolean_toString(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    JSValue val = js_thisBooleanValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ?+                       JS_ATOM_true : JS_ATOM_false);+}++static JSValue js_boolean_valueOf(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    return js_thisBooleanValue(ctx, this_val);+}++static const JSCFunctionListEntry js_boolean_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_boolean_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_boolean_valueOf ),+};++/* String */++static int js_string_get_own_property(JSContext *ctx,+                                      JSPropertyDescriptor *desc,+                                      JSValueConst obj, JSAtom prop)+{+    JSObject *p;+    JSString *p1;+    uint32_t idx, ch;++    /* This is a class exotic method: obj class_id is JS_CLASS_STRING */+    if (__JS_AtomIsTaggedInt(prop)) {+        p = JS_VALUE_GET_OBJ(obj);+        if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING) {+            p1 = JS_VALUE_GET_STRING(p->u.object_data);+            idx = __JS_AtomToUInt32(prop);+            if (idx < p1->len) {+                if (desc) {+                    if (p1->is_wide_char)+                        ch = p1->u.str16[idx];+                    else+                        ch = p1->u.str8[idx];+                    desc->flags = JS_PROP_ENUMERABLE;+                    desc->value = js_new_string_char(ctx, ch);+                    desc->getter = JS_UNDEFINED;+                    desc->setter = JS_UNDEFINED;+                }+                return TRUE;+            }+        }+    }+    return FALSE;+}++static int js_string_define_own_property(JSContext *ctx,+                                         JSValueConst this_obj,+                                         JSAtom prop, JSValueConst val,+                                         JSValueConst getter,+                                         JSValueConst setter, int flags)+{+    uint32_t idx;+    JSObject *p;+    JSString *p1, *p2;+    +    if (__JS_AtomIsTaggedInt(prop)) {+        idx = __JS_AtomToUInt32(prop);+        p = JS_VALUE_GET_OBJ(this_obj);+        if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)+            goto def;+        p1 = JS_VALUE_GET_STRING(p->u.object_data);+        if (idx >= p1->len)+            goto def;+        if (!check_define_prop_flags(JS_PROP_ENUMERABLE, flags))+            goto fail;+        /* check that the same value is configured */+        if (flags & JS_PROP_HAS_VALUE) {+            if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)+                goto fail;+            p2 = JS_VALUE_GET_STRING(val);+            if (p2->len != 1)+                goto fail;+            if (string_get(p1, idx) != string_get(p2, 0)) {+            fail:+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");+            }+        }+        return TRUE;+    } else {+    def:+        return JS_DefineProperty(ctx, this_obj, prop, val, getter, setter,+                                 flags | JS_PROP_NO_EXOTIC);+    }+}++static int js_string_delete_property(JSContext *ctx,+                                     JSValueConst obj, JSAtom prop)+{+    uint32_t idx;++    if (__JS_AtomIsTaggedInt(prop)) {+        idx = __JS_AtomToUInt32(prop);+        if (idx < js_string_obj_get_length(ctx, obj)) {+            return FALSE;+        }+    }+    return TRUE;+}++static const JSClassExoticMethods js_string_exotic_methods = {+    .get_own_property = js_string_get_own_property,+    .define_own_property = js_string_define_own_property,+    .delete_property = js_string_delete_property,+};++static JSValue js_string_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue val, obj;+    if (argc == 0) {+        val = JS_AtomToString(ctx, JS_ATOM_empty_string);+    } else {+        if (JS_IsUndefined(new_target) && JS_IsSymbol(argv[0])) {+            JSAtomStruct *p = JS_VALUE_GET_PTR(argv[0]);+            val = JS_ConcatString3(ctx, "Symbol(", JS_AtomToString(ctx, js_get_atom_index(ctx->rt, p)), ")");+        } else {+            val = JS_ToString(ctx, argv[0]);+        }+        if (JS_IsException(val))+            return val;+    }+    if (!JS_IsUndefined(new_target)) {+        JSString *p1 = JS_VALUE_GET_STRING(val);++        obj = js_create_from_ctor(ctx, new_target, JS_CLASS_STRING);+        if (!JS_IsException(obj)) {+            JS_SetObjectData(ctx, obj, val);+            JS_DefinePropertyValue(ctx, obj, JS_ATOM_length, JS_NewInt32(ctx, p1->len), 0);+        }+        return obj;+    } else {+        return val;+    }+}++static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_STRING)+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_STRING) {+            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_STRING)+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a string");+}++static JSValue js_string_fromCharCode(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    int i;+    StringBuffer b_s, *b = &b_s;++    string_buffer_init(ctx, b, argc);++    for(i = 0; i < argc; i++) {+        int32_t c;+        if (JS_ToInt32(ctx, &c, argv[i]) || string_buffer_putc16(b, c & 0xffff)) {+            string_buffer_free(b);+            return JS_EXCEPTION;+        }+    }+    return string_buffer_end(b);+}++static JSValue js_string_fromCodePoint(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    double d;+    int i, c;+    StringBuffer b_s, *b = &b_s;++    /* XXX: could pre-compute string length if all arguments are JS_TAG_INT */++    if (string_buffer_init(ctx, b, argc))+        goto fail;+    for(i = 0; i < argc; i++) {+        if (JS_VALUE_GET_TAG(argv[i]) == JS_TAG_INT) {+            c = JS_VALUE_GET_INT(argv[i]);+            if (c < 0 || c > 0x10ffff)+                goto range_error;+        } else {+            if (JS_ToFloat64(ctx, &d, argv[i]))+                goto fail;+            if (d < 0 || d > 0x10ffff || (c = (int)d) != d)+                goto range_error;+        }+        if (string_buffer_putc(b, c))+            goto fail;+    }+    return string_buffer_end(b);++ range_error:+    JS_ThrowRangeError(ctx, "invalid code point");+ fail:+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue js_string_raw(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    // raw(temp,...a)+    JSValue cooked, val, raw;+    StringBuffer b_s, *b = &b_s;+    int64_t i, n;++    string_buffer_init(ctx, b, 0);+    raw = JS_UNDEFINED;+    cooked = JS_ToObject(ctx, argv[0]);+    if (JS_IsException(cooked))+        goto exception;+    raw = JS_ToObjectFree(ctx, JS_GetProperty(ctx, cooked, JS_ATOM_raw));+    if (JS_IsException(raw))+        goto exception;+    if (js_get_length64(ctx, &n, raw) < 0)+        goto exception;+        +    for (i = 0; i < n; i++) {+        val = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, raw, i));+        if (JS_IsException(val))+            goto exception;+        string_buffer_concat_value_free(b, val);+        if (i < n - 1 && i + 1 < argc) {+            if (string_buffer_concat_value(b, argv[i + 1]))+                goto exception;+        }+    }+    JS_FreeValue(ctx, cooked);+    JS_FreeValue(ctx, raw);+    return string_buffer_end(b);++exception:+    JS_FreeValue(ctx, cooked);+    JS_FreeValue(ctx, raw);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++/* only used in test262 */+JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    uint32_t start, end, i, n;+    StringBuffer b_s, *b = &b_s;++    if (JS_ToUint32(ctx, &start, argv[0]) ||+        JS_ToUint32(ctx, &end, argv[1]))+        return JS_EXCEPTION;+    end = min_uint32(end, 0x10ffff + 1);++    if (start > end) {+        start = end;+    }+    n = end - start;+    if (end > 0x10000) {+        n += end - max_uint32(start, 0x10000);+    }+    if (string_buffer_init2(ctx, b, n, end >= 0x100))+        return JS_EXCEPTION;+    for(i = start; i < end; i++) {+        string_buffer_putc(b, i);+    }+    return string_buffer_end(b);+}++#if 0+static JSValue js_string___isSpace(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    int c;+    if (JS_ToInt32(ctx, &c, argv[0]))+        return JS_EXCEPTION;+    return JS_NewBool(ctx, lre_is_space(c));+}+#endif++static JSValue js_string_charCodeAt(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue val, ret;+    JSString *p;+    int idx, c;++    val = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_STRING(val);+    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {+        JS_FreeValue(ctx, val);+        return JS_EXCEPTION;+    }+    if (idx < 0 || idx >= p->len) {+        ret = JS_NAN;+    } else {+        if (p->is_wide_char)+            c = p->u.str16[idx];+        else+            c = p->u.str8[idx];+        ret = JS_NewInt32(ctx, c);+    }+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue js_string_charAt(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue val, ret;+    JSString *p;+    int idx, c;++    val = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_STRING(val);+    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {+        JS_FreeValue(ctx, val);+        return JS_EXCEPTION;+    }+    if (idx < 0 || idx >= p->len) {+        ret = js_new_string8(ctx, NULL, 0);+    } else {+        if (p->is_wide_char)+            c = p->u.str16[idx];+        else+            c = p->u.str8[idx];+        ret = js_new_string_char(ctx, c);+    }+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue js_string_codePointAt(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue val, ret;+    JSString *p;+    int idx, c;++    val = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_STRING(val);+    if (JS_ToInt32Sat(ctx, &idx, argv[0])) {+        JS_FreeValue(ctx, val);+        return JS_EXCEPTION;+    }+    if (idx < 0 || idx >= p->len) {+        ret = JS_UNDEFINED;+    } else {+        c = string_getc(p, &idx);+        ret = JS_NewInt32(ctx, c);+    }+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue r;+    int i;++    /* XXX: Use more efficient method */+    /* XXX: This method is OK if r has a single refcount */+    /* XXX: should use string_buffer? */+    r = JS_ToStringCheckObject(ctx, this_val);+    for (i = 0; i < argc; i++) {+        if (JS_IsException(r))+            break;+        r = JS_ConcatString(ctx, r, JS_DupValue(ctx, argv[i]));+    }+    return r;+}++static int string_cmp(JSString *p1, JSString *p2, int x1, int x2, int len)+{+    int i, c1, c2;+    for (i = 0; i < len; i++) {+        if ((c1 = string_get(p1, x1 + i)) != (c2 = string_get(p2, x2 + i)))+            return c1 - c2;+    }+    return 0;+}++static int string_indexof_char(JSString *p, int c, int from)+{+    /* assuming 0 <= from <= p->len */+    int i, len = p->len;+    if (p->is_wide_char) {+        for (i = from; i < len; i++) {+            if (p->u.str16[i] == c)+                return i;+        }+    } else {+        if ((c & ~0xff) == 0) {+            for (i = from; i < len; i++) {+                if (p->u.str8[i] == (uint8_t)c)+                    return i;+            }+        }+    }+    return -1;+}++static int string_indexof(JSString *p1, JSString *p2, int from)+{+    /* assuming 0 <= from <= p1->len */+    int c, i, j, len1 = p1->len, len2 = p2->len;+    if (len2 == 0)+        return from;+    for (i = from, c = string_get(p2, 0); i + len2 <= len1; i = j + 1) {+        j = string_indexof_char(p1, c, i);+        if (j < 0 || j + len2 > len1)+            break;+        if (!string_cmp(p1, p2, j + 1, 1, len2 - 1))+            return j;+    }+    return -1;+}++static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)+{+    if (!unicode || index >= p->len || !p->is_wide_char) {+        index++;+    } else {+        int index32 = (int)index;+        string_getc(p, &index32);+        index = index32;+    }+    return index;+}++static JSValue js_string_indexOf(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv, int lastIndexOf)+{+    JSValue str, v;+    int i, len, v_len, pos, start, stop, ret, inc;+    JSString *p;+    JSString *p1;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    v = JS_ToString(ctx, argv[0]);+    if (JS_IsException(v))+        goto fail;+    p = JS_VALUE_GET_STRING(str);+    p1 = JS_VALUE_GET_STRING(v);+    len = p->len;+    v_len = p1->len;+    if (lastIndexOf) {+        pos = len - v_len;+        if (argc > 1) {+            double d;+            if (JS_ToFloat64(ctx, &d, argv[1]))+                goto fail;+            if (!isnan(d)) {+                if (d <= 0)+                    pos = 0;+                else if (d < pos)+                    pos = d;+            }+        }+        start = pos;+        stop = 0;+        inc = -1;+    } else {+        pos = 0;+        if (argc > 1) {+            if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))+                goto fail;+        }+        start = pos;+        stop = len - v_len;+        inc = 1;+    }+    ret = -1;+    if (len >= v_len && inc * (stop - start) >= 0) {+        for (i = start;; i += inc) {+            if (!string_cmp(p, p1, i, 0, v_len)) {+                ret = i;+                break;+            }+            if (i == stop)+                break;+        }+    }+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, v);+    return JS_NewInt32(ctx, ret);++fail:+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, v);+    return JS_EXCEPTION;+}++/* return < 0 if exception or TRUE/FALSE */+static int js_is_regexp(JSContext *ctx, JSValueConst obj);++static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv, int magic)+{+    JSValue str, v = JS_UNDEFINED;+    int i, len, v_len, pos, start, stop, ret;+    JSString *p;+    JSString *p1;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    ret = js_is_regexp(ctx, argv[0]);+    if (ret) {+        if (ret > 0)+            JS_ThrowTypeError(ctx, "regex not supported");+        goto fail;+    }+    v = JS_ToString(ctx, argv[0]);+    if (JS_IsException(v))+        goto fail;+    p = JS_VALUE_GET_STRING(str);+    p1 = JS_VALUE_GET_STRING(v);+    len = p->len;+    v_len = p1->len;+    pos = (magic == 2) ? len : 0;+    if (argc > 1 && !JS_IsUndefined(argv[1])) {+        if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0))+            goto fail;+    }+    len -= v_len;+    ret = 0;+    if (magic == 0) {+        start = pos;+        stop = len;+    } else {+        if (magic == 1) {+            if (pos > len)+                goto done;+        } else {+            pos -= v_len;+        }+        start = stop = pos;+    }+    if (start >= 0 && start <= stop) {+        for (i = start;; i++) {+            if (!string_cmp(p, p1, i, 0, v_len)) {+                ret = 1;+                break;+            }+            if (i == stop)+                break;+        }+    }+ done:+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, v);+    return JS_NewBool(ctx, ret);++fail:+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, v);+    return JS_EXCEPTION;+}++static int check_regexp_g_flag(JSContext *ctx, JSValueConst regexp)+{+    int ret;+    JSValue flags;+    +    ret = js_is_regexp(ctx, regexp);+    if (ret < 0)+        return -1;+    if (ret) {+        flags = JS_GetProperty(ctx, regexp, JS_ATOM_flags);+        if (JS_IsException(flags))+            return -1;+        if (JS_IsUndefined(flags) || JS_IsNull(flags)) {+            JS_ThrowTypeError(ctx, "cannot convert to object");+            return -1;+        }+        flags = JS_ToStringFree(ctx, flags);+        if (JS_IsException(flags))+            return -1;+        ret = string_indexof_char(JS_VALUE_GET_STRING(flags), 'g', 0);+        JS_FreeValue(ctx, flags);+        if (ret < 0) {+            JS_ThrowTypeError(ctx, "regexp must have the 'g' flag");+            return -1;+        }+    }+    return 0;+}++static JSValue js_string_match(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv, int atom)+{+    // match(rx), search(rx), matchAll(rx)+    // atom is JS_ATOM_Symbol_match, JS_ATOM_Symbol_search, or JS_ATOM_Symbol_matchAll+    JSValueConst O = this_val, regexp = argv[0], args[2];+    JSValue matcher, S, rx, result, str;+    int args_len;++    if (JS_IsUndefined(O) || JS_IsNull(O))+        return JS_ThrowTypeError(ctx, "cannot convert to object");++    if (!JS_IsUndefined(regexp) && !JS_IsNull(regexp)) {+        matcher = JS_GetProperty(ctx, regexp, atom);+        if (JS_IsException(matcher))+            return JS_EXCEPTION;+        if (atom == JS_ATOM_Symbol_matchAll) {+            if (check_regexp_g_flag(ctx, regexp) < 0) {+                JS_FreeValue(ctx, matcher);+                return JS_EXCEPTION;+            }+        }+        if (!JS_IsUndefined(matcher) && !JS_IsNull(matcher)) {+            return JS_CallFree(ctx, matcher, regexp, 1, &O);+        }+    }+    S = JS_ToString(ctx, O);+    if (JS_IsException(S))+        return JS_EXCEPTION;+    args_len = 1;+    args[0] = regexp;+    str = JS_UNDEFINED;+    if (atom == JS_ATOM_Symbol_matchAll) {+        str = JS_NewString(ctx, "g");+        if (JS_IsException(str))+            goto fail;+        args[args_len++] = (JSValueConst)str;+    }+    rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args);+    JS_FreeValue(ctx, str);+    if (JS_IsException(rx)) {+    fail:+        JS_FreeValue(ctx, S);+        return JS_EXCEPTION;+    }+    result = JS_InvokeFree(ctx, rx, atom, 1, (JSValueConst *)&S);+    JS_FreeValue(ctx, S);+    return result;+}++static JSValue js_string___GetSubstitution(JSContext *ctx, JSValueConst this_val,+                                           int argc, JSValueConst *argv)+{+    // GetSubstitution(matched, str, position, captures, namedCaptures, rep)+    JSValueConst matched, str, captures, namedCaptures, rep;+    JSValue capture, name, s;+    uint32_t position, len, matched_len, captures_len;+    int i, j, j0, k, k1;+    int c, c1;+    StringBuffer b_s, *b = &b_s;+    JSString *sp, *rp;++    matched = argv[0];+    str = argv[1];+    captures = argv[3];+    namedCaptures = argv[4];+    rep = argv[5];++    if (!JS_IsString(rep) || !JS_IsString(str))+        return JS_ThrowTypeError(ctx, "not a string");++    sp = JS_VALUE_GET_STRING(str);+    rp = JS_VALUE_GET_STRING(rep);++    string_buffer_init(ctx, b, 0);++    captures_len = 0;+    if (!JS_IsUndefined(captures)) {+        if (js_get_length32(ctx, &captures_len, captures))+            goto exception;+    }+    if (js_get_length32(ctx, &matched_len, matched))+        goto exception;+    if (JS_ToUint32(ctx, &position, argv[2]) < 0)+        goto exception;++    len = rp->len;+    i = 0;+    for(;;) {+        j = string_indexof_char(rp, '$', i);+        if (j < 0 || j + 1 >= len)+            break;+        string_buffer_concat(b, rp, i, j);+        j0 = j++;+        c = string_get(rp, j++);+        if (c == '$') {+            string_buffer_putc8(b, '$');+        } else if (c == '&') {+            if (string_buffer_concat_value(b, matched))+                goto exception;+        } else if (c == '`') {+            string_buffer_concat(b, sp, 0, position);+        } else if (c == '\'') {+            string_buffer_concat(b, sp, position + matched_len, sp->len);+        } else if (c >= '0' && c <= '9') {+            k = c - '0';+            if (j < len) {+                c1 = string_get(rp, j);+                if (c1 >= '0' && c1 <= '9') {+                    /* This behavior is specified in ES6 and refined in ECMA 2019 */+                    /* ECMA 2019 does not have the extra test, but+                       Test262 S15.5.4.11_A3_T1..3 require this behavior */+                    k1 = k * 10 + c1 - '0';+                    if (k1 >= 1 && k1 < captures_len) {+                        k = k1;+                        j++;+                    }+                }+            }+            if (k >= 1 && k < captures_len) {+                s = JS_GetPropertyInt64(ctx, captures, k);+                if (JS_IsException(s))+                    goto exception;+                if (!JS_IsUndefined(s)) {+                    if (string_buffer_concat_value_free(b, s))+                        goto exception;+                }+            } else {+                goto norep;+            }+        } else if (c == '<' && !JS_IsUndefined(namedCaptures)) {+            k = string_indexof_char(rp, '>', j);+            if (k < 0)+                goto norep;+            name = js_sub_string(ctx, rp, j, k);+            if (JS_IsException(name))+                goto exception;+            capture = JS_GetPropertyValue(ctx, namedCaptures, name);+            if (JS_IsException(capture))+                goto exception;+            if (!JS_IsUndefined(capture)) {+                if (string_buffer_concat_value_free(b, capture))+                    goto exception;+            }+            j = k + 1;+        } else {+        norep:+            string_buffer_concat(b, rp, j0, j);+        }+        i = j;+    }+    string_buffer_concat(b, rp, i, rp->len);+    return string_buffer_end(b);+exception:+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv,+                                 int is_replaceAll)+{+    // replace(rx, rep)+    JSValueConst O = this_val, searchValue = argv[0], replaceValue = argv[1];+    JSValueConst args[6];+    JSValue str, search_str, replaceValue_str, repl_str;+    JSString *sp, *searchp;+    StringBuffer b_s, *b = &b_s;+    int pos, functionalReplace, endOfLastMatch;+    BOOL is_first;++    if (JS_IsUndefined(O) || JS_IsNull(O))+        return JS_ThrowTypeError(ctx, "cannot convert to object");++    search_str = JS_UNDEFINED;+    replaceValue_str = JS_UNDEFINED;+    repl_str = JS_UNDEFINED;++    if (!JS_IsUndefined(searchValue) && !JS_IsNull(searchValue)) {+        JSValue replacer;+        if (is_replaceAll) {+            if (check_regexp_g_flag(ctx, searchValue) < 0)+                return JS_EXCEPTION;+        }+        replacer = JS_GetProperty(ctx, searchValue, JS_ATOM_Symbol_replace);+        if (JS_IsException(replacer))+            return JS_EXCEPTION;+        if (!JS_IsUndefined(replacer) && !JS_IsNull(replacer)) {+            args[0] = O;+            args[1] = replaceValue;+            return JS_CallFree(ctx, replacer, searchValue, 2, args);+        }+    }+    string_buffer_init(ctx, b, 0);++    str = JS_ToString(ctx, O);+    if (JS_IsException(str))+        goto exception;+    search_str = JS_ToString(ctx, searchValue);+    if (JS_IsException(search_str))+        goto exception;+    functionalReplace = JS_IsFunction(ctx, replaceValue);+    if (!functionalReplace) {+        replaceValue_str = JS_ToString(ctx, replaceValue);+        if (JS_IsException(replaceValue_str))+            goto exception;+    }++    sp = JS_VALUE_GET_STRING(str);+    searchp = JS_VALUE_GET_STRING(search_str);+    endOfLastMatch = 0;+    is_first = TRUE;+    for(;;) {+        if (unlikely(searchp->len == 0)) {+            if (is_first)+                pos = 0;+            else if (endOfLastMatch >= sp->len)+                pos = -1;+            else+                pos = endOfLastMatch + 1;+        } else {+            pos = string_indexof(sp, searchp, endOfLastMatch);+        }+        if (pos < 0) {+            if (is_first) {+                string_buffer_free(b);+                JS_FreeValue(ctx, search_str);+                JS_FreeValue(ctx, replaceValue_str);+                return str;+            } else {+                break;+            }+        }+        if (functionalReplace) {+            args[0] = search_str;+            args[1] = JS_NewInt32(ctx, pos);+            args[2] = str;+            repl_str = JS_ToStringFree(ctx, JS_Call(ctx, replaceValue, JS_UNDEFINED, 3, args));+        } else {+            args[0] = search_str;+            args[1] = str;+            args[2] = JS_NewInt32(ctx, pos);+            args[3] = JS_UNDEFINED;+            args[4] = JS_UNDEFINED;+            args[5] = replaceValue_str;+            repl_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args);+        }+        if (JS_IsException(repl_str))+            goto exception;+        +        string_buffer_concat(b, sp, endOfLastMatch, pos);+        string_buffer_concat_value_free(b, repl_str);+        endOfLastMatch = pos + searchp->len;+        is_first = FALSE;+        if (!is_replaceAll)+            break;+    }+    string_buffer_concat(b, sp, endOfLastMatch, sp->len);+    JS_FreeValue(ctx, search_str);+    JS_FreeValue(ctx, replaceValue_str);+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);++exception:+    string_buffer_free(b);+    JS_FreeValue(ctx, search_str);+    JS_FreeValue(ctx, replaceValue_str);+    JS_FreeValue(ctx, str);+    return JS_EXCEPTION;+}++static JSValue js_string_split(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    // split(sep, limit)+    JSValueConst O = this_val, separator = argv[0], limit = argv[1];+    JSValueConst args[2];+    JSValue S, A, R, T;+    uint32_t lim, lengthA;+    int64_t p, q, s, r, e;+    JSString *sp, *rp;++    if (JS_IsUndefined(O) || JS_IsNull(O))+        return JS_ThrowTypeError(ctx, "cannot convert to object");++    S = JS_UNDEFINED;+    A = JS_UNDEFINED;+    R = JS_UNDEFINED;++    if (!JS_IsUndefined(separator) && !JS_IsNull(separator)) {+        JSValue splitter;+        splitter = JS_GetProperty(ctx, separator, JS_ATOM_Symbol_split);+        if (JS_IsException(splitter))+            return JS_EXCEPTION;+        if (!JS_IsUndefined(splitter) && !JS_IsNull(splitter)) {+            args[0] = O;+            args[1] = limit;+            return JS_CallFree(ctx, splitter, separator, 2, args);+        }+    }+    S = JS_ToString(ctx, O);+    if (JS_IsException(S))+        goto exception;+    A = JS_NewArray(ctx);+    if (JS_IsException(A))+        goto exception;+    lengthA = 0;+    if (JS_IsUndefined(limit)) {+        lim = 0xffffffff;+    } else {+        if (JS_ToUint32(ctx, &lim, limit) < 0)+            goto exception;+    }+    sp = JS_VALUE_GET_STRING(S);+    s = sp->len;+    R = JS_ToString(ctx, separator);+    if (JS_IsException(R))+        goto exception;+    rp = JS_VALUE_GET_STRING(R);+    r = rp->len;+    p = 0;+    if (lim == 0)+        goto done;+    if (JS_IsUndefined(separator))+        goto add_tail;+    if (s == 0) {+        if (r != 0)+            goto add_tail;+        goto done;+    }+    q = p;+    for (q = p; (q += !r) <= s - r - !r; q = p = e + r) {+        e = string_indexof(sp, rp, q);+        if (e < 0)+            break;+        T = js_sub_string(ctx, sp, p, e);+        if (JS_IsException(T))+            goto exception;+        if (JS_CreateDataPropertyUint32(ctx, A, lengthA++, T, 0) < 0)+            goto exception;+        if (lengthA == lim)+            goto done;+    }+add_tail:+    T = js_sub_string(ctx, sp, p, s);+    if (JS_IsException(T))+        goto exception;+    if (JS_CreateDataPropertyUint32(ctx, A, lengthA++, T,0 ) < 0)+        goto exception;+done:+    JS_FreeValue(ctx, S);+    JS_FreeValue(ctx, R);+    return A;++exception:+    JS_FreeValue(ctx, A);+    JS_FreeValue(ctx, S);+    JS_FreeValue(ctx, R);+    return JS_EXCEPTION;+}++static JSValue js_string_substring(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    JSValue str, ret;+    int a, b, start, end;+    JSString *p;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    p = JS_VALUE_GET_STRING(str);+    if (JS_ToInt32Clamp(ctx, &a, argv[0], 0, p->len, 0)) {+        JS_FreeValue(ctx, str);+        return JS_EXCEPTION;+    }+    b = p->len;+    if (!JS_IsUndefined(argv[1])) {+        if (JS_ToInt32Clamp(ctx, &b, argv[1], 0, p->len, 0)) {+            JS_FreeValue(ctx, str);+            return JS_EXCEPTION;+        }+    }+    if (a < b) {+        start = a;+        end = b;+    } else {+        start = b;+        end = a;+    }+    ret = js_sub_string(ctx, p, start, end);+    JS_FreeValue(ctx, str);+    return ret;+}++static JSValue js_string_substr(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue str, ret;+    int a, len, n;+    JSString *p;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    p = JS_VALUE_GET_STRING(str);+    len = p->len;+    if (JS_ToInt32Clamp(ctx, &a, argv[0], 0, len, len)) {+        JS_FreeValue(ctx, str);+        return JS_EXCEPTION;+    }+    n = len - a;+    if (!JS_IsUndefined(argv[1])) {+        if (JS_ToInt32Clamp(ctx, &n, argv[1], 0, len - a, 0)) {+            JS_FreeValue(ctx, str);+            return JS_EXCEPTION;+        }+    }+    ret = js_sub_string(ctx, p, a, a + n);+    JS_FreeValue(ctx, str);+    return ret;+}++static JSValue js_string_slice(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    JSValue str, ret;+    int len, start, end;+    JSString *p;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    p = JS_VALUE_GET_STRING(str);+    len = p->len;+    if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len)) {+        JS_FreeValue(ctx, str);+        return JS_EXCEPTION;+    }+    end = len;+    if (!JS_IsUndefined(argv[1])) {+        if (JS_ToInt32Clamp(ctx, &end, argv[1], 0, len, len)) {+            JS_FreeValue(ctx, str);+            return JS_EXCEPTION;+        }+    }+    ret = js_sub_string(ctx, p, start, max_int(end, start));+    JS_FreeValue(ctx, str);+    return ret;+}++static JSValue js_string_pad(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv, int padEnd)+{+    JSValue str, v = JS_UNDEFINED;+    StringBuffer b_s, *b = &b_s;+    JSString *p, *p1 = NULL;+    int n, len, c = ' ';++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        goto fail1;+    if (JS_ToInt32Sat(ctx, &n, argv[0]))+        goto fail2;+    p = JS_VALUE_GET_STRING(str);+    len = p->len;+    if (len >= n)+        return str;+    if (argc > 1 && !JS_IsUndefined(argv[1])) {+        v = JS_ToString(ctx, argv[1]);+        if (JS_IsException(v))+            goto fail2;+        p1 = JS_VALUE_GET_STRING(v);+        if (p1->len == 0) {+            JS_FreeValue(ctx, v);+            return str;+        }+        if (p1->len == 1) {+            c = string_get(p1, 0);+            p1 = NULL;+        }+    }+    if (n > JS_STRING_LEN_MAX) {+        JS_ThrowInternalError(ctx, "string too long");+        goto fail2;+    }+    if (string_buffer_init(ctx, b, n))+        goto fail3;+    n -= len;+    if (padEnd) {+        if (string_buffer_concat(b, p, 0, len))+            goto fail;+    }+    if (p1) {+        while (n > 0) {+            int chunk = min_int(n, p1->len);+            if (string_buffer_concat(b, p1, 0, chunk))+                goto fail;+            n -= chunk;+        }+    } else {+        if (string_buffer_fill(b, c, n))+            goto fail;+    }+    if (!padEnd) {+        if (string_buffer_concat(b, p, 0, len))+            goto fail;+    }+    JS_FreeValue(ctx, v);+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);++fail:+    string_buffer_free(b);+fail3:+    JS_FreeValue(ctx, v);+fail2:+    JS_FreeValue(ctx, str);+fail1:+    return JS_EXCEPTION;+}++static JSValue js_string_repeat(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue str;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int64_t val;+    int n, len;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        goto fail;+    if (JS_ToInt64Sat(ctx, &val, argv[0]))+        goto fail;+    if (val < 0 || val > 2147483647) {+        JS_ThrowRangeError(ctx, "invalid repeat count");+        goto fail;+    }+    n = val;+    p = JS_VALUE_GET_STRING(str);+    len = p->len;+    if (len == 0 || n == 1)+        return str;+    if (val * len > JS_STRING_LEN_MAX) {+        JS_ThrowInternalError(ctx, "string too long");+        goto fail;+    }+    if (string_buffer_init2(ctx, b, n * len, p->is_wide_char))+        goto fail;+    if (len == 1) {+        string_buffer_fill(b, string_get(p, 0), n);+    } else {+        while (n-- > 0) {+            string_buffer_concat(b, p, 0, len);+        }+    }+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);++fail:+    JS_FreeValue(ctx, str);+    return JS_EXCEPTION;+}++static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    JSValue str, ret;+    int a, b, len;+    JSString *p;++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return str;+    p = JS_VALUE_GET_STRING(str);+    a = 0;+    b = len = p->len;+    if (magic & 1) {+        while (a < len && lre_is_space(string_get(p, a)))+            a++;+    }+    if (magic & 2) {+        while (b > a && lre_is_space(string_get(p, b - 1)))+            b--;+    }+    ret = js_sub_string(ctx, p, a, b);+    JS_FreeValue(ctx, str);+    return ret;+}++static JSValue js_string___quote(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return JS_ToQuotedString(ctx, this_val);+}++/* return 0 if before the first char */+static int string_prevc(JSString *p, int *pidx)+{+    int idx, c, c1;++    idx = *pidx;+    if (idx <= 0)+        return 0;+    idx--;+    if (p->is_wide_char) {+        c = p->u.str16[idx];+        if (c >= 0xdc00 && c < 0xe000 && idx > 0) {+            c1 = p->u.str16[idx - 1];+            if (c1 >= 0xd800 && c1 <= 0xdc00) {+                c = (((c1 & 0x3ff) << 10) | (c & 0x3ff)) + 0x10000;+                idx--;+            }+        }+    } else {+        c = p->u.str8[idx];+    }+    *pidx = idx;+    return c;+}++static BOOL test_final_sigma(JSString *p, int sigma_pos)+{+    int k, c1;++    /* before C: skip case ignorable chars and check there is+       a cased letter */+    k = sigma_pos;+    for(;;) {+        c1 = string_prevc(p, &k);+        if (!lre_is_case_ignorable(c1))+            break;+    }+    if (!lre_is_cased(c1))+        return FALSE;++    /* after C: skip case ignorable chars and check there is+       no cased letter */+    k = sigma_pos + 1;+    for(;;) {+        if (k >= p->len)+            return TRUE;+        c1 = string_getc(p, &k);+        if (!lre_is_case_ignorable(c1))+            break;+    }+    return !lre_is_cased(c1);+}++static JSValue js_string_localeCompare(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValue a, b;+    int cmp;++    a = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(a))+        return JS_EXCEPTION;+    b = JS_ToString(ctx, argv[0]);+    if (JS_IsException(b)) {+        JS_FreeValue(ctx, a);+        return JS_EXCEPTION;+    }+    cmp = js_string_compare(ctx, JS_VALUE_GET_STRING(a), JS_VALUE_GET_STRING(b));+    JS_FreeValue(ctx, a);+    JS_FreeValue(ctx, b);+    return JS_NewInt32(ctx, cmp);+}++static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv, int to_lower)+{+    JSValue val;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int i, c, j, l;+    uint32_t res[LRE_CC_RES_LEN_MAX];++    val = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_STRING(val);+    if (p->len == 0)+        return val;+    if (string_buffer_init(ctx, b, p->len))+        goto fail;+    for(i = 0; i < p->len;) {+        c = string_getc(p, &i);+        if (c == 0x3a3 && to_lower && test_final_sigma(p, i - 1)) {+            res[0] = 0x3c2; /* final sigma */+            l = 1;+        } else {+            l = lre_case_conv(res, c, to_lower);+        }+        for(j = 0; j < l; j++) {+            if (string_buffer_putc(b, res[j]))+                goto fail;+        }+    }+    JS_FreeValue(ctx, val);+    return string_buffer_end(b);+ fail:+    JS_FreeValue(ctx, val);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++#ifdef CONFIG_ALL_UNICODE++/* return (-1, NULL) if exception, otherwise (len, buf) */+static int JS_ToUTF32String(JSContext *ctx, uint32_t **pbuf, JSValueConst val1)+{+    JSValue val;+    JSString *p;+    uint32_t *buf;+    int i, j, len;++    val = JS_ToString(ctx, val1);+    if (JS_IsException(val))+        return -1;+    p = JS_VALUE_GET_STRING(val);+    len = p->len;+    /* UTF32 buffer length is len minus the number of correct surrogates pairs */+    buf = js_malloc(ctx, sizeof(buf[0]) * max_int(len, 1));+    if (!buf) {+        JS_FreeValue(ctx, val);+        goto fail;+    }+    for(i = j = 0; i < len;)+        buf[j++] = string_getc(p, &i);+    JS_FreeValue(ctx, val);+    *pbuf = buf;+    return j;+ fail:+    *pbuf = NULL;+    return -1;+}++static JSValue JS_NewUTF32String(JSContext *ctx, const uint32_t *buf, int len)+{+    int i;+    StringBuffer b_s, *b = &b_s;+    if (string_buffer_init(ctx, b, len))+        return JS_EXCEPTION;+    for(i = 0; i < len; i++) {+        if (string_buffer_putc(b, buf[i]))+            goto fail;+    }+    return string_buffer_end(b);+ fail:+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue js_string_normalize(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    const char *form, *p;+    size_t form_len;+    int is_compat, buf_len, out_len;+    UnicodeNormalizationEnum n_type;+    JSValue val;+    uint32_t *buf, *out_buf;++    val = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(val))+        return val;+    buf_len = JS_ToUTF32String(ctx, &buf, val);+    JS_FreeValue(ctx, val);+    if (buf_len < 0)+        return JS_EXCEPTION;++    if (argc == 0 || JS_IsUndefined(argv[0])) {+        n_type = UNICODE_NFC;+    } else {+        form = JS_ToCStringLen(ctx, &form_len, argv[0]);+        if (!form)+            goto fail1;+        p = form;+        if (p[0] != 'N' || p[1] != 'F')+            goto bad_form;+        p += 2;+        is_compat = FALSE;+        if (*p == 'K') {+            is_compat = TRUE;+            p++;+        }+        if (*p == 'C' || *p == 'D') {+            n_type = UNICODE_NFC + is_compat * 2 + (*p - 'C');+            if ((p + 1 - form) != form_len)+                goto bad_form;+        } else {+        bad_form:+            JS_FreeCString(ctx, form);+            JS_ThrowRangeError(ctx, "bad normalization form");+        fail1:+            js_free(ctx, buf);+            return JS_EXCEPTION;+        }+        JS_FreeCString(ctx, form);+    }++    out_len = unicode_normalize(&out_buf, buf, buf_len, n_type,+                                ctx->rt, (DynBufReallocFunc *)js_realloc_rt);+    js_free(ctx, buf);+    if (out_len < 0)+        return JS_EXCEPTION;+    val = JS_NewUTF32String(ctx, out_buf, out_len);+    js_free(ctx, out_buf);+    return val;+}+#endif /* CONFIG_ALL_UNICODE */++/* also used for String.prototype.valueOf */+static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    return js_thisStringValue(ctx, this_val);+}++#if 0+static JSValue js_string___toStringCheckObject(JSContext *ctx, JSValueConst this_val,+                                               int argc, JSValueConst *argv)+{+    return JS_ToStringCheckObject(ctx, argv[0]);+}++static JSValue js_string___toString(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    return JS_ToString(ctx, argv[0]);+}++static JSValue js_string___advanceStringIndex(JSContext *ctx, JSValueConst+                                              this_val,+                                              int argc, JSValueConst *argv)+{+    JSValue str;+    int idx;+    BOOL is_unicode;+    JSString *p;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return str;+    if (JS_ToInt32Sat(ctx, &idx, argv[1])) {+        JS_FreeValue(ctx, str);+        return JS_EXCEPTION;+    }+    is_unicode = JS_ToBool(ctx, argv[2]);+    p = JS_VALUE_GET_STRING(str);+    if (!is_unicode || (unsigned)idx >= p->len || !p->is_wide_char) {+        idx++;+    } else {+        string_getc(p, &idx);+    }+    JS_FreeValue(ctx, str);+    return JS_NewInt32(ctx, idx);+}+#endif++/* String Iterator */++static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv,+                                       BOOL *pdone, int magic)+{+    JSArrayIteratorData *it;+    uint32_t idx, c, start;+    JSString *p;++    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_STRING_ITERATOR);+    if (!it) {+        *pdone = FALSE;+        return JS_EXCEPTION;+    }+    if (JS_IsUndefined(it->obj))+        goto done;+    p = JS_VALUE_GET_STRING(it->obj);+    idx = it->idx;+    if (idx >= p->len) {+        JS_FreeValue(ctx, it->obj);+        it->obj = JS_UNDEFINED;+    done:+        *pdone = TRUE;+        return JS_UNDEFINED;+    }++    start = idx;+    c = string_getc(p, (int *)&idx);+    it->idx = idx;+    *pdone = FALSE;+    if (c <= 0xffff) {+        return js_new_string_char(ctx, c);+    } else {+        return js_new_string16(ctx, p->u.str16 + start, 2);+    }+}++/* ES6 Annex B 2.3.2 etc. */+enum {+    magic_string_anchor,+    magic_string_big,+    magic_string_blink,+    magic_string_bold,+    magic_string_fixed,+    magic_string_fontcolor,+    magic_string_fontsize,+    magic_string_italics,+    magic_string_link,+    magic_string_small,+    magic_string_strike,+    magic_string_sub,+    magic_string_sup,+};++static JSValue js_string_CreateHTML(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv, int magic)+{+    JSValue str;+    const JSString *p;+    StringBuffer b_s, *b = &b_s;+    static struct { const char *tag, *attr; } const defs[] = {+        { "a", "name" }, { "big", NULL }, { "blink", NULL }, { "b", NULL },+        { "tt", NULL }, { "font", "color" }, { "font", "size" }, { "i", NULL },+        { "a", "href" }, { "small", NULL }, { "strike", NULL }, +        { "sub", NULL }, { "sup", NULL },+    };++    str = JS_ToStringCheckObject(ctx, this_val);+    if (JS_IsException(str))+        return JS_EXCEPTION;+    string_buffer_init(ctx, b, 7);+    string_buffer_putc8(b, '<');+    string_buffer_puts8(b, defs[magic].tag);+    if (defs[magic].attr) {+        // r += " " + attr + "=\"" + value + "\"";+        JSValue value;+        int i;++        string_buffer_putc8(b, ' ');+        string_buffer_puts8(b, defs[magic].attr);+        string_buffer_puts8(b, "=\"");+        value = JS_ToStringCheckObject(ctx, argv[0]);+        if (JS_IsException(value)) {+            JS_FreeValue(ctx, str);+            string_buffer_free(b);+            return JS_EXCEPTION;+        }+        p = JS_VALUE_GET_STRING(value);+        for (i = 0; i < p->len; i++) {+            int c = string_get(p, i);+            if (c == '"') {+                string_buffer_puts8(b, "&quot;");+            } else {+                string_buffer_putc16(b, c);+            }+        }+        JS_FreeValue(ctx, value);+        string_buffer_putc8(b, '\"');+    }+    // return r + ">" + str + "</" + tag + ">";+    string_buffer_putc8(b, '>');+    string_buffer_concat_value_free(b, str);+    string_buffer_puts8(b, "</");+    string_buffer_puts8(b, defs[magic].tag);+    string_buffer_putc8(b, '>');+    return string_buffer_end(b);+}++static const JSCFunctionListEntry js_string_funcs[] = {+    JS_CFUNC_DEF("fromCharCode", 1, js_string_fromCharCode ),+    JS_CFUNC_DEF("fromCodePoint", 1, js_string_fromCodePoint ),+    JS_CFUNC_DEF("raw", 1, js_string_raw ),+    //JS_CFUNC_DEF("__toString", 1, js_string___toString ),+    //JS_CFUNC_DEF("__isSpace", 1, js_string___isSpace ),+    //JS_CFUNC_DEF("__toStringCheckObject", 1, js_string___toStringCheckObject ),+    //JS_CFUNC_DEF("__advanceStringIndex", 3, js_string___advanceStringIndex ),+    //JS_CFUNC_DEF("__GetSubstitution", 6, js_string___GetSubstitution ),+};++static const JSCFunctionListEntry js_string_proto_funcs[] = {+    JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ),+    JS_CFUNC_DEF("charCodeAt", 1, js_string_charCodeAt ),+    JS_CFUNC_DEF("charAt", 1, js_string_charAt ),+    JS_CFUNC_DEF("concat", 1, js_string_concat ),+    JS_CFUNC_DEF("codePointAt", 1, js_string_codePointAt ),+    JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ),+    JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ),+    JS_CFUNC_MAGIC_DEF("includes", 1, js_string_includes, 0 ),+    JS_CFUNC_MAGIC_DEF("endsWith", 1, js_string_includes, 2 ),+    JS_CFUNC_MAGIC_DEF("startsWith", 1, js_string_includes, 1 ),+    JS_CFUNC_MAGIC_DEF("match", 1, js_string_match, JS_ATOM_Symbol_match ),+    JS_CFUNC_MAGIC_DEF("matchAll", 1, js_string_match, JS_ATOM_Symbol_matchAll ),+    JS_CFUNC_MAGIC_DEF("search", 1, js_string_match, JS_ATOM_Symbol_search ),+    JS_CFUNC_DEF("split", 2, js_string_split ),+    JS_CFUNC_DEF("substring", 2, js_string_substring ),+    JS_CFUNC_DEF("substr", 2, js_string_substr ),+    JS_CFUNC_DEF("slice", 2, js_string_slice ),+    JS_CFUNC_DEF("repeat", 1, js_string_repeat ),+    JS_CFUNC_MAGIC_DEF("replace", 2, js_string_replace, 0 ),+    JS_CFUNC_MAGIC_DEF("replaceAll", 2, js_string_replace, 1 ),+    JS_CFUNC_MAGIC_DEF("padEnd", 1, js_string_pad, 1 ),+    JS_CFUNC_MAGIC_DEF("padStart", 1, js_string_pad, 0 ),+    JS_CFUNC_MAGIC_DEF("trim", 0, js_string_trim, 3 ),+    JS_CFUNC_MAGIC_DEF("trimEnd", 0, js_string_trim, 2 ),+    JS_ALIAS_DEF("trimRight", "trimEnd" ),+    JS_CFUNC_MAGIC_DEF("trimStart", 0, js_string_trim, 1 ),+    JS_ALIAS_DEF("trimLeft", "trimStart" ),+    JS_CFUNC_DEF("toString", 0, js_string_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_string_toString ),+    JS_CFUNC_DEF("__quote", 1, js_string___quote ),+    JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ),+    JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ),+    JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ),+    JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ),+    JS_CFUNC_MAGIC_DEF("toLocaleUpperCase", 0, js_string_toLowerCase, 0 ),+    JS_CFUNC_MAGIC_DEF("[Symbol.iterator]", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE | 4 ),+    /* ES6 Annex B 2.3.2 etc. */+    JS_CFUNC_MAGIC_DEF("anchor", 1, js_string_CreateHTML, magic_string_anchor ),+    JS_CFUNC_MAGIC_DEF("big", 0, js_string_CreateHTML, magic_string_big ),+    JS_CFUNC_MAGIC_DEF("blink", 0, js_string_CreateHTML, magic_string_blink ),+    JS_CFUNC_MAGIC_DEF("bold", 0, js_string_CreateHTML, magic_string_bold ),+    JS_CFUNC_MAGIC_DEF("fixed", 0, js_string_CreateHTML, magic_string_fixed ),+    JS_CFUNC_MAGIC_DEF("fontcolor", 1, js_string_CreateHTML, magic_string_fontcolor ),+    JS_CFUNC_MAGIC_DEF("fontsize", 1, js_string_CreateHTML, magic_string_fontsize ),+    JS_CFUNC_MAGIC_DEF("italics", 0, js_string_CreateHTML, magic_string_italics ),+    JS_CFUNC_MAGIC_DEF("link", 1, js_string_CreateHTML, magic_string_link ),+    JS_CFUNC_MAGIC_DEF("small", 0, js_string_CreateHTML, magic_string_small ),+    JS_CFUNC_MAGIC_DEF("strike", 0, js_string_CreateHTML, magic_string_strike ),+    JS_CFUNC_MAGIC_DEF("sub", 0, js_string_CreateHTML, magic_string_sub ),+    JS_CFUNC_MAGIC_DEF("sup", 0, js_string_CreateHTML, magic_string_sup ),+};++static const JSCFunctionListEntry js_string_iterator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 0, js_string_iterator_next, 0 ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "String Iterator", JS_PROP_CONFIGURABLE ),+};++#ifdef CONFIG_ALL_UNICODE+static const JSCFunctionListEntry js_string_proto_normalize[] = {+    JS_CFUNC_DEF("normalize", 0, js_string_normalize ),+};+#endif++void JS_AddIntrinsicStringNormalize(JSContext *ctx)+{+#ifdef CONFIG_ALL_UNICODE+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize,+                               countof(js_string_proto_normalize));+#endif+}++/* Math */++/* precondition: a and b are not NaN */+static double js_fmin(double a, double b)+{+    if (a == 0 && b == 0) {+        JSFloat64Union a1, b1;+        a1.d = a;+        b1.d = b;+        a1.u64 |= b1.u64;+        return a1.d;+    } else {+        return fmin(a, b);+    }+}++/* precondition: a and b are not NaN */+static double js_fmax(double a, double b)+{+    if (a == 0 && b == 0) {+        JSFloat64Union a1, b1;+        a1.d = a;+        b1.d = b;+        a1.u64 &= b1.u64;+        return a1.d;+    } else {+        return fmax(a, b);+    }+}++static JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv, int magic)+{+    BOOL is_max = magic;+    double r, a;+    int i;+    uint32_t tag;++    if (unlikely(argc == 0)) {+        return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0);+    }++    tag = JS_VALUE_GET_TAG(argv[0]);+    if (tag == JS_TAG_INT) {+        int a1, r1 = JS_VALUE_GET_INT(argv[0]);+        for(i = 1; i < argc; i++) {+            tag = JS_VALUE_GET_TAG(argv[i]);+            if (tag != JS_TAG_INT) {+                r = r1;+                goto generic_case;+            }+            a1 = JS_VALUE_GET_INT(argv[i]);+            if (is_max)+                r1 = max_int(r1, a1);+            else+                r1 = min_int(r1, a1);++        }+        return JS_NewInt32(ctx, r1);+    } else {+        if (JS_ToFloat64(ctx, &r, argv[0]))+            return JS_EXCEPTION;+        i = 1;+    generic_case:+        while (i < argc) {+            if (JS_ToFloat64(ctx, &a, argv[i]))+                return JS_EXCEPTION;+            if (!isnan(r)) {+                if (isnan(a)) {+                    r = a;+                } else {+                    if (is_max)+                        r = js_fmax(r, a);+                    else+                        r = js_fmin(r, a);+                }+            }+            i++;+        }+        return JS_NewFloat64(ctx, r);+    }+}++static double js_math_sign(double a)+{+    if (isnan(a) || a == 0.0)+        return a;+    if (a < 0)+        return -1;+    else+        return 1;+}++static double js_math_round(double a)+{+    JSFloat64Union u;+    uint64_t frac_mask, one;+    unsigned int e, s;++    u.d = a;+    e = (u.u64 >> 52) & 0x7ff;+    if (e < 1023) {+        /* abs(a) < 1 */+        if (e == (1023 - 1) && u.u64 != 0xbfe0000000000000) {+            /* abs(a) > 0.5 or a = 0.5: return +/-1.0 */+            u.u64 = (u.u64 & ((uint64_t)1 << 63)) | ((uint64_t)1023 << 52);+        } else {+            /* return +/-0.0 */+            u.u64 &= (uint64_t)1 << 63;+        }+    } else if (e < (1023 + 52)) {+        s = u.u64 >> 63;+        one = (uint64_t)1 << (52 - (e - 1023));+        frac_mask = one - 1;+        u.u64 += (one >> 1) - s;+        u.u64 &= ~frac_mask; /* truncate to an integer */+    }+    /* otherwise: abs(a) >= 2^52, or NaN, +/-Infinity: no change */+    return u.d;+}++static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    double r, a;+    int i;++    r = 0;+    if (argc > 0) {+        if (JS_ToFloat64(ctx, &r, argv[0]))+            return JS_EXCEPTION;+        if (argc == 1) {+            r = fabs(r);+        } else {+            /* use the built-in function to minimize precision loss */+            for (i = 1; i < argc; i++) {+                if (JS_ToFloat64(ctx, &a, argv[i]))+                    return JS_EXCEPTION;+                r = hypot(r, a);+            }+        }+    }+    return JS_NewFloat64(ctx, r);+}++static double js_math_fround(double a)+{+    return (float)a;+}++static JSValue js_math_imul(JSContext *ctx, JSValueConst this_val,+                            int argc, JSValueConst *argv)+{+    int a, b;++    if (JS_ToInt32(ctx, &a, argv[0]))+        return JS_EXCEPTION;+    if (JS_ToInt32(ctx, &b, argv[1]))+        return JS_EXCEPTION;+    /* purposely ignoring overflow */+    return JS_NewInt32(ctx, a * b);+}++static JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    uint32_t a, r;++    if (JS_ToUint32(ctx, &a, argv[0]))+        return JS_EXCEPTION;+    if (a == 0)+        r = 32;+    else+        r = clz32(a);+    return JS_NewInt32(ctx, r);+}++/* xorshift* random number generator by Marsaglia */+static uint64_t xorshift64star(uint64_t *pstate)+{+    uint64_t x;+    x = *pstate;+    x ^= x >> 12;+    x ^= x << 25;+    x ^= x >> 27;+    *pstate = x;+    return x * 0x2545F4914F6CDD1D;+}++static void js_random_init(JSContext *ctx)+{+    struct timeval tv;+    gettimeofday(&tv, NULL);+    ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;+    /* the state must be non zero */+    if (ctx->random_state == 0)+        ctx->random_state = 1;+}++static JSValue js_math_random(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSFloat64Union u;+    uint64_t v;++    v = xorshift64star(&ctx->random_state);+    /* 1.0 <= u.d < 2 */+    u.u64 = ((uint64_t)0x3ff << 52) | (v >> 12);+    return __JS_NewFloat64(ctx, u.d - 1.0);+}++static const JSCFunctionListEntry js_math_funcs[] = {+    JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),+    JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),+    JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),+    JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ),+    JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ),+    JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),+    JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),++    JS_CFUNC_SPECIAL_DEF("acos", 1, f_f, acos ),+    JS_CFUNC_SPECIAL_DEF("asin", 1, f_f, asin ),+    JS_CFUNC_SPECIAL_DEF("atan", 1, f_f, atan ),+    JS_CFUNC_SPECIAL_DEF("atan2", 2, f_f_f, atan2 ),+    JS_CFUNC_SPECIAL_DEF("cos", 1, f_f, cos ),+    JS_CFUNC_SPECIAL_DEF("exp", 1, f_f, exp ),+    JS_CFUNC_SPECIAL_DEF("log", 1, f_f, log ),+    JS_CFUNC_SPECIAL_DEF("pow", 2, f_f_f, js_pow ),+    JS_CFUNC_SPECIAL_DEF("sin", 1, f_f, sin ),+    JS_CFUNC_SPECIAL_DEF("tan", 1, f_f, tan ),+    /* ES6 */+    JS_CFUNC_SPECIAL_DEF("trunc", 1, f_f, trunc ),+    JS_CFUNC_SPECIAL_DEF("sign", 1, f_f, js_math_sign ),+    JS_CFUNC_SPECIAL_DEF("cosh", 1, f_f, cosh ),+    JS_CFUNC_SPECIAL_DEF("sinh", 1, f_f, sinh ),+    JS_CFUNC_SPECIAL_DEF("tanh", 1, f_f, tanh ),+    JS_CFUNC_SPECIAL_DEF("acosh", 1, f_f, acosh ),+    JS_CFUNC_SPECIAL_DEF("asinh", 1, f_f, asinh ),+    JS_CFUNC_SPECIAL_DEF("atanh", 1, f_f, atanh ),+    JS_CFUNC_SPECIAL_DEF("expm1", 1, f_f, expm1 ),+    JS_CFUNC_SPECIAL_DEF("log1p", 1, f_f, log1p ),+    JS_CFUNC_SPECIAL_DEF("log2", 1, f_f, log2 ),+    JS_CFUNC_SPECIAL_DEF("log10", 1, f_f, log10 ),+    JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),+    JS_CFUNC_DEF("hypot", 2, js_math_hypot ),+    JS_CFUNC_DEF("random", 0, js_math_random ),+    JS_CFUNC_SPECIAL_DEF("fround", 1, f_f, js_math_fround ),+    JS_CFUNC_DEF("imul", 2, js_math_imul ),+    JS_CFUNC_DEF("clz32", 1, js_math_clz32 ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Math", JS_PROP_CONFIGURABLE ),+    JS_PROP_DOUBLE_DEF("E", 2.718281828459045, 0 ),+    JS_PROP_DOUBLE_DEF("LN10", 2.302585092994046, 0 ),+    JS_PROP_DOUBLE_DEF("LN2", 0.6931471805599453, 0 ),+    JS_PROP_DOUBLE_DEF("LOG2E", 1.4426950408889634, 0 ),+    JS_PROP_DOUBLE_DEF("LOG10E", 0.4342944819032518, 0 ),+    JS_PROP_DOUBLE_DEF("PI", 3.141592653589793, 0 ),+    JS_PROP_DOUBLE_DEF("SQRT1_2", 0.7071067811865476, 0 ),+    JS_PROP_DOUBLE_DEF("SQRT2", 1.4142135623730951, 0 ),+};++static const JSCFunctionListEntry js_math_obj[] = {+    JS_OBJECT_DEF("Math", js_math_funcs, countof(js_math_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),+};++/* Date */++#if 0+/* OS dependent: return the UTC time in ms since 1970. */+static JSValue js___date_now(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    int64_t d;+    struct timeval tv;+    gettimeofday(&tv, NULL);+    d = (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);+    return JS_NewInt64(ctx, d);+}+#endif++/* OS dependent: return the UTC time in microseconds since 1970. */+static JSValue js___date_clock(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    int64_t d;+    struct timeval tv;+    gettimeofday(&tv, NULL);+    d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;+    return JS_NewInt64(ctx, d);+}++/* OS dependent. d = argv[0] is in ms from 1970. Return the difference+   between local time and UTC time 'd' in minutes */+static int getTimezoneOffset(int64_t time) {+#if defined(_WIN32)+    /* XXX: TODO */+    return 0;+#else+    time_t ti;+    struct tm tm;++    time /= 1000; /* convert to seconds */+    if (sizeof(time_t) == 4) {+        /* on 32-bit systems, we need to clamp the time value to the+           range of `time_t`. This is better than truncating values to+           32 bits and hopefully provides the same result as 64-bit+           implementation of localtime_r.+         */+        if ((time_t)-1 < 0) {+            if (time < INT32_MIN) {+                time = INT32_MIN;+            } else if (time > INT32_MAX) {+                time = INT32_MAX;+            }+        } else {+            if (time < 0) {+                time = 0;+            } else if (time > UINT32_MAX) {+                time = UINT32_MAX;+            }+        }+    }+    ti = time;+    localtime_r(&ti, &tm);+    return -tm.tm_gmtoff / 60;+#endif+}++#if 0+static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,+                                           int argc, JSValueConst *argv)+{+    double dd;++    if (JS_ToFloat64(ctx, &dd, argv[0]))+        return JS_EXCEPTION;+    if (isnan(dd))+        return __JS_NewFloat64(ctx, dd);+    else+        return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));+}++static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor,+                                          JSValueConst def_proto)+{+    JSValue proto;+    proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);+    if (JS_IsException(proto))+        return proto;+    if (!JS_IsObject(proto)) {+        JS_FreeValue(ctx, proto);+        proto = JS_DupValue(ctx, def_proto);+    }+    return proto;+}++/* create a new date object */+static JSValue js___date_create(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue obj, proto;+    proto = js_get_prototype_from_ctor(ctx, argv[0], argv[1]);+    if (JS_IsException(proto))+        return proto;+    obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_DATE);+    JS_FreeValue(ctx, proto);+    if (!JS_IsException(obj))+        JS_SetObjectData(ctx, obj, JS_DupValue(ctx, argv[2]));+    return obj;+}+#endif++/* RegExp */++static void js_regexp_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSRegExp *re = &p->u.regexp;+    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->bytecode));+    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_STRING, re->pattern));+}++/* create a string containing the RegExp bytecode */+static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,+                                 JSValueConst flags)+{+    const char *str;+    int re_flags, mask;+    uint8_t *re_bytecode_buf;+    size_t i, len;+    int re_bytecode_len;+    JSValue ret;+    char error_msg[64];++    re_flags = 0;+    if (!JS_IsUndefined(flags)) {+        str = JS_ToCStringLen(ctx, &len, flags);+        if (!str)+            return JS_EXCEPTION;+        /* XXX: re_flags = LRE_FLAG_OCTAL unless strict mode? */+        for (i = 0; i < len; i++) {+            switch(str[i]) {+            case 'g':+                mask = LRE_FLAG_GLOBAL;+                break;+            case 'i':+                mask = LRE_FLAG_IGNORECASE;+                break;+            case 'm':+                mask = LRE_FLAG_MULTILINE;+                break;+            case 's':+                mask = LRE_FLAG_DOTALL;+                break;+            case 'u':+                mask = LRE_FLAG_UTF16;+                break;+            case 'y':+                mask = LRE_FLAG_STICKY;+                break;+            default:+                goto bad_flags;+            }+            if ((re_flags & mask) != 0) {+            bad_flags:+                JS_FreeCString(ctx, str);+                return JS_ThrowSyntaxError(ctx, "invalid regular expression flags");+            }+            re_flags |= mask;+        }+        JS_FreeCString(ctx, str);+    }++    str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UTF16));+    if (!str)+        return JS_EXCEPTION;+    re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg,+                                  sizeof(error_msg), str, len, re_flags, ctx);+    JS_FreeCString(ctx, str);+    if (!re_bytecode_buf) {+        JS_ThrowSyntaxError(ctx, "%s", error_msg);+        return JS_EXCEPTION;+    }++    ret = js_new_string8(ctx, re_bytecode_buf, re_bytecode_len);+    js_free(ctx, re_bytecode_buf);+    return ret;+}++/* create a RegExp object from a string containing the RegExp bytecode+   and the source pattern */+static JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor,+                                              JSValue pattern, JSValue bc)+{+    JSValue obj;+    JSObject *p;+    JSRegExp *re;++    /* sanity check */+    if (JS_VALUE_GET_TAG(bc) != JS_TAG_STRING ||+        JS_VALUE_GET_TAG(pattern) != JS_TAG_STRING) {+        JS_ThrowTypeError(ctx, "string expected");+    fail:+        JS_FreeValue(ctx, bc);+        JS_FreeValue(ctx, pattern);+        return JS_EXCEPTION;+    }++    obj = js_create_from_ctor(ctx, ctor, JS_CLASS_REGEXP);+    if (JS_IsException(obj))+        goto fail;+    p = JS_VALUE_GET_OBJ(obj);+    re = &p->u.regexp;+    re->pattern = JS_VALUE_GET_STRING(pattern);+    re->bytecode = JS_VALUE_GET_STRING(bc);+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0),+                           JS_PROP_WRITABLE);+    return obj;+}++static JSRegExp *js_get_regexp(JSContext *ctx, JSValueConst obj, BOOL throw_error)+{+    if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(obj);+        if (p->class_id == JS_CLASS_REGEXP)+            return &p->u.regexp;+    }+    if (throw_error) {+        JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);+    }+    return NULL;+}++/* return < 0 if exception or TRUE/FALSE */+static int js_is_regexp(JSContext *ctx, JSValueConst obj)+{+    JSValue m;++    if (!JS_IsObject(obj))+        return FALSE;+    m = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_match);+    if (JS_IsException(m))+        return -1;+    if (!JS_IsUndefined(m))+        return JS_ToBoolFree(ctx, m);+    return js_get_regexp(ctx, obj, FALSE) != NULL;+}++static JSValue js_regexp_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue pattern, flags, bc, val;+    JSValueConst pat, flags1;+    JSRegExp *re;+    int pat_is_regexp;++    pat = argv[0];+    flags1 = argv[1];+    pat_is_regexp = js_is_regexp(ctx, pat);+    if (pat_is_regexp < 0)+        return JS_EXCEPTION;+    if (JS_IsUndefined(new_target)) {+        /* called as a function */+        new_target = JS_GetActiveFunction(ctx);+        if (pat_is_regexp && JS_IsUndefined(flags1)) {+            JSValue ctor;+            BOOL res;+            ctor = JS_GetProperty(ctx, pat, JS_ATOM_constructor);+            if (JS_IsException(ctor))+                return ctor;+            res = js_same_value(ctx, ctor, new_target);+            JS_FreeValue(ctx, ctor);+            if (res)+                return JS_DupValue(ctx, pat);+        }+    }+    re = js_get_regexp(ctx, pat, FALSE);+    if (re) {+        pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));+        if (JS_IsUndefined(flags1)) {+            bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode));+            goto no_compilation;+        } else {+            flags = JS_ToString(ctx, flags1);+            if (JS_IsException(flags))+                goto fail;+        }+    } else {+        flags = JS_UNDEFINED;+        if (pat_is_regexp) {+            pattern = JS_GetProperty(ctx, pat, JS_ATOM_source);+            if (JS_IsException(pattern))+                goto fail;+            if (JS_IsUndefined(flags1)) {+                flags = JS_GetProperty(ctx, pat, JS_ATOM_flags);+                if (JS_IsException(flags))+                    goto fail;+            } else {+                flags = JS_DupValue(ctx, flags1);+            }+        } else {+            pattern = JS_DupValue(ctx, pat);+            flags = JS_DupValue(ctx, flags1);+        }+        if (JS_IsUndefined(pattern)) {+            pattern = JS_AtomToString(ctx, JS_ATOM_empty_string);+        } else {+            val = pattern;+            pattern = JS_ToString(ctx, val);+            JS_FreeValue(ctx, val);+            if (JS_IsException(pattern))+                goto fail;+        }+    }+    bc = js_compile_regexp(ctx, pattern, flags);+    if (JS_IsException(bc))+        goto fail;+    JS_FreeValue(ctx, flags);+ no_compilation:+    return js_regexp_constructor_internal(ctx, new_target, pattern, bc);+ fail:+    JS_FreeValue(ctx, pattern);+    JS_FreeValue(ctx, flags);+    return JS_EXCEPTION;+}++static JSValue js_regexp_compile(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSRegExp *re1, *re;+    JSValueConst pattern1, flags1;+    JSValue bc, pattern;++    re = js_get_regexp(ctx, this_val, TRUE);+    if (!re)+        return JS_EXCEPTION;+    pattern1 = argv[0];+    flags1 = argv[1];+    re1 = js_get_regexp(ctx, pattern1, FALSE);+    if (re1) {+        if (!JS_IsUndefined(flags1))+            return JS_ThrowTypeError(ctx, "flags must be undefined");+        pattern = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->pattern));+        bc = JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re1->bytecode));+    } else {+        bc = JS_UNDEFINED;+        if (JS_IsUndefined(pattern1))+            pattern = JS_AtomToString(ctx, JS_ATOM_empty_string);+        else+            pattern = JS_ToString(ctx, pattern1);+        if (JS_IsException(pattern))+            goto fail;+        bc = js_compile_regexp(ctx, pattern, flags1);+        if (JS_IsException(bc))+            goto fail;+    }+    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));+    JS_FreeValue(ctx, JS_MKPTR(JS_TAG_STRING, re->bytecode));+    re->pattern = JS_VALUE_GET_STRING(pattern);+    re->bytecode = JS_VALUE_GET_STRING(bc);+    if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,+                       JS_NewInt32(ctx, 0)) < 0)+        return JS_EXCEPTION;+    return JS_DupValue(ctx, this_val);+ fail:+    JS_FreeValue(ctx, pattern);+    JS_FreeValue(ctx, bc);+    return JS_EXCEPTION;+}++#if 0+static JSValue js_regexp_get___source(JSContext *ctx, JSValueConst this_val)+{+    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);+    if (!re)+        return JS_EXCEPTION;+    return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, re->pattern));+}++static JSValue js_regexp_get___flags(JSContext *ctx, JSValueConst this_val)+{+    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);+    int flags;++    if (!re)+        return JS_EXCEPTION;+    flags = lre_get_flags(re->bytecode->u.str8);+    return JS_NewInt32(ctx, flags);+}+#endif++static JSValue js_regexp_get_source(JSContext *ctx, JSValueConst this_val)+{+    JSRegExp *re;+    JSString *p;+    StringBuffer b_s, *b = &b_s;+    int i, n, c, c2, bra;++    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);++    if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))+        goto empty_regex;++    re = js_get_regexp(ctx, this_val, TRUE);+    if (!re)+        return JS_EXCEPTION;++    p = re->pattern;++    if (p->len == 0) {+    empty_regex:+        return JS_NewString(ctx, "(?:)");+    }    +    string_buffer_init2(ctx, b, p->len, p->is_wide_char);++    /* Escape '/' and newline sequences as needed */+    bra = 0;+    for (i = 0, n = p->len; i < n;) {+        c2 = -1;+        switch (c = string_get(p, i++)) {+        case '\\':+            if (i < n)+                c2 = string_get(p, i++);+            break;+        case ']':+            bra = 0;+            break;+        case '[':+            if (!bra) {+                if (i < n && string_get(p, i) == ']')+                    c2 = string_get(p, i++);+                bra = 1;+            }+            break;+        case '\n':+            c = '\\';+            c2 = 'n';+            break;+        case '\r':+            c = '\\';+            c2 = 'r';+            break;+        case '/':+            if (!bra) {+                c = '\\';+                c2 = '/';+            }+            break;+        }+        string_buffer_putc16(b, c);+        if (c2 >= 0)+            string_buffer_putc16(b, c2);+    }+    return string_buffer_end(b);+}++static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mask)+{+    JSRegExp *re;+    int flags;++    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);++    re = js_get_regexp(ctx, this_val, FALSE);+    if (!re) {+        if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))+            return JS_UNDEFINED;+        else+            return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);+    }+    +    flags = lre_get_flags(re->bytecode->u.str8);+    return JS_NewBool(ctx, (flags & mask) != 0);+}++static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)+{+    char str[8], *p = str;+    int res;++    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);++    res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 'g';+    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "ignoreCase"));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 'i';+    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "multiline"));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 'm';+    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "dotAll"));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 's';+    res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_unicode));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 'u';+    res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "sticky"));+    if (res < 0)+        goto exception;+    if (res)+        *p++ = 'y';+    return JS_NewStringLen(ctx, str, p - str);++exception:+    return JS_EXCEPTION;+}++static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValue pattern, flags;+    StringBuffer b_s, *b = &b_s;++    if (!JS_IsObject(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    string_buffer_init(ctx, b, 0);+    string_buffer_putc8(b, '/');+    pattern = JS_GetProperty(ctx, this_val, JS_ATOM_source);+    if (string_buffer_concat_value_free(b, pattern))+        goto fail;+    string_buffer_putc8(b, '/');+    flags = JS_GetProperty(ctx, this_val, JS_ATOM_flags);+    if (string_buffer_concat_value_free(b, flags))+        goto fail;+    return string_buffer_end(b);++fail:+    string_buffer_free(b);+    return JS_EXCEPTION;+}++BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)+{+    JSContext *ctx = opaque;+    return js_check_stack_overflow(ctx->rt, alloca_size);+}++void *lre_realloc(void *opaque, void *ptr, size_t size)+{+    JSContext *ctx = opaque;+    /* No JS exception is raised here */+    return js_realloc_rt(ctx->rt, ptr, size);+}++static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);+    JSString *str;+    JSValue str_val, obj, val, groups = JS_UNDEFINED;+    uint8_t *re_bytecode;+    int ret;+    uint8_t **capture, *str_buf;+    int capture_count, shift, i, re_flags;+    int64_t last_index;+    const char *group_name_ptr;++    if (!re)+        return JS_EXCEPTION;+    str_val = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str_val))+        return str_val;+    val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);+    if (JS_IsException(val) ||+        JS_ToLengthFree(ctx, &last_index, val)) {+        JS_FreeValue(ctx, str_val);+        return JS_EXCEPTION;+    }+    re_bytecode = re->bytecode->u.str8;+    re_flags = lre_get_flags(re_bytecode);+    if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {+        last_index = 0;+    }+    str = JS_VALUE_GET_STRING(str_val);+    capture_count = lre_get_capture_count(re_bytecode);+    capture = NULL;+    if (capture_count > 0) {+        capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);+        if (!capture) {+            JS_FreeValue(ctx, str_val);+            return JS_EXCEPTION;+        }+    }+    shift = str->is_wide_char;+    str_buf = str->u.str8;+    if (last_index > str->len) {+        ret = 2;+    } else {+        ret = lre_exec(capture, re_bytecode,+                       str_buf, last_index, str->len,+                       shift, ctx);+    }+    obj = JS_NULL;+    if (ret != 1) {+        if (ret >= 0) {+            if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {+                if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,+                                   JS_NewInt32(ctx, 0)) < 0)+                    goto fail;+            }+        } else {+            JS_ThrowInternalError(ctx, "out of memory in regexp execution");+            goto fail;+        }+        JS_FreeValue(ctx, str_val);+    } else {+        int prop_flags;+        if (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) {+            if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,+                               JS_NewInt32(ctx, (capture[1] - str_buf) >> shift)) < 0)+                goto fail;+        }+        obj = JS_NewArray(ctx);+        if (JS_IsException(obj))+            goto fail;+        prop_flags = JS_PROP_C_W_E | JS_PROP_THROW;+        group_name_ptr = lre_get_groupnames(re_bytecode);+        if (group_name_ptr) {+            groups = JS_NewObjectProto(ctx, JS_NULL);+            if (JS_IsException(groups))+                goto fail;+        }++        for(i = 0; i < capture_count; i++) {+            int start, end;+            JSValue val;+            if (capture[2 * i] == NULL ||+                capture[2 * i + 1] == NULL) {+                val = JS_UNDEFINED;+            } else {+                start = (capture[2 * i] - str_buf) >> shift;+                end = (capture[2 * i + 1] - str_buf) >> shift;+                val = js_sub_string(ctx, str, start, end);+                if (JS_IsException(val))+                    goto fail;+            }+            if (group_name_ptr && i > 0) {+                if (*group_name_ptr) {+                    if (JS_DefinePropertyValueStr(ctx, groups, group_name_ptr,+                                                  JS_DupValue(ctx, val),+                                                  prop_flags) < 0) {+                        JS_FreeValue(ctx, val);+                        goto fail;+                    }+                }+                group_name_ptr += strlen(group_name_ptr) + 1;+            }+            if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0)+                goto fail;+        }+        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_groups,+                                   groups, prop_flags) < 0)+            goto fail;+        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_index,+                                   JS_NewInt32(ctx, (capture[0] - str_buf) >> shift), prop_flags) < 0)+            goto fail;+        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_input, str_val, prop_flags) < 0)+            goto fail1;+    }+    js_free(ctx, capture);+    return obj;+fail:+    JS_FreeValue(ctx, groups);+    JS_FreeValue(ctx, str_val);+fail1:+    JS_FreeValue(ctx, obj);+    js_free(ctx, capture);+    return JS_EXCEPTION;+}++/* delete portions of a string that match a given regex */+static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg)+{+    JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);+    JSString *str;+    JSValue str_val, val;+    uint8_t *re_bytecode;+    int ret;+    uint8_t **capture, *str_buf;+    int capture_count, shift, re_flags;+    int next_src_pos, start, end;+    int64_t last_index;+    StringBuffer b_s, *b = &b_s;++    if (!re)+        return JS_EXCEPTION;++    string_buffer_init(ctx, b, 0);++    capture = NULL;+    str_val = JS_ToString(ctx, arg);+    if (JS_IsException(str_val))+        goto fail;+    str = JS_VALUE_GET_STRING(str_val);+    re_bytecode = re->bytecode->u.str8;+    re_flags = lre_get_flags(re_bytecode);+    if ((re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY)) == 0) {+        last_index = 0;+    } else {+        val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex);+        if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val))+            goto fail;+    }+    capture_count = lre_get_capture_count(re_bytecode);+    if (capture_count > 0) {+        capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2);+        if (!capture)+            goto fail;+    }+    shift = str->is_wide_char;+    str_buf = str->u.str8;+    next_src_pos = 0;+    for (;;) {+        if (last_index > str->len)+            break;++        ret = lre_exec(capture, re_bytecode,+                       str_buf, last_index, str->len, shift, ctx);+        if (ret != 1) {+            if (ret >= 0) {+                if (ret == 2 || (re_flags & (LRE_FLAG_GLOBAL | LRE_FLAG_STICKY))) {+                    if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,+                                       JS_NewInt32(ctx, 0)) < 0)+                        goto fail;+                }+            } else {+                JS_ThrowInternalError(ctx, "out of memory in regexp execution");+                goto fail;+            }+            break;+        }+        start = (capture[0] - str_buf) >> shift;+        end = (capture[1] - str_buf) >> shift;+        last_index = end;+        if (next_src_pos < start) {+            if (string_buffer_concat(b, str, next_src_pos, start))+                goto fail;+        }+        next_src_pos = end;+        if (!(re_flags & LRE_FLAG_GLOBAL)) {+            if (JS_SetProperty(ctx, this_val, JS_ATOM_lastIndex,+                               JS_NewInt32(ctx, end)) < 0)+                goto fail;+            break;+        }+        if (end == start) {+            if (!(re_flags & LRE_FLAG_UTF16) || (unsigned)end >= str->len || !str->is_wide_char) {+                end++;+            } else {+                string_getc(str, &end);+            }+        }+        last_index = end;+    }+    if (string_buffer_concat(b, str, next_src_pos, str->len))+        goto fail;+    JS_FreeValue(ctx, str_val);+    js_free(ctx, capture);+    return string_buffer_end(b);+fail:+    JS_FreeValue(ctx, str_val);+    js_free(ctx, capture);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue JS_RegExpExec(JSContext *ctx, JSValueConst r, JSValueConst s)+{+    JSValue method, ret;++    method = JS_GetProperty(ctx, r, JS_ATOM_exec);+    if (JS_IsException(method))+        return method;+    if (JS_IsFunction(ctx, method)) {+        ret = JS_CallFree(ctx, method, r, 1, &s);+        if (JS_IsException(ret))+            return ret;+        if (!JS_IsObject(ret) && !JS_IsNull(ret)) {+            JS_FreeValue(ctx, ret);+            return JS_ThrowTypeError(ctx, "RegExp exec method must return an object or null");+        }+        return ret;+    }+    JS_FreeValue(ctx, method);+    return js_regexp_exec(ctx, r, 1, &s);+}++#if 0+static JSValue js_regexp___RegExpExec(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    return JS_RegExpExec(ctx, argv[0], argv[1]);+}+static JSValue js_regexp___RegExpDelete(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    return JS_RegExpDelete(ctx, argv[0], argv[1]);+}+#endif++static JSValue js_regexp_test(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSValue val;+    BOOL ret;++    val = JS_RegExpExec(ctx, this_val, argv[0]);+    if (JS_IsException(val))+        return JS_EXCEPTION;+    ret = !JS_IsNull(val);+    JS_FreeValue(ctx, val);+    return JS_NewBool(ctx, ret);+}++static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    // [Symbol.match](str)+    JSValueConst rx = this_val;+    JSValue A, S, result, matchStr;+    int global, n, fullUnicode, isEmpty;+    JSString *p;++    if (!JS_IsObject(rx))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    A = JS_UNDEFINED;+    result = JS_UNDEFINED;+    matchStr = JS_UNDEFINED;+    S = JS_ToString(ctx, argv[0]);+    if (JS_IsException(S))+        goto exception;++    global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));+    if (global < 0)+        goto exception;++    if (!global) {+        A = JS_RegExpExec(ctx, rx, S);+    } else {+        fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));+        if (fullUnicode < 0)+            goto exception;++        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)+            goto exception;+        A = JS_NewArray(ctx);+        if (JS_IsException(A))+            goto exception;+        n = 0;+        for(;;) {+            JS_FreeValue(ctx, result);+            result = JS_RegExpExec(ctx, rx, S);+            if (JS_IsException(result))+                goto exception;+            if (JS_IsNull(result))+                break;+            matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));+            if (JS_IsException(matchStr))+                goto exception;+            isEmpty = JS_IsEmptyString(matchStr);+            if (JS_SetPropertyInt64(ctx, A, n++, matchStr) < 0)+                goto exception;+            if (isEmpty) {+                int64_t thisIndex, nextIndex;+                if (JS_ToLengthFree(ctx, &thisIndex,+                                    JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)+                    goto exception;+                p = JS_VALUE_GET_STRING(S);+                nextIndex = string_advance_index(p, thisIndex, fullUnicode);+                if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)+                    goto exception;+            }+        }+        if (n == 0) {+            JS_FreeValue(ctx, A);+            A = JS_NULL;+        }+    }+    JS_FreeValue(ctx, result);+    JS_FreeValue(ctx, S);+    return A;++exception:+    JS_FreeValue(ctx, A);+    JS_FreeValue(ctx, result);+    JS_FreeValue(ctx, S);+    return JS_EXCEPTION;+}++typedef struct JSRegExpStringIteratorData {+    JSValue iterating_regexp;+    JSValue iterated_string;+    BOOL global;+    BOOL unicode;+    BOOL done;+} JSRegExpStringIteratorData;++static void js_regexp_string_iterator_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data;+    if (it) {+        JS_FreeValueRT(rt, it->iterating_regexp);+        JS_FreeValueRT(rt, it->iterated_string);+        js_free_rt(rt, it);+    }+}++static void js_regexp_string_iterator_mark(JSRuntime *rt, JSValueConst val,+                                           JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSRegExpStringIteratorData *it = p->u.regexp_string_iterator_data;+    if (it) {+        JS_MarkValue(rt, it->iterating_regexp, mark_func);+        JS_MarkValue(rt, it->iterated_string, mark_func);+    }+}++static JSValue js_regexp_string_iterator_next(JSContext *ctx,+                                              JSValueConst this_val,+                                              int argc, JSValueConst *argv,+                                              BOOL *pdone, int magic)+{+    JSRegExpStringIteratorData *it;+    JSValueConst R, S;+    JSValue matchStr = JS_UNDEFINED, match = JS_UNDEFINED;+    JSString *sp;++    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_REGEXP_STRING_ITERATOR);+    if (!it)+        goto exception;+    if (it->done) {+        *pdone = TRUE;+        return JS_UNDEFINED;+    }+    R = it->iterating_regexp;+    S = it->iterated_string;+    match = JS_RegExpExec(ctx, R, S);+    if (JS_IsException(match))+        goto exception;+    if (JS_IsNull(match)) {+        it->done = TRUE;+        *pdone = TRUE;+        return JS_UNDEFINED;+    } else if (it->global) {+        matchStr = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, match, 0));+        if (JS_IsException(matchStr))+            goto exception;+        if (JS_IsEmptyString(matchStr)) {+            int64_t thisIndex, nextIndex;+            if (JS_ToLengthFree(ctx, &thisIndex,+                                JS_GetProperty(ctx, R, JS_ATOM_lastIndex)) < 0)+                goto exception;+            sp = JS_VALUE_GET_STRING(S);+            nextIndex = string_advance_index(sp, thisIndex, it->unicode);+            if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex,+                               JS_NewInt64(ctx, nextIndex)) < 0)+                goto exception;+        }+        JS_FreeValue(ctx, matchStr);+    } else {+        it->done = TRUE;+    }+    *pdone = FALSE;+    return match;+ exception:+    JS_FreeValue(ctx, match);+    JS_FreeValue(ctx, matchStr);+    *pdone = FALSE;+    return JS_EXCEPTION;+}++static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    // [Symbol.matchAll](str)+    JSValueConst R = this_val;+    JSValue S, C, flags, matcher, iter;+    JSValueConst args[2];+    JSString *strp;+    int64_t lastIndex;+    JSRegExpStringIteratorData *it;+    +    if (!JS_IsObject(R))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    C = JS_UNDEFINED;+    flags = JS_UNDEFINED;+    matcher = JS_UNDEFINED;+    iter = JS_UNDEFINED;+    +    S = JS_ToString(ctx, argv[0]);+    if (JS_IsException(S))+        goto exception;+    C = JS_SpeciesConstructor(ctx, R, ctx->regexp_ctor);+    if (JS_IsException(C))+        goto exception;+    flags = JS_ToStringFree(ctx, JS_GetProperty(ctx, R, JS_ATOM_flags));+    if (JS_IsException(flags))+        goto exception;+    args[0] = R;+    args[1] = flags;+    matcher = JS_CallConstructor(ctx, C, 2, args);+    if (JS_IsException(matcher))+        goto exception;+    if (JS_ToLengthFree(ctx, &lastIndex,+                        JS_GetProperty(ctx, R, JS_ATOM_lastIndex)))+        goto exception;+    if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex,+                       JS_NewInt64(ctx, lastIndex)) < 0)+        goto exception;+    +    iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR);+    if (JS_IsException(iter))+        goto exception;+    it = js_malloc(ctx, sizeof(*it));+    if (!it)+        goto exception;+    it->iterating_regexp = matcher;+    it->iterated_string = S;+    strp = JS_VALUE_GET_STRING(flags);+    it->global = string_indexof_char(strp, 'g', 0) >= 0;+    it->unicode = string_indexof_char(strp, 'u', 0) >= 0;+    it->done = FALSE;+    JS_SetOpaque(iter, it);++    JS_FreeValue(ctx, C);+    JS_FreeValue(ctx, flags);+    return iter;+ exception:+    JS_FreeValue(ctx, S);+    JS_FreeValue(ctx, C);+    JS_FreeValue(ctx, flags);+    JS_FreeValue(ctx, matcher);+    JS_FreeValue(ctx, iter);+    return JS_EXCEPTION;+}++typedef struct ValueBuffer {+    JSContext *ctx;+    JSValue *arr;+    JSValue def[4];+    int len;+    int size;+    int error_status;+} ValueBuffer;++static int value_buffer_init(JSContext *ctx, ValueBuffer *b)+{+    b->ctx = ctx;+    b->len = 0;+    b->size = 4;+    b->error_status = 0;+    b->arr = b->def;+    return 0;+}++static void value_buffer_free(ValueBuffer *b)+{+    while (b->len > 0)+        JS_FreeValue(b->ctx, b->arr[--b->len]);+    if (b->arr != b->def)+        js_free(b->ctx, b->arr);+    b->arr = b->def;+    b->size = 4;+}++static int value_buffer_append(ValueBuffer *b, JSValue val)+{+    if (b->error_status)+        return -1;++    if (b->len >= b->size) {+        int new_size = (b->len + (b->len >> 1) + 31) & ~16;+        size_t slack;+        JSValue *new_arr;++        if (b->arr == b->def) {+            new_arr = js_realloc2(b->ctx, NULL, sizeof(*b->arr) * new_size, &slack);+            if (new_arr)+                memcpy(new_arr, b->def, sizeof b->def);+        } else {+            new_arr = js_realloc2(b->ctx, b->arr, sizeof(*b->arr) * new_size, &slack);+        }+        if (!new_arr) {+            value_buffer_free(b);+            JS_FreeValue(b->ctx, val);+            b->error_status = -1;+            return -1;+        }+        new_size += slack / sizeof(*new_arr);+        b->arr = new_arr;+        b->size = new_size;+    }+    b->arr[b->len++] = val;+    return 0;+}++static int js_is_standard_regexp(JSContext *ctx, JSValueConst rx)+{+    JSValue val;+    int res;++    val = JS_GetProperty(ctx, rx, JS_ATOM_constructor);+    if (JS_IsException(val))+        return -1;+    // rx.constructor === RegExp+    res = js_same_value(ctx, val, ctx->regexp_ctor);+    JS_FreeValue(ctx, val);+    if (res) {+        val = JS_GetProperty(ctx, rx, JS_ATOM_exec);+        if (JS_IsException(val))+            return -1;+        // rx.exec === RE_exec+        res = JS_IsCFunction(ctx, val, js_regexp_exec, 0);+        JS_FreeValue(ctx, val);+    }+    return res;+}++static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    // [Symbol.replace](str, rep)+    JSValueConst rx = this_val, rep = argv[1];+    JSValueConst args[6];+    JSValue str, rep_val, matched, tab, rep_str, namedCaptures, res;+    JSString *sp, *rp;+    StringBuffer b_s, *b = &b_s;+    ValueBuffer v_b, *results = &v_b;+    int nextSourcePosition, n, j, functionalReplace, is_global, fullUnicode;+    uint32_t nCaptures;+    int64_t position;++    if (!JS_IsObject(rx))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    string_buffer_init(ctx, b, 0);+    value_buffer_init(ctx, results);++    rep_val = JS_UNDEFINED;+    matched = JS_UNDEFINED;+    tab = JS_UNDEFINED;+    rep_str = JS_UNDEFINED;+    namedCaptures = JS_UNDEFINED;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        goto exception;+        +    sp = JS_VALUE_GET_STRING(str);+    rp = NULL;+    functionalReplace = JS_IsFunction(ctx, rep);+    if (!functionalReplace) {+        rep_val = JS_ToString(ctx, rep);+        if (JS_IsException(rep_val))+            goto exception;+        rp = JS_VALUE_GET_STRING(rep_val);+    }+    fullUnicode = 0;+    is_global = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_global));+    if (is_global < 0)+        goto exception;+    if (is_global) {+        fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));+        if (fullUnicode < 0)+            goto exception;+        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)+            goto exception;+    }++    if (rp && rp->len == 0 && is_global && js_is_standard_regexp(ctx, rx)) {+        /* use faster version for simple cases */+        res = JS_RegExpDelete(ctx, rx, str);+        goto done;+    }+    for(;;) {+        JSValue result;+        result = JS_RegExpExec(ctx, rx, str);+        if (JS_IsException(result))+            goto exception;+        if (JS_IsNull(result))+            break;+        if (value_buffer_append(results, result) < 0)+            goto exception;+        if (!is_global)+            break;+        JS_FreeValue(ctx, matched);+        matched = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));+        if (JS_IsException(matched))+            goto exception;+        if (JS_IsEmptyString(matched)) {+            /* always advance of at least one char */+            int64_t thisIndex, nextIndex;+            if (JS_ToLengthFree(ctx, &thisIndex, JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)+                goto exception;+            nextIndex = string_advance_index(sp, thisIndex, fullUnicode);+            if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)+                goto exception;+        }+    }+    nextSourcePosition = 0;+    for(j = 0; j < results->len; j++) {+        JSValueConst result;+        result = results->arr[j];+        if (js_get_length32(ctx, &nCaptures, result) < 0)+            goto exception;+        JS_FreeValue(ctx, matched);+        matched = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, result, 0));+        if (JS_IsException(matched))+            goto exception;+        if (JS_ToLengthFree(ctx, &position, JS_GetProperty(ctx, result, JS_ATOM_index)))+            goto exception;+        if (position > sp->len)+            position = sp->len;+        else if (position < 0)+            position = 0;+        /* ignore substition if going backward (can happen+           with custom regexp object) */+        JS_FreeValue(ctx, tab);+        tab = JS_NewArray(ctx);+        if (JS_IsException(tab))+            goto exception;+        if (JS_DefinePropertyValueInt64(ctx, tab, 0, JS_DupValue(ctx, matched),+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)+            goto exception;+        for(n = 1; n < nCaptures; n++) {+            JSValue capN;+            capN = JS_GetPropertyInt64(ctx, result, n);+            if (JS_IsException(capN))+                goto exception;+            if (!JS_IsUndefined(capN)) {+                capN = JS_ToStringFree(ctx, capN);+                if (JS_IsException(capN))+                    goto exception;+            }+            if (JS_DefinePropertyValueInt64(ctx, tab, n, capN,+                                            JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+        }+        JS_FreeValue(ctx, namedCaptures);+        namedCaptures = JS_GetProperty(ctx, result, JS_ATOM_groups);+        if (JS_IsException(namedCaptures))+            goto exception;+        if (functionalReplace) {+            if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_NewInt32(ctx, position), JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+            if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, str), JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                goto exception;+            if (!JS_IsUndefined(namedCaptures)) {+                if (JS_DefinePropertyValueInt64(ctx, tab, n++, JS_DupValue(ctx, namedCaptures), JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                    goto exception;+            }+            args[0] = JS_UNDEFINED;+            args[1] = tab;+            JS_FreeValue(ctx, rep_str);+            rep_str = JS_ToStringFree(ctx, js_function_apply(ctx, rep, 2, args, 0));+        } else {+            JSValue namedCaptures1;+            if (!JS_IsUndefined(namedCaptures)) {+                namedCaptures1 = JS_ToObject(ctx, namedCaptures);+                if (JS_IsException(namedCaptures1))+                    goto exception;+            } else {+                namedCaptures1 = JS_UNDEFINED;+            }+            args[0] = matched;+            args[1] = str;+            args[2] = JS_NewInt32(ctx, position);+            args[3] = tab;+            args[4] = namedCaptures1;+            args[5] = rep_val;+            JS_FreeValue(ctx, rep_str);+            rep_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args);+            JS_FreeValue(ctx, namedCaptures1);+        }+        if (JS_IsException(rep_str))+            goto exception;+        if (position >= nextSourcePosition) {+            string_buffer_concat(b, sp, nextSourcePosition, position);+            string_buffer_concat_value(b, rep_str);+            nextSourcePosition = position + JS_VALUE_GET_STRING(matched)->len;+        }+    }+    string_buffer_concat(b, sp, nextSourcePosition, sp->len);+    res = string_buffer_end(b);+    goto done1;++exception:+    res = JS_EXCEPTION;+done:+    string_buffer_free(b);+done1:+    value_buffer_free(results);+    JS_FreeValue(ctx, rep_val);+    JS_FreeValue(ctx, matched);+    JS_FreeValue(ctx, tab);+    JS_FreeValue(ctx, rep_str);+    JS_FreeValue(ctx, namedCaptures);+    JS_FreeValue(ctx, str);+    return res;+}++static JSValue js_regexp_Symbol_search(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValueConst rx = this_val;+    JSValue str, previousLastIndex, currentLastIndex, result, index;++    if (!JS_IsObject(rx))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    result = JS_UNDEFINED;+    currentLastIndex = JS_UNDEFINED;+    previousLastIndex = JS_UNDEFINED;+    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        goto exception;++    previousLastIndex = JS_GetProperty(ctx, rx, JS_ATOM_lastIndex);+    if (JS_IsException(previousLastIndex))+        goto exception;++    if (!js_same_value(ctx, previousLastIndex, JS_NewInt32(ctx, 0))) {+        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0) {+            goto exception;+        }+    }+    result = JS_RegExpExec(ctx, rx, str);+    if (JS_IsException(result))+        goto exception;+    currentLastIndex = JS_GetProperty(ctx, rx, JS_ATOM_lastIndex);+    if (JS_IsException(currentLastIndex))+        goto exception;+    if (js_same_value(ctx, currentLastIndex, previousLastIndex)) {+        JS_FreeValue(ctx, previousLastIndex);+    } else {+        if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, previousLastIndex) < 0) {+            previousLastIndex = JS_UNDEFINED;+            goto exception;+        }+    }+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, currentLastIndex);++    if (JS_IsNull(result)) {+        return JS_NewInt32(ctx, -1);+    } else {+        index = JS_GetProperty(ctx, result, JS_ATOM_index);+        JS_FreeValue(ctx, result);+        return index;+    }++exception:+    JS_FreeValue(ctx, result);+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, currentLastIndex);+    JS_FreeValue(ctx, previousLastIndex);+    return JS_EXCEPTION;+}++static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    // [Symbol.split](str, limit)+    JSValueConst rx = this_val;+    JSValueConst args[2];+    JSValue str, ctor, splitter, A, flags, z, sub;+    JSString *strp;+    uint32_t lim, size, p, q;+    int unicodeMatching;+    int64_t lengthA, e, numberOfCaptures, i;++    if (!JS_IsObject(rx))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    ctor = JS_UNDEFINED;+    splitter = JS_UNDEFINED;+    A = JS_UNDEFINED;+    flags = JS_UNDEFINED;+    z = JS_UNDEFINED;+    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        goto exception;+    ctor = JS_SpeciesConstructor(ctx, rx, ctx->regexp_ctor);+    if (JS_IsException(ctor))+        goto exception;+    flags = JS_ToStringFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_flags));+    if (JS_IsException(flags))+        goto exception;+    strp = JS_VALUE_GET_STRING(flags);+    unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0;+    if (string_indexof_char(strp, 'y', 0) < 0) {+        flags = JS_ConcatString3(ctx, "", flags, "y");+        if (JS_IsException(flags))+            goto exception;+    }+    args[0] = rx;+    args[1] = flags;+    splitter = JS_CallConstructor(ctx, ctor, 2, args);+    if (JS_IsException(splitter))+        goto exception;+    A = JS_NewArray(ctx);+    if (JS_IsException(A))+        goto exception;+    lengthA = 0;+    if (JS_IsUndefined(argv[1])) {+        lim = 0xffffffff;+    } else {+        if (JS_ToUint32(ctx, &lim, argv[1]) < 0)+            goto exception;+        if (lim == 0)+            goto done;+    }+    strp = JS_VALUE_GET_STRING(str);+    p = q = 0;+    size = strp->len;+    if (size == 0) {+        z = JS_RegExpExec(ctx, splitter, str);+        if (JS_IsException(z))+            goto exception;+        if (JS_IsNull(z))+            goto add_tail;+        goto done;+    }+    while (q < size) {+        if (JS_SetProperty(ctx, splitter, JS_ATOM_lastIndex, JS_NewInt32(ctx, q)) < 0)+            goto exception;+        JS_FreeValue(ctx, z);    +        z = JS_RegExpExec(ctx, splitter, str);+        if (JS_IsException(z))+            goto exception;+        if (JS_IsNull(z)) {+            q = string_advance_index(strp, q, unicodeMatching);+        } else {+            if (JS_ToLengthFree(ctx, &e, JS_GetProperty(ctx, splitter, JS_ATOM_lastIndex)))+                goto exception;+            if (e > size)+                e = size;+            if (e == p) {+                q = string_advance_index(strp, q, unicodeMatching);+            } else {+                sub = js_sub_string(ctx, strp, p, q);+                if (JS_IsException(sub))+                    goto exception;+                if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub,+                                                JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                    goto exception;+                if (lengthA == lim)+                    goto done;+                p = e;+                if (js_get_length64(ctx, &numberOfCaptures, z))+                    goto exception;+                for(i = 1; i < numberOfCaptures; i++) {+                    sub = JS_ToStringFree(ctx, JS_GetPropertyInt64(ctx, z, i));+                    if (JS_IsException(sub))+                        goto exception;+                    if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0)+                        goto exception;+                    if (lengthA == lim)+                        goto done;+                }+                q = p;+            }+        }+    }+add_tail:+    if (p > size)+        p = size;+    sub = js_sub_string(ctx, strp, p, size);+    if (JS_IsException(sub))+        goto exception;+    if (JS_DefinePropertyValueInt64(ctx, A, lengthA++, sub, JS_PROP_C_W_E | JS_PROP_THROW) < 0)+        goto exception;+    goto done;+exception:+    JS_FreeValue(ctx, A);+    A = JS_EXCEPTION;+done:+    JS_FreeValue(ctx, str);+    JS_FreeValue(ctx, ctor);+    JS_FreeValue(ctx, splitter);+    JS_FreeValue(ctx, flags);+    JS_FreeValue(ctx, z);    +    return A;+}++static const JSCFunctionListEntry js_regexp_funcs[] = {+    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),+    //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ),+    //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ),+};++static const JSCFunctionListEntry js_regexp_proto_funcs[] = {+    JS_CGETSET_DEF("flags", js_regexp_get_flags, NULL ),+    JS_CGETSET_DEF("source", js_regexp_get_source, NULL ),+    JS_CGETSET_MAGIC_DEF("global", js_regexp_get_flag, NULL, 1 ),+    JS_CGETSET_MAGIC_DEF("ignoreCase", js_regexp_get_flag, NULL, 2 ),+    JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, 4 ),+    JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, 8 ),+    JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, 16 ),+    JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, 32 ),+    JS_CFUNC_DEF("exec", 1, js_regexp_exec ),+    JS_CFUNC_DEF("compile", 2, js_regexp_compile ),+    JS_CFUNC_DEF("test", 1, js_regexp_test ),+    JS_CFUNC_DEF("toString", 0, js_regexp_toString ),+    JS_CFUNC_DEF("[Symbol.replace]", 2, js_regexp_Symbol_replace ),+    JS_CFUNC_DEF("[Symbol.match]", 1, js_regexp_Symbol_match ),+    JS_CFUNC_DEF("[Symbol.matchAll]", 1, js_regexp_Symbol_matchAll ),+    JS_CFUNC_DEF("[Symbol.search]", 1, js_regexp_Symbol_search ),+    JS_CFUNC_DEF("[Symbol.split]", 2, js_regexp_Symbol_split ),+    //JS_CGETSET_DEF("__source", js_regexp_get___source, NULL ),+    //JS_CGETSET_DEF("__flags", js_regexp_get___flags, NULL ),+};++static const JSCFunctionListEntry js_regexp_string_iterator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 0, js_regexp_string_iterator_next, 0 ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "RegExp String Iterator", JS_PROP_CONFIGURABLE ),+};++void JS_AddIntrinsicRegExpCompiler(JSContext *ctx)+{+    ctx->compile_regexp = js_compile_regexp;+}++void JS_AddIntrinsicRegExp(JSContext *ctx)+{+    JSValueConst obj;++    JS_AddIntrinsicRegExpCompiler(ctx);++    ctx->class_proto[JS_CLASS_REGEXP] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP], js_regexp_proto_funcs,+                               countof(js_regexp_proto_funcs));+    obj = JS_NewGlobalCConstructor(ctx, "RegExp", js_regexp_constructor, 2,+                                   ctx->class_proto[JS_CLASS_REGEXP]);+    ctx->regexp_ctor = JS_DupValue(ctx, obj);+    JS_SetPropertyFunctionList(ctx, obj, js_regexp_funcs, countof(js_regexp_funcs));++    ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR] =+        JS_NewObjectProto(ctx, ctx->iterator_proto);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_REGEXP_STRING_ITERATOR],+                               js_regexp_string_iterator_proto_funcs,+                               countof(js_regexp_string_iterator_proto_funcs));+}++/* JSON */++static int json_parse_expect(JSParseState *s, int tok)+{+    if (s->token.val != tok) {+        /* XXX: dump token correctly in all cases */+        return js_parse_error(s, "expecting '%c'", tok);+    }+    return json_next_token(s);+}++static JSValue json_parse_value(JSParseState *s)+{+    JSContext *ctx = s->ctx;+    JSValue val = JS_NULL;+    int ret;++    switch(s->token.val) {+    case '{':+        {+            JSValue prop_val;+            JSAtom prop_name;+            +            if (json_next_token(s))+                goto fail;+            val = JS_NewObject(ctx);+            if (JS_IsException(val))+                goto fail;+            if (s->token.val != '}') {+                for(;;) {+                    if (s->token.val == TOK_STRING) {+                        prop_name = JS_ValueToAtom(ctx, s->token.u.str.str);+                        if (prop_name == JS_ATOM_NULL)+                            goto fail;+                    } else if (s->ext_json && s->token.val == TOK_IDENT) {+                        prop_name = JS_DupAtom(ctx, s->token.u.ident.atom);+                    } else {+                        js_parse_error(s, "expecting property name");+                        goto fail;+                    }+                    if (json_next_token(s))+                        goto fail1;+                    if (json_parse_expect(s, ':'))+                        goto fail1;+                    prop_val = json_parse_value(s);+                    if (JS_IsException(prop_val)) {+                    fail1:+                        JS_FreeAtom(ctx, prop_name);+                        goto fail;+                    }+                    ret = JS_DefinePropertyValue(ctx, val, prop_name,+                                                 prop_val, JS_PROP_C_W_E);+                    JS_FreeAtom(ctx, prop_name);+                    if (ret < 0)+                        goto fail;++                    if (s->token.val != ',')+                        break;+                    if (json_next_token(s))+                        goto fail;+                    if (s->ext_json && s->token.val == '}')+                        break;+                }+            }+            if (json_parse_expect(s, '}'))+                goto fail;+        }+        break;+    case '[':+        {+            JSValue el;+            uint32_t idx;++            if (json_next_token(s))+                goto fail;+            val = JS_NewArray(ctx);+            if (JS_IsException(val))+                goto fail;+            if (s->token.val != ']') {+                idx = 0;+                for(;;) {+                    el = json_parse_value(s);+                    if (JS_IsException(el))+                        goto fail;+                    ret = JS_DefinePropertyValueUint32(ctx, val, idx, el, JS_PROP_C_W_E);+                    if (ret < 0)+                        goto fail;+                    if (s->token.val != ',')+                        break;+                    if (json_next_token(s))+                        goto fail;+                    idx++;+                    if (s->ext_json && s->token.val == ']')+                        break;+                }+            }+            if (json_parse_expect(s, ']'))+                goto fail;+        }+        break;+    case TOK_STRING:+        val = JS_DupValue(ctx, s->token.u.str.str);+        if (json_next_token(s))+            goto fail;+        break;+    case TOK_NUMBER:+        val = s->token.u.num.val;+        if (json_next_token(s))+            goto fail;+        break;+    case TOK_IDENT:+        if (s->token.u.ident.atom == JS_ATOM_false ||+            s->token.u.ident.atom == JS_ATOM_true) {+            val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true));+        } else if (s->token.u.ident.atom == JS_ATOM_null) {+            val = JS_NULL;+        } else {+            goto def_token;+        }+        if (json_next_token(s))+            goto fail;+        break;+    default:+    def_token:+        if (s->token.val == TOK_EOF) {+            js_parse_error(s, "unexpected end of input");+        } else {+            js_parse_error(s, "unexpected token: '%.*s'",+                           (int)(s->buf_ptr - s->token.ptr), s->token.ptr);+        }+        goto fail;+    }+    return val;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len,+                      const char *filename, int flags)+{+    JSParseState s1, *s = &s1;+    JSValue val = JS_UNDEFINED;++    js_parse_init(ctx, s, buf, buf_len, filename);+    s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0);+    if (json_next_token(s))+        goto fail;+    val = json_parse_value(s);+    if (JS_IsException(val))+        goto fail;+    if (s->token.val != TOK_EOF) {+        if (js_parse_error(s, "unexpected data at the end"))+            goto fail;+    }+    return val;+ fail:+    JS_FreeValue(ctx, val);+    free_token(s, &s->token);+    return JS_EXCEPTION;+}++JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,+                     const char *filename)+{+    return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); +}++static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,+                                         JSAtom name, JSValueConst reviver)+{+    JSValue val, new_el, name_val, res;+    JSValueConst args[2];+    int ret, is_array;+    uint32_t i, len = 0;+    JSAtom prop;+    JSPropertyEnum *atoms = NULL;++    if (js_check_stack_overflow(ctx->rt, 0)) {+        return JS_ThrowStackOverflow(ctx);+    }++    val = JS_GetProperty(ctx, holder, name);+    if (JS_IsException(val))+        return val;+    if (JS_IsObject(val)) {+        is_array = JS_IsArray(ctx, val);+        if (is_array < 0)+            goto fail;+        if (is_array) {+            if (js_get_length32(ctx, &len, val))+                goto fail;+        } else {+            ret = JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, JS_VALUE_GET_OBJ(val), JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);+            if (ret < 0)+                goto fail;+        }+        for(i = 0; i < len; i++) {+            if (is_array) {+                prop = JS_NewAtomUInt32(ctx, i);+                if (prop == JS_ATOM_NULL)+                    goto fail;+            } else {+                prop = JS_DupAtom(ctx, atoms[i].atom);+            }+            new_el = internalize_json_property(ctx, val, prop, reviver);+            if (JS_IsException(new_el)) {+                JS_FreeAtom(ctx, prop);+                goto fail;+            }+            if (JS_IsUndefined(new_el)) {+                ret = JS_DeleteProperty(ctx, val, prop, 0);+            } else {+                ret = JS_DefinePropertyValue(ctx, val, prop, new_el, JS_PROP_C_W_E);+            }+            JS_FreeAtom(ctx, prop);+            if (ret < 0)+                goto fail;+        }+    }+    js_free_prop_enum(ctx, atoms, len);+    atoms = NULL;+    name_val = JS_AtomToValue(ctx, name);+    if (JS_IsException(name_val))+        goto fail;+    args[0] = name_val;+    args[1] = val;+    res = JS_Call(ctx, reviver, holder, 2, args);+    JS_FreeValue(ctx, name_val);+    JS_FreeValue(ctx, val);+    return res;+ fail:+    js_free_prop_enum(ctx, atoms, len);+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_json_parse(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    JSValue obj, root;+    JSValueConst reviver;+    const char *str;+    size_t len;++    str = JS_ToCStringLen(ctx, &len, argv[0]);+    if (!str)+        return JS_EXCEPTION;+    obj = JS_ParseJSON(ctx, str, len, "<input>");+    JS_FreeCString(ctx, str);+    if (JS_IsException(obj))+        return obj;+    if (argc > 1 && JS_IsFunction(ctx, argv[1])) {+        reviver = argv[1];+        root = JS_NewObject(ctx);+        if (JS_IsException(root)) {+            JS_FreeValue(ctx, obj);+            return JS_EXCEPTION;+        }+        if (JS_DefinePropertyValue(ctx, root, JS_ATOM_empty_string, obj,+                                   JS_PROP_C_W_E) < 0) {+            JS_FreeValue(ctx, root);+            return JS_EXCEPTION;+        }+        obj = internalize_json_property(ctx, root, JS_ATOM_empty_string,+                                        reviver);+        JS_FreeValue(ctx, root);+    }+    return obj;+}++typedef struct JSONStringifyContext {+    JSValueConst replacer_func;+    JSValue stack;+    JSValue property_list;+    JSValue gap;+    JSValue empty;+    StringBuffer *b;+} JSONStringifyContext;++static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) {+    JSValue r = JS_ToQuotedString(ctx, val);+    JS_FreeValue(ctx, val);+    return r;+}++static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,+                             JSValueConst holder, JSValue val, JSValueConst key)+{+    JSValue v;+    JSValueConst args[2];++    if (JS_IsObject(val)+#ifdef CONFIG_BIGNUM+    ||  JS_IsBigInt(ctx, val)   /* XXX: probably useless */+#endif+        ) {+            JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);+            if (JS_IsException(f))+                goto exception;+            if (JS_IsFunction(ctx, f)) {+                v = JS_CallFree(ctx, f, val, 1, &key);+                JS_FreeValue(ctx, val);+                val = v;+                if (JS_IsException(val))+                    goto exception;+            } else {+                JS_FreeValue(ctx, f);+            }+        }++    if (!JS_IsUndefined(jsc->replacer_func)) {+        args[0] = key;+        args[1] = val;+        v = JS_Call(ctx, jsc->replacer_func, holder, 2, args);+        JS_FreeValue(ctx, val);+        val = v;+        if (JS_IsException(val))+            goto exception;+    }++    switch (JS_VALUE_GET_NORM_TAG(val)) {+    case JS_TAG_OBJECT:+        if (JS_IsFunction(ctx, val))+            break;+    case JS_TAG_STRING:+    case JS_TAG_INT:+    case JS_TAG_FLOAT64:+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+#endif+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+#endif+    case JS_TAG_EXCEPTION:+        return val;+    default:+        break;+    }+    JS_FreeValue(ctx, val);+    return JS_UNDEFINED;++exception:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,+                          JSValueConst holder, JSValue val,+                          JSValueConst indent)+{+    JSValue indent1, sep, sep1, tab, v, prop;+    JSObject *p;+    int64_t i, len;+    int cl, ret;+    BOOL has_content;+    +    indent1 = JS_UNDEFINED;+    sep = JS_UNDEFINED;+    sep1 = JS_UNDEFINED;+    tab = JS_UNDEFINED;+    prop = JS_UNDEFINED;++    switch (JS_VALUE_GET_NORM_TAG(val)) {+    case JS_TAG_OBJECT:+        p = JS_VALUE_GET_OBJ(val);+        cl = p->class_id;+        if (cl == JS_CLASS_STRING) {+            val = JS_ToStringFree(ctx, val);+            if (JS_IsException(val))+                goto exception;+            val = JS_ToQuotedStringFree(ctx, val);+            if (JS_IsException(val))+                goto exception;+            return string_buffer_concat_value_free(jsc->b, val);+        } else if (cl == JS_CLASS_NUMBER) {+            val = JS_ToNumberFree(ctx, val);+            if (JS_IsException(val))+                goto exception;+            return string_buffer_concat_value_free(jsc->b, val);+        } else if (cl == JS_CLASS_BOOLEAN) {+            ret = string_buffer_concat_value(jsc->b, p->u.object_data);+            JS_FreeValue(ctx, val);+            return ret;+        }+#ifdef CONFIG_BIGNUM+        else if (cl == JS_CLASS_BIG_FLOAT) {+            return string_buffer_concat_value_free(jsc->b, val);+        } else if (cl == JS_CLASS_BIG_INT) {+            JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");+            goto exception;+        }+#endif+        v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);+        if (JS_IsException(v))+            goto exception;+        if (JS_ToBoolFree(ctx, v)) {+            JS_ThrowTypeError(ctx, "circular reference");+            goto exception;+        }+        indent1 = JS_ConcatString(ctx, JS_DupValue(ctx, indent), JS_DupValue(ctx, jsc->gap));+        if (JS_IsException(indent1))+            goto exception;+        if (!JS_IsEmptyString(jsc->gap)) {+            sep = JS_ConcatString3(ctx, "\n", JS_DupValue(ctx, indent1), "");+            if (JS_IsException(sep))+                goto exception;+            sep1 = JS_NewString(ctx, " ");+            if (JS_IsException(sep1))+                goto exception;+        } else {+            sep = JS_DupValue(ctx, jsc->empty);+            sep1 = JS_DupValue(ctx, jsc->empty);+        }+        v = js_array_push(ctx, jsc->stack, 1, (JSValueConst *)&val, 0);+        if (check_exception_free(ctx, v))+            goto exception;+        ret = JS_IsArray(ctx, val);+        if (ret < 0)+            goto exception;+        if (ret) {+            if (js_get_length64(ctx, &len, val))+                goto exception;+            string_buffer_putc8(jsc->b, '[');+            for(i = 0; i < len; i++) {+                if (i > 0)+                    string_buffer_putc8(jsc->b, ',');+                string_buffer_concat_value(jsc->b, sep);+                v = JS_GetPropertyInt64(ctx, val, i);+                if (JS_IsException(v))+                    goto exception;+                /* XXX: could do this string conversion only when needed */+                prop = JS_ToStringFree(ctx, JS_NewInt64(ctx, i));+                if (JS_IsException(prop))+                    goto exception;+                v = js_json_check(ctx, jsc, val, v, prop);+                JS_FreeValue(ctx, prop);+                prop = JS_UNDEFINED;+                if (JS_IsException(v))+                    goto exception;+                if (JS_IsUndefined(v))+                    v = JS_NULL;+                if (js_json_to_str(ctx, jsc, val, v, indent1))+                    goto exception;+            }+            if (len > 0 && !JS_IsEmptyString(jsc->gap)) {+                string_buffer_putc8(jsc->b, '\n');+                string_buffer_concat_value(jsc->b, indent);+            }+            string_buffer_putc8(jsc->b, ']');+        } else {+            if (!JS_IsUndefined(jsc->property_list))+                tab = JS_DupValue(ctx, jsc->property_list);+            else+                tab = js_object_keys(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val, JS_ITERATOR_KIND_KEY);+            if (JS_IsException(tab))+                goto exception;+            if (js_get_length64(ctx, &len, tab))+                goto exception;+            string_buffer_putc8(jsc->b, '{');+            has_content = FALSE;+            for(i = 0; i < len; i++) {+                JS_FreeValue(ctx, prop);+                prop = JS_GetPropertyInt64(ctx, tab, i);+                if (JS_IsException(prop))+                    goto exception;+                v = JS_GetPropertyValue(ctx, val, JS_DupValue(ctx, prop));+                if (JS_IsException(v))+                    goto exception;+                v = js_json_check(ctx, jsc, val, v, prop);+                if (JS_IsException(v))+                    goto exception;+                if (!JS_IsUndefined(v)) {+                    if (has_content)+                        string_buffer_putc8(jsc->b, ',');+                    prop = JS_ToQuotedStringFree(ctx, prop);+                    if (JS_IsException(prop)) {+                        JS_FreeValue(ctx, v);+                        goto exception;+                    }+                    string_buffer_concat_value(jsc->b, sep);+                    string_buffer_concat_value(jsc->b, prop);+                    string_buffer_putc8(jsc->b, ':');+                    string_buffer_concat_value(jsc->b, sep1);+                    if (js_json_to_str(ctx, jsc, val, v, indent1))+                        goto exception;+                    has_content = TRUE;+                }+            }+            if (has_content && JS_VALUE_GET_STRING(jsc->gap)->len != 0) {+                string_buffer_putc8(jsc->b, '\n');+                string_buffer_concat_value(jsc->b, indent);+            }+            string_buffer_putc8(jsc->b, '}');+        }+        if (check_exception_free(ctx, js_array_pop(ctx, jsc->stack, 0, NULL, 0)))+            goto exception;+        JS_FreeValue(ctx, val);+        JS_FreeValue(ctx, tab);+        JS_FreeValue(ctx, sep);+        JS_FreeValue(ctx, sep1);+        JS_FreeValue(ctx, indent1);+        JS_FreeValue(ctx, prop);+        return 0;+    case JS_TAG_STRING:+        val = JS_ToQuotedStringFree(ctx, val);+        if (JS_IsException(val))+            goto exception;+        goto concat_value;+    case JS_TAG_FLOAT64:+        if (!isfinite(JS_VALUE_GET_FLOAT64(val))) {+            val = JS_NULL;+        }+        goto concat_value;+    case JS_TAG_INT:+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_FLOAT:+#endif+    case JS_TAG_BOOL:+    case JS_TAG_NULL:+    concat_value:+        return string_buffer_concat_value_free(jsc->b, val);+#ifdef CONFIG_BIGNUM+    case JS_TAG_BIG_INT:+        JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");+        goto exception;+#endif+    default:+        JS_FreeValue(ctx, val);+        return 0;+    }+    +exception:+    JS_FreeValue(ctx, val);+    JS_FreeValue(ctx, tab);+    JS_FreeValue(ctx, sep);+    JS_FreeValue(ctx, sep1);+    JS_FreeValue(ctx, indent1);+    JS_FreeValue(ctx, prop);+    return -1;+}++JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj,+                         JSValueConst replacer, JSValueConst space0)+{+    StringBuffer b_s;+    JSONStringifyContext jsc_s, *jsc = &jsc_s;+    JSValue val, v, space, ret, wrapper;+    int res;+    int64_t i, j, n;++    jsc->replacer_func = JS_UNDEFINED;+    jsc->stack = JS_UNDEFINED;+    jsc->property_list = JS_UNDEFINED;+    jsc->gap = JS_UNDEFINED;+    jsc->b = &b_s;+    jsc->empty = JS_AtomToString(ctx, JS_ATOM_empty_string);+    ret = JS_UNDEFINED;+    wrapper = JS_UNDEFINED;++    string_buffer_init(ctx, jsc->b, 0);+    jsc->stack = JS_NewArray(ctx);+    if (JS_IsException(jsc->stack))+        goto exception;+    if (JS_IsFunction(ctx, replacer)) {+        jsc->replacer_func = replacer;+    } else {+        res = JS_IsArray(ctx, replacer);+        if (res < 0)+            goto exception;+        if (res) {+            /* XXX: enumeration is not fully correct */+            jsc->property_list = JS_NewArray(ctx);+            if (JS_IsException(jsc->property_list))+                goto exception;+            if (js_get_length64(ctx, &n, replacer))+                goto exception;+            for (i = j = 0; i < n; i++) {+                JSValue present;+                v = JS_GetPropertyInt64(ctx, replacer, i);+                if (JS_IsException(v))+                    goto exception;+                if (JS_IsObject(v)) {+                    JSObject *p = JS_VALUE_GET_OBJ(v);+                    if (p->class_id == JS_CLASS_STRING ||+                        p->class_id == JS_CLASS_NUMBER) {+                        v = JS_ToStringFree(ctx, v);+                        if (JS_IsException(v))+                            goto exception;+                    } else {+                        JS_FreeValue(ctx, v);+                        continue;+                    }+                } else if (JS_IsNumber(v)) {+                    v = JS_ToStringFree(ctx, v);+                    if (JS_IsException(v))+                        goto exception;+                } else if (!JS_IsString(v)) {+                    JS_FreeValue(ctx, v);+                    continue;+                }+                present = js_array_includes(ctx, jsc->property_list,+                                            1, (JSValueConst *)&v);+                if (JS_IsException(present)) {+                    JS_FreeValue(ctx, v);+                    goto exception;+                }+                if (!JS_ToBoolFree(ctx, present)) {+                    JS_SetPropertyInt64(ctx, jsc->property_list, j++, v);+                } else {+                    JS_FreeValue(ctx, v);+                }+            }+        }+    }+    space = JS_DupValue(ctx, space0);+    if (JS_IsObject(space)) {+        JSObject *p = JS_VALUE_GET_OBJ(space);+        if (p->class_id == JS_CLASS_NUMBER) {+            space = JS_ToNumberFree(ctx, space);+        } else if (p->class_id == JS_CLASS_STRING) {+            space = JS_ToStringFree(ctx, space);+        }+        if (JS_IsException(space)) {+            JS_FreeValue(ctx, space);+            goto exception;+        }+    }+    if (JS_IsNumber(space)) {+        int n;+        if (JS_ToInt32Clamp(ctx, &n, space, 0, 10, 0))+            goto exception;+        jsc->gap = JS_NewStringLen(ctx, "          ", n);+    } else if (JS_IsString(space)) {+        JSString *p = JS_VALUE_GET_STRING(space);+        jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10));+    } else {+        jsc->gap = JS_DupValue(ctx, jsc->empty);+    }+    JS_FreeValue(ctx, space);+    if (JS_IsException(jsc->gap))+        goto exception;+    wrapper = JS_NewObject(ctx);+    if (JS_IsException(wrapper))+        goto exception;+    if (JS_DefinePropertyValue(ctx, wrapper, JS_ATOM_empty_string,+                               JS_DupValue(ctx, obj), JS_PROP_C_W_E) < 0)+        goto exception;+    val = JS_DupValue(ctx, obj);+                           +    val = js_json_check(ctx, jsc, wrapper, val, jsc->empty);+    if (JS_IsException(val))+        goto exception;+    if (JS_IsUndefined(val)) {+        ret = JS_UNDEFINED;+        goto done1;+    }+    if (js_json_to_str(ctx, jsc, wrapper, val, jsc->empty))+        goto exception;++    ret = string_buffer_end(jsc->b);+    goto done;++exception:+    ret = JS_EXCEPTION;+done1:+    string_buffer_free(jsc->b);+done:+    JS_FreeValue(ctx, wrapper);+    JS_FreeValue(ctx, jsc->empty);+    JS_FreeValue(ctx, jsc->gap);+    JS_FreeValue(ctx, jsc->property_list);+    JS_FreeValue(ctx, jsc->stack);+    return ret;+}++static JSValue js_json_stringify(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    // stringify(val, replacer, space)+    return JS_JSONStringify(ctx, argv[0], argv[1], argv[2]);+}++static const JSCFunctionListEntry js_json_funcs[] = {+    JS_CFUNC_DEF("parse", 2, js_json_parse ),+    JS_CFUNC_DEF("stringify", 3, js_json_stringify ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "JSON", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_json_obj[] = {+    JS_OBJECT_DEF("JSON", js_json_funcs, countof(js_json_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),+};++void JS_AddIntrinsicJSON(JSContext *ctx)+{+    /* add JSON as autoinit object */+    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_json_obj, countof(js_json_obj));+}++/* Reflect */++static JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 2);+}++static JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValueConst func, array_arg, new_target;+    JSValue *tab, ret;+    uint32_t len;++    func = argv[0];+    array_arg = argv[1];+    if (argc > 2) {+        new_target = argv[2];+        if (!JS_IsConstructor(ctx, new_target))+            return JS_ThrowTypeError(ctx, "not a constructor");+    } else {+        new_target = func;+    }+    tab = build_arg_list(ctx, &len, array_arg);+    if (!tab)+        return JS_EXCEPTION;+    ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab);+    free_arg_list(ctx, tab, len);+    return ret;+}++static JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    JSValueConst obj;+    JSAtom atom;+    int ret;++    obj = argv[0];+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    atom = JS_ValueToAtom(ctx, argv[1]);+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    ret = JS_DeleteProperty(ctx, obj, atom, 0);+    JS_FreeAtom(ctx, atom);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSValueConst obj, prop, receiver;+    JSAtom atom;+    JSValue ret;++    obj = argv[0];+    prop = argv[1];+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    if (argc > 2)+        receiver = argv[2];+    else+        receiver = obj;+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, FALSE);+    JS_FreeAtom(ctx, atom);+    return ret;+}++static JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSValueConst obj, prop;+    JSAtom atom;+    int ret;++    obj = argv[0];+    prop = argv[1];+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    ret = JS_HasProperty(ctx, obj, atom);+    JS_FreeAtom(ctx, atom);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    JSValueConst obj, prop, val, receiver;+    int ret;+    JSAtom atom;++    obj = argv[0];+    prop = argv[1];+    val = argv[2];+    if (argc > 3)+        receiver = argv[3];+    else+        receiver = obj;+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    atom = JS_ValueToAtom(ctx, prop);+    if (unlikely(atom == JS_ATOM_NULL))+        return JS_EXCEPTION;+    ret = JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(obj), atom,+                                JS_DupValue(ctx, val), receiver, 0);+    JS_FreeAtom(ctx, atom);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    int ret;+    ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE);+    if (ret < 0)+        return JS_EXCEPTION;+    else+        return JS_NewBool(ctx, ret);+}++static JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);+    return JS_GetOwnPropertyNames2(ctx, argv[0],+                                   JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK,+                                   JS_ITERATOR_KIND_KEY);+}++static const JSCFunctionListEntry js_reflect_funcs[] = {+    JS_CFUNC_DEF("apply", 3, js_reflect_apply ),+    JS_CFUNC_DEF("construct", 2, js_reflect_construct ),+    JS_CFUNC_MAGIC_DEF("defineProperty", 3, js_object_defineProperty, 1 ),+    JS_CFUNC_DEF("deleteProperty", 2, js_reflect_deleteProperty ),+    JS_CFUNC_DEF("get", 2, js_reflect_get ),+    JS_CFUNC_MAGIC_DEF("getOwnPropertyDescriptor", 2, js_object_getOwnPropertyDescriptor, 1 ),+    JS_CFUNC_MAGIC_DEF("getPrototypeOf", 1, js_object_getPrototypeOf, 1 ),+    JS_CFUNC_DEF("has", 2, js_reflect_has ),+    JS_CFUNC_MAGIC_DEF("isExtensible", 1, js_object_isExtensible, 1 ),+    JS_CFUNC_DEF("ownKeys", 1, js_reflect_ownKeys ),+    JS_CFUNC_MAGIC_DEF("preventExtensions", 1, js_object_preventExtensions, 1 ),+    JS_CFUNC_DEF("set", 3, js_reflect_set ),+    JS_CFUNC_DEF("setPrototypeOf", 2, js_reflect_setPrototypeOf ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Reflect", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_reflect_obj[] = {+    JS_OBJECT_DEF("Reflect", js_reflect_funcs, countof(js_reflect_funcs), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),+};++/* Proxy */++static void js_proxy_finalizer(JSRuntime *rt, JSValue val)+{+    JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY);+    if (s) {+        JS_FreeValueRT(rt, s->target);+        JS_FreeValueRT(rt, s->handler);+        js_free_rt(rt, s);+    }+}++static void js_proxy_mark(JSRuntime *rt, JSValueConst val,+                          JS_MarkFunc *mark_func)+{+    JSProxyData *s = JS_GetOpaque(val, JS_CLASS_PROXY);+    if (s) {+        JS_MarkValue(rt, s->target, mark_func);+        JS_MarkValue(rt, s->handler, mark_func);+    }+}++static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "revoked proxy");+}++static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod,+                                     JSValueConst obj, JSAtom name)+{+    JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);+    JSValue method;++    /* safer to test recursion in all proxy methods */+    if (js_check_stack_overflow(ctx->rt, 0)) {+        JS_ThrowStackOverflow(ctx);+        return NULL;+    }+    +    /* 's' should never be NULL */+    if (s->is_revoked) {+        JS_ThrowTypeErrorRevokedProxy(ctx);+        return NULL;+    }+    method = JS_GetProperty(ctx, s->handler, name);+    if (JS_IsException(method))+        return NULL;+    if (JS_IsNull(method))+        method = JS_UNDEFINED;+    *pmethod = method;+    return s;+}++static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj)+{+    JSProxyData *s;+    JSValue method, ret, proto1;+    int res;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf);+    if (!s)+        return JS_EXCEPTION;+    if (JS_IsUndefined(method))+        return JS_GetPrototype(ctx, s->target);+    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);+    if (JS_IsException(ret))+        return ret;+    if (JS_VALUE_GET_TAG(ret) != JS_TAG_NULL &&+        JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {+        goto fail;+    }+    res = JS_IsExtensible(ctx, s->target);+    if (res < 0) {+        JS_FreeValue(ctx, ret);+        return JS_EXCEPTION;+    }+    if (!res) {+        /* check invariant */+        proto1 = JS_GetPrototype(ctx, s->target);+        if (JS_IsException(proto1)) {+            JS_FreeValue(ctx, ret);+            return JS_EXCEPTION;+        }+        if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) {+            JS_FreeValue(ctx, proto1);+        fail:+            JS_FreeValue(ctx, ret);+            return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");+        }+        JS_FreeValue(ctx, proto1);+    }+    return ret;+}++static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,+                                   JSValueConst proto_val, BOOL throw_flag)+{+    JSProxyData *s;+    JSValue method, ret, proto1;+    JSValueConst args[2];+    BOOL res;+    int res2;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_setPrototypeOf);+    if (!s)+        return -1;+    if (JS_IsUndefined(method))+        return JS_SetPrototypeInternal(ctx, s->target, proto_val, throw_flag);+    args[0] = s->target;+    args[1] = proto_val;+    ret = JS_CallFree(ctx, method, s->handler, 2, args);+    if (JS_IsException(ret))+        return -1;+    res = JS_ToBoolFree(ctx, ret);+    if (!res) {+        if (throw_flag) {+            JS_ThrowTypeError(ctx, "proxy: bad prototype");+            return -1;+        } else {+            return FALSE;+        }+    }+    res2 = JS_IsExtensible(ctx, s->target);+    if (res2 < 0)+        return -1;+    if (!res2) {+        proto1 = JS_GetPrototype(ctx, s->target);+        if (JS_IsException(proto1))+            return -1;+        if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) {+            JS_FreeValue(ctx, proto1);+            JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");+            return -1;+        }+        JS_FreeValue(ctx, proto1);+    }+    return TRUE;+}++static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj)+{+    JSProxyData *s;+    JSValue method, ret;+    BOOL res;+    int res2;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_isExtensible);+    if (!s)+        return -1;+    if (JS_IsUndefined(method))+        return JS_IsExtensible(ctx, s->target);+    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);+    if (JS_IsException(ret))+        return -1;+    res = JS_ToBoolFree(ctx, ret);+    res2 = JS_IsExtensible(ctx, s->target);+    if (res2 < 0)+        return res2;+    if (res != res2) {+        JS_ThrowTypeError(ctx, "proxy: inconsistent isExtensible");+        return -1;+    }+    return res;+}++static int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj)+{+    JSProxyData *s;+    JSValue method, ret;+    BOOL res;+    int res2;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_preventExtensions);+    if (!s)+        return -1;+    if (JS_IsUndefined(method))+        return JS_PreventExtensions(ctx, s->target);+    ret = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);+    if (JS_IsException(ret))+        return -1;+    res = JS_ToBoolFree(ctx, ret);+    if (res) {+        res2 = JS_IsExtensible(ctx, s->target);+        if (res2 < 0)+            return res2;+        if (res2) {+            JS_ThrowTypeError(ctx, "proxy: inconsistent preventExtensions");+            return -1;+        }+    }+    return res;+}++static int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom)+{+    JSProxyData *s;+    JSValue method, ret1, atom_val;+    int ret, res;+    JSObject *p;+    JSValueConst args[2];+    BOOL res2;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_has);+    if (!s)+        return -1;+    if (JS_IsUndefined(method))+        return JS_HasProperty(ctx, s->target, atom);+    atom_val = JS_AtomToValue(ctx, atom);+    if (JS_IsException(atom_val)) {+        JS_FreeValue(ctx, method);+        return -1;+    }+    args[0] = s->target;+    args[1] = atom_val;+    ret1 = JS_CallFree(ctx, method, s->handler, 2, args);+    JS_FreeValue(ctx, atom_val);+    if (JS_IsException(ret1))+        return -1;+    ret = JS_ToBoolFree(ctx, ret1);+    if (!ret) {+        JSPropertyDescriptor desc;+        p = JS_VALUE_GET_OBJ(s->target);+        res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);+        if (res < 0)+            return -1;+        if (res) {+            res2 = !(desc.flags & JS_PROP_CONFIGURABLE);+            js_free_desc(ctx, &desc);+            if (res2 || !p->extensible) {+                JS_ThrowTypeError(ctx, "proxy: inconsistent has");+                return -1;+            }+        }+    }+    return ret;+}++static JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom,+                            JSValueConst receiver)+{+    JSProxyData *s;+    JSValue method, ret, atom_val;+    int res;+    JSValueConst args[3];+    JSPropertyDescriptor desc;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_get);+    if (!s)+        return JS_EXCEPTION;+    /* Note: recursion is possible thru the prototype of s->target */+    if (JS_IsUndefined(method))+        return JS_GetPropertyInternal(ctx, s->target, atom, receiver, FALSE);+    atom_val = JS_AtomToValue(ctx, atom);+    if (JS_IsException(atom_val)) {+        JS_FreeValue(ctx, method);+        return JS_EXCEPTION;+    }+    args[0] = s->target;+    args[1] = atom_val;+    args[2] = receiver;+    ret = JS_CallFree(ctx, method, s->handler, 3, args);+    JS_FreeValue(ctx, atom_val);+    if (JS_IsException(ret))+        return JS_EXCEPTION;+    res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);+    if (res < 0)+        return JS_EXCEPTION;+    if (res) {+        if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) {+            if (!js_same_value(ctx, desc.value, ret)) {+                goto fail;+            }+        } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET) {+            if (JS_IsUndefined(desc.getter) && !JS_IsUndefined(ret)) {+            fail:+                js_free_desc(ctx, &desc);+                JS_FreeValue(ctx, ret);+                return JS_ThrowTypeError(ctx, "proxy: inconsistent get");+            }+        }+        js_free_desc(ctx, &desc);+    }+    return ret;+}++static int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom,+                        JSValueConst value, JSValueConst receiver, int flags)+{+    JSProxyData *s;+    JSValue method, ret1, atom_val;+    int ret, res;+    JSValueConst args[4];++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_set);+    if (!s)+        return -1;+    if (JS_IsUndefined(method)) {+        return JS_SetPropertyGeneric(ctx, JS_VALUE_GET_OBJ(s->target), atom,+                                     JS_DupValue(ctx, value), receiver,+                                     flags);+    }+    atom_val = JS_AtomToValue(ctx, atom);+    if (JS_IsException(atom_val)) {+        JS_FreeValue(ctx, method);+        return -1;+    }+    args[0] = s->target;+    args[1] = atom_val;+    args[2] = value;+    args[3] = receiver;+    ret1 = JS_CallFree(ctx, method, s->handler, 4, args);+    JS_FreeValue(ctx, atom_val);+    if (JS_IsException(ret1))+        return -1;+    ret = JS_ToBoolFree(ctx, ret1);+    if (ret) {+        JSPropertyDescriptor desc;+        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);+        if (res < 0)+            return -1;+        if (res) {+            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0) {+                if (!js_same_value(ctx, desc.value, value)) {+                    goto fail;+                }+            } else if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) == JS_PROP_GETSET && JS_IsUndefined(desc.setter)) {+                fail:+                    js_free_desc(ctx, &desc);+                    JS_ThrowTypeError(ctx, "proxy: inconsistent set");+                    return -1;+            }+            js_free_desc(ctx, &desc);+        }+    } else {+        if ((flags & JS_PROP_THROW) ||+            ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) {+            JS_ThrowTypeError(ctx, "proxy: cannot set property");+            return -1;+        }+    }+    return ret;+}++static JSValue js_create_desc(JSContext *ctx, JSValueConst val,+                              JSValueConst getter, JSValueConst setter,+                              int flags)+{+    JSValue ret;+    ret = JS_NewObject(ctx);+    if (JS_IsException(ret))+        return ret;+    if (flags & JS_PROP_HAS_GET) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_get, JS_DupValue(ctx, getter),+                               JS_PROP_C_W_E);+    }+    if (flags & JS_PROP_HAS_SET) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_set, JS_DupValue(ctx, setter),+                               JS_PROP_C_W_E);+    }+    if (flags & JS_PROP_HAS_VALUE) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_value, JS_DupValue(ctx, val),+                               JS_PROP_C_W_E);+    }+    if (flags & JS_PROP_HAS_WRITABLE) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_writable,+                               JS_NewBool(ctx, (flags & JS_PROP_WRITABLE) != 0),+                               JS_PROP_C_W_E);+    }+    if (flags & JS_PROP_HAS_ENUMERABLE) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_enumerable,+                               JS_NewBool(ctx, (flags & JS_PROP_ENUMERABLE) != 0),+                               JS_PROP_C_W_E);+    }+    if (flags & JS_PROP_HAS_CONFIGURABLE) {+        JS_DefinePropertyValue(ctx, ret, JS_ATOM_configurable,+                               JS_NewBool(ctx, (flags & JS_PROP_CONFIGURABLE) != 0),+                               JS_PROP_C_W_E);+    }+    return ret;+}++static int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc,+                                     JSValueConst obj, JSAtom prop)+{+    JSProxyData *s;+    JSValue method, trap_result_obj, prop_val;+    int res, target_desc_ret, ret;+    JSObject *p;+    JSValueConst args[2];+    JSPropertyDescriptor result_desc, target_desc;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_getOwnPropertyDescriptor);+    if (!s)+        return -1;+    p = JS_VALUE_GET_OBJ(s->target);+    if (JS_IsUndefined(method)) {+        return JS_GetOwnPropertyInternal(ctx, pdesc, p, prop);+    }+    prop_val = JS_AtomToValue(ctx, prop);+    if (JS_IsException(prop_val)) {+        JS_FreeValue(ctx, method);+        return -1;+    }+    args[0] = s->target;+    args[1] = prop_val;+    trap_result_obj = JS_CallFree(ctx, method, s->handler, 2, args);+    JS_FreeValue(ctx, prop_val);+    if (JS_IsException(trap_result_obj))+        return -1;+    if (!JS_IsObject(trap_result_obj) && !JS_IsUndefined(trap_result_obj)) {+        JS_FreeValue(ctx, trap_result_obj);+        goto fail;+    }+    target_desc_ret = JS_GetOwnPropertyInternal(ctx, &target_desc, p, prop);+    if (target_desc_ret < 0) {+        JS_FreeValue(ctx, trap_result_obj);+        return -1;+    }+    if (target_desc_ret)+        js_free_desc(ctx, &target_desc);+    if (JS_IsUndefined(trap_result_obj)) {+        if (target_desc_ret) {+            if (!(target_desc.flags & JS_PROP_CONFIGURABLE) || !p->extensible)+                goto fail;+        }+        ret = FALSE;+    } else {+        int flags1, extensible_target;+        extensible_target = JS_IsExtensible(ctx, s->target);+        if (extensible_target < 0) {+            JS_FreeValue(ctx, trap_result_obj);+            return -1;+        }+        res = js_obj_to_desc(ctx, &result_desc, trap_result_obj);+        JS_FreeValue(ctx, trap_result_obj);+        if (res < 0)+            return -1;+        +        if (target_desc_ret) {+            /* convert result_desc.flags to defineProperty flags */+            flags1 = result_desc.flags | JS_PROP_HAS_CONFIGURABLE | JS_PROP_HAS_ENUMERABLE;+            if (result_desc.flags & JS_PROP_GETSET)+                flags1 |= JS_PROP_HAS_GET | JS_PROP_HAS_SET;+            else+                flags1 |= JS_PROP_HAS_VALUE | JS_PROP_HAS_WRITABLE;+            /* XXX: not complete check: need to compare value &+               getter/setter as in defineproperty */+            if (!check_define_prop_flags(target_desc.flags, flags1))+                goto fail1;+        } else {+            if (!extensible_target)+                goto fail1;+        }+        if (!(result_desc.flags & JS_PROP_CONFIGURABLE)) {+            if (!target_desc_ret || (target_desc.flags & JS_PROP_CONFIGURABLE))+                goto fail1;+            if ((result_desc.flags &+                 (JS_PROP_GETSET | JS_PROP_WRITABLE)) == 0 &&+                target_desc_ret &&+                (target_desc.flags & JS_PROP_WRITABLE) != 0) {+                /* proxy-missing-checks */+            fail1:+                js_free_desc(ctx, &result_desc);+            fail:+                JS_ThrowTypeError(ctx, "proxy: inconsistent getOwnPropertyDescriptor");+                return -1;+            }+        }+        ret = TRUE;+        if (pdesc) {+            *pdesc = result_desc;+        } else {+            js_free_desc(ctx, &result_desc);+        }+    }+    return ret;+}++static int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj,+                                        JSAtom prop, JSValueConst val,+                                        JSValueConst getter, JSValueConst setter,+                                        int flags)+{+    JSProxyData *s;+    JSValue method, ret1, prop_val, desc_val;+    int res, ret;+    JSObject *p;+    JSValueConst args[3];+    JSPropertyDescriptor desc;+    BOOL setting_not_configurable;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_defineProperty);+    if (!s)+        return -1;+    if (JS_IsUndefined(method)) {+        return JS_DefineProperty(ctx, s->target, prop, val, getter, setter, flags);+    }+    prop_val = JS_AtomToValue(ctx, prop);+    if (JS_IsException(prop_val)) {+        JS_FreeValue(ctx, method);+        return -1;+    }+    desc_val = js_create_desc(ctx, val, getter, setter, flags);+    if (JS_IsException(desc_val)) {+        JS_FreeValue(ctx, prop_val);+        JS_FreeValue(ctx, method);+        return -1;+    }+    args[0] = s->target;+    args[1] = prop_val;+    args[2] = desc_val;+    ret1 = JS_CallFree(ctx, method, s->handler, 3, args);+    JS_FreeValue(ctx, prop_val);+    JS_FreeValue(ctx, desc_val);+    if (JS_IsException(ret1))+        return -1;+    ret = JS_ToBoolFree(ctx, ret1);+    if (!ret) {+        if (flags & JS_PROP_THROW) {+            JS_ThrowTypeError(ctx, "proxy: defineProperty exception");+            return -1;+        } else {+            return 0;+        }+    }+    p = JS_VALUE_GET_OBJ(s->target);+    res = JS_GetOwnPropertyInternal(ctx, &desc, p, prop);+    if (res < 0)+        return -1;+    setting_not_configurable = ((flags & (JS_PROP_HAS_CONFIGURABLE |+                                          JS_PROP_CONFIGURABLE)) ==+                                JS_PROP_HAS_CONFIGURABLE);+    if (!res) {+        if (!p->extensible || setting_not_configurable)+            goto fail;+    } else {+        if (!check_define_prop_flags(desc.flags, flags) ||+            ((desc.flags & JS_PROP_CONFIGURABLE) && setting_not_configurable)) {+            goto fail1;+        }+        if (flags & (JS_PROP_HAS_GET | JS_PROP_HAS_SET)) {+            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE)) ==+                JS_PROP_GETSET) {+                if ((flags & JS_PROP_HAS_GET) &&+                    !js_same_value(ctx, getter, desc.getter)) {+                    goto fail1;+                }+                if ((flags & JS_PROP_HAS_SET) &&+                    !js_same_value(ctx, setter, desc.setter)) {+                    goto fail1;+                }+            }+        } else if (flags & JS_PROP_HAS_VALUE) {+            if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) ==+                JS_PROP_WRITABLE && !(flags & JS_PROP_WRITABLE)) {+                /* missing-proxy-check feature */+                goto fail1;+            } else if ((desc.flags & (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE)) == 0 &&+                !js_same_value(ctx, val, desc.value)) {+                goto fail1;+            }+        }+        if (flags & JS_PROP_HAS_WRITABLE) {+            if ((desc.flags & (JS_PROP_GETSET | JS_PROP_CONFIGURABLE |+                               JS_PROP_WRITABLE)) == JS_PROP_WRITABLE) {+                /* proxy-missing-checks */+            fail1:+                js_free_desc(ctx, &desc);+            fail:+                JS_ThrowTypeError(ctx, "proxy: inconsistent defineProperty");+                return -1;+            }+        }+        js_free_desc(ctx, &desc);+    }+    return 1;+}++static int js_proxy_delete_property(JSContext *ctx, JSValueConst obj,+                                    JSAtom atom)+{+    JSProxyData *s;+    JSValue method, ret, atom_val;+    int res, res2, is_extensible;+    JSValueConst args[2];++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_deleteProperty);+    if (!s)+        return -1;+    if (JS_IsUndefined(method)) {+        return JS_DeleteProperty(ctx, s->target, atom, 0);+    }+    atom_val = JS_AtomToValue(ctx, atom);;+    if (JS_IsException(atom_val)) {+        JS_FreeValue(ctx, method);+        return -1;+    }+    args[0] = s->target;+    args[1] = atom_val;+    ret = JS_CallFree(ctx, method, s->handler, 2, args);+    JS_FreeValue(ctx, atom_val);+    if (JS_IsException(ret))+        return -1;+    res = JS_ToBoolFree(ctx, ret);+    if (res) {+        JSPropertyDescriptor desc;+        res2 = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target), atom);+        if (res2 < 0)+            return -1;+        if (res2) {+            if (!(desc.flags & JS_PROP_CONFIGURABLE))+                goto fail;+            is_extensible = JS_IsExtensible(ctx, s->target);+            if (is_extensible < 0)+                goto fail1;+            if (!is_extensible) {+                /* proxy-missing-checks */+            fail:+                JS_ThrowTypeError(ctx, "proxy: inconsistent deleteProperty");+            fail1:+                js_free_desc(ctx, &desc);+                return -1;+            }+            js_free_desc(ctx, &desc);+        }+    }+    return res;+}++/* return the index of the property or -1 if not found */+static int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom)+{+    int i;+    for(i = 0; i < n; i++) {+        if (tab[i].atom == atom)+            return i;+    }+    return -1;+}++static int js_proxy_get_own_property_names(JSContext *ctx,+                                           JSPropertyEnum **ptab,+                                           uint32_t *plen,+                                           JSValueConst obj)+{+    JSProxyData *s;+    JSValue method, prop_array, val;+    uint32_t len, i, len2;+    JSPropertyEnum *tab, *tab2;+    JSAtom atom;+    JSPropertyDescriptor desc;+    int res, is_extensible, idx;++    s = get_proxy_method(ctx, &method, obj, JS_ATOM_ownKeys);+    if (!s)+        return -1;+    if (JS_IsUndefined(method)) {+        return JS_GetOwnPropertyNamesInternal(ctx, ptab, plen,+                                      JS_VALUE_GET_OBJ(s->target),+                                      JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK);+    }+    prop_array = JS_CallFree(ctx, method, s->handler, 1, (JSValueConst *)&s->target);+    if (JS_IsException(prop_array))+        return -1;+    tab = NULL;+    len = 0;+    tab2 = NULL;+    len2 = 0;+    if (js_get_length32(ctx, &len, prop_array))+        goto fail;+    if (len > 0) {+        tab = js_mallocz(ctx, sizeof(tab[0]) * len);+        if (!tab)+            goto fail;+    }+    for(i = 0; i < len; i++) {+        val = JS_GetPropertyUint32(ctx, prop_array, i);+        if (JS_IsException(val))+            goto fail;+        if (!JS_IsString(val) && !JS_IsSymbol(val)) {+            JS_FreeValue(ctx, val);+            JS_ThrowTypeError(ctx, "proxy: properties must be strings or symbols");+            goto fail;+        }+        atom = JS_ValueToAtom(ctx, val);+        JS_FreeValue(ctx, val);+        if (atom == JS_ATOM_NULL)+            goto fail;+        tab[i].atom = atom;+        tab[i].is_enumerable = FALSE; /* XXX: redundant? */+    }++    /* check duplicate properties (XXX: inefficient, could store the+     * properties an a temporary object to use the hash) */+    for(i = 1; i < len; i++) {+        if (find_prop_key(tab, i, tab[i].atom) >= 0) {+            JS_ThrowTypeError(ctx, "proxy: duplicate property");+            goto fail;+        }+    }++    is_extensible = JS_IsExtensible(ctx, s->target);+    if (is_extensible < 0)+        goto fail;++    /* check if there are non configurable properties */+    if (s->is_revoked) {+        JS_ThrowTypeErrorRevokedProxy(ctx);+        goto fail;+    }+    if (JS_GetOwnPropertyNamesInternal(ctx, &tab2, &len2, JS_VALUE_GET_OBJ(s->target),+                               JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK))+        goto fail;+    for(i = 0; i < len2; i++) {+        if (s->is_revoked) {+            JS_ThrowTypeErrorRevokedProxy(ctx);+            goto fail;+        }+        res = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(s->target),+                                tab2[i].atom);+        if (res < 0)+            goto fail;+        if (res) {  /* safety, property should be found */+            js_free_desc(ctx, &desc);+            if (!(desc.flags & JS_PROP_CONFIGURABLE) || !is_extensible) {+                idx = find_prop_key(tab, len, tab2[i].atom);+                if (idx < 0) {+                    JS_ThrowTypeError(ctx, "proxy: target property must be present in proxy ownKeys");+                    goto fail;+                }+                /* mark the property as found */+                if (!is_extensible)+                    tab[idx].is_enumerable = TRUE;+            }+        }+    }+    if (!is_extensible) {+        /* check that all property in 'tab' were checked */+        for(i = 0; i < len; i++) {+            if (!tab[i].is_enumerable) {+                JS_ThrowTypeError(ctx, "proxy: property not present in target were returned by non extensible proxy");+                goto fail;+            }+        }+    }++    js_free_prop_enum(ctx, tab2, len2);+    JS_FreeValue(ctx, prop_array);+    *ptab = tab;+    *plen = len;+    return 0;+ fail:+    js_free_prop_enum(ctx, tab2, len2);+    js_free_prop_enum(ctx, tab, len);+    JS_FreeValue(ctx, prop_array);+    return -1;+}++static JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj,+                                         JSValueConst new_target,+                                         int argc, JSValueConst *argv)+{+    JSProxyData *s;+    JSValue method, arg_array, ret;+    JSValueConst args[3];++    s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_construct);+    if (!s)+        return JS_EXCEPTION;+    if (!JS_IsConstructor(ctx, s->target))+        return JS_ThrowTypeError(ctx, "not a constructor");+    if (JS_IsUndefined(method))+        return JS_CallConstructor2(ctx, s->target, new_target, argc, argv);+    arg_array = js_create_array(ctx, argc, argv);+    if (JS_IsException(arg_array)) {+        ret = JS_EXCEPTION;+        goto fail;+    }+    args[0] = s->target;+    args[1] = arg_array;+    args[2] = new_target;+    ret = JS_Call(ctx, method, s->handler, 3, args);+    if (!JS_IsException(ret) && JS_VALUE_GET_TAG(ret) != JS_TAG_OBJECT) {+        JS_FreeValue(ctx, ret);+        ret = JS_ThrowTypeErrorNotAnObject(ctx);+    }+ fail:+    JS_FreeValue(ctx, method);+    JS_FreeValue(ctx, arg_array);+    return ret;+}++static JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj,+                             JSValueConst this_obj,+                             int argc, JSValueConst *argv, int flags)+{+    JSProxyData *s;+    JSValue method, arg_array, ret;+    JSValueConst args[3];++    if (flags & JS_CALL_FLAG_CONSTRUCTOR)+        return js_proxy_call_constructor(ctx, func_obj, this_obj, argc, argv);+    +    s = get_proxy_method(ctx, &method, func_obj, JS_ATOM_apply);+    if (!s)+        return JS_EXCEPTION;+    if (!s->is_func) {+        JS_FreeValue(ctx, method);+        return JS_ThrowTypeError(ctx, "not a function");+    }+    if (JS_IsUndefined(method))+        return JS_Call(ctx, s->target, this_obj, argc, argv);+    arg_array = js_create_array(ctx, argc, argv);+    if (JS_IsException(arg_array)) {+        ret = JS_EXCEPTION;+        goto fail;+    }+    args[0] = s->target;+    args[1] = this_obj;+    args[2] = arg_array;+    ret = JS_Call(ctx, method, s->handler, 3, args);+ fail:+    JS_FreeValue(ctx, method);+    JS_FreeValue(ctx, arg_array);+    return ret;+}++static int js_proxy_isArray(JSContext *ctx, JSValueConst obj)+{+    JSProxyData *s = JS_GetOpaque(obj, JS_CLASS_PROXY);+    if (!s)+        return FALSE;+    if (s->is_revoked) {+        JS_ThrowTypeErrorRevokedProxy(ctx);+        return -1;+    }+    return JS_IsArray(ctx, s->target);+}++static const JSClassExoticMethods js_proxy_exotic_methods = {+    .get_own_property = js_proxy_get_own_property,+    .define_own_property = js_proxy_define_own_property,+    .delete_property = js_proxy_delete_property,+    .get_own_property_names = js_proxy_get_own_property_names,+    .has_property = js_proxy_has,+    .get_property = js_proxy_get,+    .set_property = js_proxy_set,+};++static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValueConst target, handler;+    JSValue obj;+    JSProxyData *s;++    target = argv[0];+    handler = argv[1];+    if (JS_VALUE_GET_TAG(target) != JS_TAG_OBJECT ||+        JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT)+        return JS_ThrowTypeErrorNotAnObject(ctx);++    obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY);+    if (JS_IsException(obj))+        return obj;+    s = js_malloc(ctx, sizeof(JSProxyData));+    if (!s) {+        JS_FreeValue(ctx, obj);+        return JS_EXCEPTION;+    }+    s->target = JS_DupValue(ctx, target);+    s->handler = JS_DupValue(ctx, handler);+    s->is_func = JS_IsFunction(ctx, target);+    s->is_revoked = FALSE;+    JS_SetOpaque(obj, s);+    JS_SetConstructorBit(ctx, obj, JS_IsConstructor(ctx, target));+    return obj;+}++static JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv, int magic,+                               JSValue *func_data)+{+    JSProxyData *s = JS_GetOpaque(func_data[0], JS_CLASS_PROXY);+    if (s) {+        /* We do not free the handler and target in case they are+           referenced as constants in the C call stack */+        s->is_revoked = TRUE;+        JS_FreeValue(ctx, func_data[0]);+        func_data[0] = JS_NULL;+    }+    return JS_UNDEFINED;+}++static JSValue js_proxy_revoke_constructor(JSContext *ctx,+                                           JSValueConst proxy_obj)+{+    return JS_NewCFunctionData(ctx, js_proxy_revoke, 0, 0, 1, &proxy_obj);+}++static JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue proxy_obj, revoke_obj = JS_UNDEFINED, obj;++    proxy_obj = js_proxy_constructor(ctx, JS_UNDEFINED, argc, argv);+    if (JS_IsException(proxy_obj))+        goto fail;+    revoke_obj = js_proxy_revoke_constructor(ctx, proxy_obj);+    if (JS_IsException(revoke_obj))+        goto fail;+    obj = JS_NewObject(ctx);+    if (JS_IsException(obj))+        goto fail;+    // XXX: exceptions?+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_proxy, proxy_obj, JS_PROP_C_W_E);+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_revoke, revoke_obj, JS_PROP_C_W_E);+    return obj;+ fail:+    JS_FreeValue(ctx, proxy_obj);+    JS_FreeValue(ctx, revoke_obj);+    return JS_EXCEPTION;+}++static const JSCFunctionListEntry js_proxy_funcs[] = {+    JS_CFUNC_DEF("revocable", 2, js_proxy_revocable ),+};++static const JSClassShortDef js_proxy_class_def[] = {+    { JS_ATOM_Object, js_proxy_finalizer, js_proxy_mark }, /* JS_CLASS_PROXY */+};++void JS_AddIntrinsicProxy(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    JSValue obj1;++    if (!JS_IsRegisteredClass(rt, JS_CLASS_PROXY)) {+        init_class_range(rt, js_proxy_class_def, JS_CLASS_PROXY,+                         countof(js_proxy_class_def));+        rt->class_array[JS_CLASS_PROXY].exotic = &js_proxy_exotic_methods;+        rt->class_array[JS_CLASS_PROXY].call = js_proxy_call;+    }++    obj1 = JS_NewCFunction2(ctx, js_proxy_constructor, "Proxy", 2,+                            JS_CFUNC_constructor, 0);+    JS_SetConstructorBit(ctx, obj1, TRUE);+    JS_SetPropertyFunctionList(ctx, obj1, js_proxy_funcs,+                               countof(js_proxy_funcs));+    JS_DefinePropertyValueStr(ctx, ctx->global_obj, "Proxy",+                              obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+}++/* Symbol */++static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    JSValue str;+    JSString *p;++    if (!JS_IsUndefined(new_target))+        return JS_ThrowTypeError(ctx, "not a constructor");+    if (argc == 0 || JS_IsUndefined(argv[0])) {+        p = NULL;+    } else {+        str = JS_ToString(ctx, argv[0]);+        if (JS_IsException(str))+            return JS_EXCEPTION;+        p = JS_VALUE_GET_STRING(str);+    }+    return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL);+}++static JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL)+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_SYMBOL) {+            if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_SYMBOL)+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a symbol");+}++static JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValue val, ret;+    val = js_thisSymbolValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    /* XXX: use JS_ToStringInternal() with a flags */+    ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val);+    JS_FreeValue(ctx, val);+    return ret;+}++static JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return js_thisSymbolValue(ctx, this_val);+}++static JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val)+{+    JSValue val, ret;+    JSAtomStruct *p;++    val = js_thisSymbolValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    p = JS_VALUE_GET_PTR(val);+    if (p->len == 0 && p->is_wide_char != 0) {+        ret = JS_UNDEFINED;+    } else {+        ret = JS_AtomToString(ctx, js_get_atom_index(ctx->rt, p));+    }+    JS_FreeValue(ctx, val);+    return ret;+}++static const JSCFunctionListEntry js_symbol_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_symbol_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_symbol_valueOf ),+    // XXX: should have writable: false+    JS_CFUNC_DEF("[Symbol.toPrimitive]", 1, js_symbol_valueOf ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Symbol", JS_PROP_CONFIGURABLE ),+    JS_CGETSET_DEF("description", js_symbol_get_description, NULL ),+};++static JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    JSValue str;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return JS_EXCEPTION;+    return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL);+}++static JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSAtomStruct *p;++    if (!JS_IsSymbol(argv[0]))+        return JS_ThrowTypeError(ctx, "not a symbol");+    p = JS_VALUE_GET_PTR(argv[0]);+    if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL)+        return JS_UNDEFINED;+    return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p));+}++static const JSCFunctionListEntry js_symbol_funcs[] = {+    JS_CFUNC_DEF("for", 1, js_symbol_for ),+    JS_CFUNC_DEF("keyFor", 1, js_symbol_keyFor ),+};++/* Set/Map/WeakSet/WeakMap */++typedef struct JSMapRecord {+    int ref_count; /* used during enumeration to avoid freeing the record */+    BOOL empty; /* TRUE if the record is deleted */+    struct JSMapState *map;+    struct JSMapRecord *next_weak_ref;+    struct list_head link;+    struct list_head hash_link;+    JSValue key;+    JSValue value;+} JSMapRecord;++typedef struct JSMapState {+    BOOL is_weak; /* TRUE if WeakSet/WeakMap */+    struct list_head records; /* list of JSMapRecord.link */+    uint32_t record_count;+    struct list_head *hash_table;+    uint32_t hash_size; /* must be a power of two */+    uint32_t record_count_threshold; /* count at which a hash table+                                        resize is needed */+} JSMapState;++#define MAGIC_SET (1 << 0)+#define MAGIC_WEAK (1 << 1)++static JSValue js_map_constructor(JSContext *ctx, JSValueConst new_target,+                                  int argc, JSValueConst *argv, int magic)+{+    JSMapState *s;+    JSValue obj, adder = JS_UNDEFINED, iter = JS_UNDEFINED, next_method = JS_UNDEFINED;+    JSValueConst arr;+    BOOL is_set, is_weak;++    is_set = magic & MAGIC_SET;+    is_weak = ((magic & MAGIC_WEAK) != 0);+    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_MAP + magic);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    s = js_mallocz(ctx, sizeof(*s));+    if (!s)+        goto fail;+    init_list_head(&s->records);+    s->is_weak = is_weak;+    JS_SetOpaque(obj, s);+    s->hash_size = 1;+    s->hash_table = js_malloc(ctx, sizeof(s->hash_table[0]) * s->hash_size);+    if (!s->hash_table)+        goto fail;+    init_list_head(&s->hash_table[0]);+    s->record_count_threshold = 4;++    arr = JS_UNDEFINED;+    if (argc > 0)+        arr = argv[0];+    if (!JS_IsUndefined(arr) && !JS_IsNull(arr)) {+        JSValue item, ret;+        BOOL done;++        adder = JS_GetProperty(ctx, obj, is_set ? JS_ATOM_add : JS_ATOM_set);+        if (JS_IsException(adder))+            goto fail;+        if (!JS_IsFunction(ctx, adder)) {+            JS_ThrowTypeError(ctx, "set/add is not a function");+            goto fail;+        }++        iter = JS_GetIterator(ctx, arr, FALSE);+        if (JS_IsException(iter))+            goto fail;+        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);+        if (JS_IsException(next_method))+            goto fail;++        for(;;) {+            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);+            if (JS_IsException(item))+                goto fail;+            if (done) {+                JS_FreeValue(ctx, item);+                break;+            }+            if (is_set) {+                ret = JS_Call(ctx, adder, obj, 1, (JSValueConst *)&item);+                if (JS_IsException(ret)) {+                    JS_FreeValue(ctx, item);+                    goto fail;+                }+            } else {+                JSValue key, value;+                JSValueConst args[2];+                key = JS_UNDEFINED;+                value = JS_UNDEFINED;+                if (!JS_IsObject(item)) {+                    JS_ThrowTypeErrorNotAnObject(ctx);+                    goto fail1;+                }+                key = JS_GetPropertyUint32(ctx, item, 0);+                if (JS_IsException(key))+                    goto fail1;+                value = JS_GetPropertyUint32(ctx, item, 1);+                if (JS_IsException(value))+                    goto fail1;+                args[0] = key;+                args[1] = value;+                ret = JS_Call(ctx, adder, obj, 2, args);+                if (JS_IsException(ret)) {+                fail1:+                    JS_FreeValue(ctx, item);+                    JS_FreeValue(ctx, key);+                    JS_FreeValue(ctx, value);+                    goto fail;+                }+                JS_FreeValue(ctx, key);+                JS_FreeValue(ctx, value);+            }+            JS_FreeValue(ctx, ret);+            JS_FreeValue(ctx, item);+        }+        JS_FreeValue(ctx, next_method);+        JS_FreeValue(ctx, iter);+        JS_FreeValue(ctx, adder);+    }+    return obj;+ fail:+    if (JS_IsObject(iter)) {+        /* close the iterator object, preserving pending exception */+        JS_IteratorClose(ctx, iter, TRUE);+    }+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    JS_FreeValue(ctx, adder);+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++/* XXX: could normalize strings to speed up comparison */+static JSValueConst map_normalize_key(JSContext *ctx, JSValueConst key)+{+    uint32_t tag = JS_VALUE_GET_TAG(key);+    /* convert -0.0 to +0.0 */+    if (JS_TAG_IS_FLOAT64(tag) && JS_VALUE_GET_FLOAT64(key) == 0.0) {+        key = JS_NewInt32(ctx, 0);+    }+    return key;+}++/* XXX: better hash ? */+static uint32_t map_hash_key(JSContext *ctx, JSValueConst key)+{+    uint32_t tag = JS_VALUE_GET_NORM_TAG(key);+    uint32_t h;+    double d;+    JSFloat64Union u;++    switch(tag) {+    case JS_TAG_BOOL:+        h = JS_VALUE_GET_INT(key);+        break;+    case JS_TAG_STRING:+        h = hash_string(JS_VALUE_GET_STRING(key), 0);+        break;+    case JS_TAG_OBJECT:+    case JS_TAG_SYMBOL:+        h = (uintptr_t)JS_VALUE_GET_PTR(key) * 3163;+        break;+    case JS_TAG_INT:+        d = JS_VALUE_GET_INT(key) * 3163;+        goto hash_float64;+    case JS_TAG_FLOAT64:+        d = JS_VALUE_GET_FLOAT64(key);+        /* normalize the NaN */+        if (isnan(d))+            d = JS_FLOAT64_NAN;+    hash_float64:+        u.d = d;+        h = (u.u32[0] ^ u.u32[1]) * 3163;+        break;+    default:+        h = 0; /* XXX: bignum support */+        break;+    }+    h ^= tag;+    return h;+}++static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s,+                                    JSValueConst key)+{+    struct list_head *el;+    JSMapRecord *mr;+    uint32_t h;+    h = map_hash_key(ctx, key) & (s->hash_size - 1);+    list_for_each(el, &s->hash_table[h]) {+        mr = list_entry(el, JSMapRecord, hash_link);+        if (js_same_value_zero(ctx, mr->key, key))+            return mr;+    }+    return NULL;+}++static void map_hash_resize(JSContext *ctx, JSMapState *s)+{+    uint32_t new_hash_size, i, h;+    size_t slack;+    struct list_head *new_hash_table, *el;+    JSMapRecord *mr;++    /* XXX: no reporting of memory allocation failure */+    if (s->hash_size == 1)+        new_hash_size = 4;+    else+        new_hash_size = s->hash_size * 2;+    new_hash_table = js_realloc2(ctx, s->hash_table,+                                 sizeof(new_hash_table[0]) * new_hash_size, &slack);+    if (!new_hash_table)+        return;+    new_hash_size += slack / sizeof(*new_hash_table);++    for(i = 0; i < new_hash_size; i++)+        init_list_head(&new_hash_table[i]);++    list_for_each(el, &s->records) {+        mr = list_entry(el, JSMapRecord, link);+        if (!mr->empty) {+            h = map_hash_key(ctx, mr->key) & (new_hash_size - 1);+            list_add_tail(&mr->hash_link, &new_hash_table[h]);+        }+    }+    s->hash_table = new_hash_table;+    s->hash_size = new_hash_size;+    s->record_count_threshold = new_hash_size * 2;+}++static JSMapRecord *map_add_record(JSContext *ctx, JSMapState *s,+                                   JSValueConst key)+{+    uint32_t h;+    JSMapRecord *mr;++    mr = js_malloc(ctx, sizeof(*mr));+    if (!mr)+        return NULL;+    mr->ref_count = 1;+    mr->map = s;+    mr->empty = FALSE;+    if (s->is_weak) {+        JSObject *p = JS_VALUE_GET_OBJ(key);+        /* Add the weak reference */+        mr->next_weak_ref = p->first_weak_ref;+        p->first_weak_ref = mr;+    } else {+        JS_DupValue(ctx, key);+    }+    mr->key = (JSValue)key;+    h = map_hash_key(ctx, key) & (s->hash_size - 1);+    list_add_tail(&mr->hash_link, &s->hash_table[h]);+    list_add_tail(&mr->link, &s->records);+    s->record_count++;+    if (s->record_count >= s->record_count_threshold) {+        map_hash_resize(ctx, s);+    }+    return mr;+}++/* Remove the weak reference from the object weak+   reference list. we don't use a doubly linked list to+   save space, assuming a given object has few weak+       references to it */+static void delete_weak_ref(JSRuntime *rt, JSMapRecord *mr)+{+    JSMapRecord **pmr, *mr1;+    JSObject *p;++    p = JS_VALUE_GET_OBJ(mr->key);+    pmr = &p->first_weak_ref;+    for(;;) {+        mr1 = *pmr;+        assert(mr1 != NULL);+        if (mr1 == mr)+            break;+        pmr = &mr1->next_weak_ref;+    }+    *pmr = mr1->next_weak_ref;+}++static void map_delete_record(JSRuntime *rt, JSMapState *s, JSMapRecord *mr)+{+    if (mr->empty)+        return;+    list_del(&mr->hash_link);+    if (s->is_weak) {+        delete_weak_ref(rt, mr);+    } else {+        JS_FreeValueRT(rt, mr->key);+    }+    JS_FreeValueRT(rt, mr->value);+    if (--mr->ref_count == 0) {+        list_del(&mr->link);+        js_free_rt(rt, mr);+    } else {+        /* keep a zombie record for iterators */+        mr->empty = TRUE;+        mr->key = JS_UNDEFINED;+        mr->value = JS_UNDEFINED;+    }+    s->record_count--;+}++static void map_decref_record(JSRuntime *rt, JSMapRecord *mr)+{+    if (--mr->ref_count == 0) {+        /* the record can be safely removed */+        assert(mr->empty);+        list_del(&mr->link);+        js_free_rt(rt, mr);+    }+}++static void reset_weak_ref(JSRuntime *rt, JSObject *p)+{+    JSMapRecord *mr, *mr_next;+    JSMapState *s;+    +    /* first pass to remove the records from the WeakMap/WeakSet+       lists */+    for(mr = p->first_weak_ref; mr != NULL; mr = mr->next_weak_ref) {+        s = mr->map;+        assert(s->is_weak);+        assert(!mr->empty); /* no iterator on WeakMap/WeakSet */+        list_del(&mr->hash_link);+        list_del(&mr->link);+    }+    +    /* second pass to free the values to avoid modifying the weak+       reference list while traversing it. */+    for(mr = p->first_weak_ref; mr != NULL; mr = mr_next) {+        mr_next = mr->next_weak_ref;+        JS_FreeValueRT(rt, mr->value);+        js_free_rt(rt, mr);+    }++    p->first_weak_ref = NULL; /* fail safe */+}++static JSValue js_map_set(JSContext *ctx, JSValueConst this_val,+                          int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    JSMapRecord *mr;+    JSValueConst key, value;++    if (!s)+        return JS_EXCEPTION;+    key = map_normalize_key(ctx, argv[0]);+    if (s->is_weak && !JS_IsObject(key))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    if (magic & MAGIC_SET)+        value = JS_UNDEFINED;+    else+        value = argv[1];+    mr = map_find_record(ctx, s, key);+    if (mr) {+        JS_FreeValue(ctx, mr->value);+    } else {+        mr = map_add_record(ctx, s, key);+        if (!mr)+            return JS_EXCEPTION;+    }+    mr->value = JS_DupValue(ctx, value);+    return JS_DupValue(ctx, this_val);+}++static JSValue js_map_get(JSContext *ctx, JSValueConst this_val,+                          int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    JSMapRecord *mr;+    JSValueConst key;++    if (!s)+        return JS_EXCEPTION;+    key = map_normalize_key(ctx, argv[0]);+    mr = map_find_record(ctx, s, key);+    if (!mr)+        return JS_UNDEFINED;+    else+        return JS_DupValue(ctx, mr->value);+}++static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,+                          int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    JSMapRecord *mr;+    JSValueConst key;++    if (!s)+        return JS_EXCEPTION;+    key = map_normalize_key(ctx, argv[0]);+    mr = map_find_record(ctx, s, key);+    return JS_NewBool(ctx, (mr != NULL));+}++static JSValue js_map_delete(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    JSMapRecord *mr;+    JSValueConst key;++    if (!s)+        return JS_EXCEPTION;+    key = map_normalize_key(ctx, argv[0]);+    mr = map_find_record(ctx, s, key);+    if (!mr)+        return JS_FALSE;+    map_delete_record(ctx->rt, s, mr);+    return JS_TRUE;+}++static JSValue js_map_clear(JSContext *ctx, JSValueConst this_val,+                            int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    struct list_head *el, *el1;+    JSMapRecord *mr;++    if (!s)+        return JS_EXCEPTION;+    list_for_each_safe(el, el1, &s->records) {+        mr = list_entry(el, JSMapRecord, link);+        map_delete_record(ctx->rt, s, mr);+    }+    return JS_UNDEFINED;+}++static JSValue js_map_get_size(JSContext *ctx, JSValueConst this_val, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    if (!s)+        return JS_EXCEPTION;+    return JS_NewUint32(ctx, s->record_count);+}++static JSValue js_map_forEach(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    JSMapState *s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    JSValueConst func, this_arg;+    JSValue ret, args[3];+    struct list_head *el;+    JSMapRecord *mr;++    if (!s)+        return JS_EXCEPTION;+    func = argv[0];+    if (argc > 1)+        this_arg = argv[1];+    else+        this_arg = JS_UNDEFINED;+    if (check_function(ctx, func))+        return JS_EXCEPTION;+    /* Note: the list can be modified while traversing it, but the+       current element is locked */+    el = s->records.next;+    while (el != &s->records) {+        mr = list_entry(el, JSMapRecord, link);+        if (!mr->empty) {+            mr->ref_count++;+            /* must duplicate in case the record is deleted */+            args[1] = JS_DupValue(ctx, mr->key);+            if (magic)+                args[0] = args[1];+            else+                args[0] = JS_DupValue(ctx, mr->value);+            args[2] = (JSValue)this_val;+            ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);+            JS_FreeValue(ctx, args[0]);+            if (!magic)+                JS_FreeValue(ctx, args[1]);+            el = el->next;+            map_decref_record(ctx->rt, mr);+            if (JS_IsException(ret))+                return ret;+            JS_FreeValue(ctx, ret);+        } else {+            el = el->next;+        }+    }+    return JS_UNDEFINED;+}++static void js_map_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p;+    JSMapState *s;+    struct list_head *el, *el1;+    JSMapRecord *mr;++    p = JS_VALUE_GET_OBJ(val);+    s = p->u.map_state;+    if (s) {+        /* if the object is deleted we are sure that no iterator is+           using it */+        list_for_each_safe(el, el1, &s->records) {+            mr = list_entry(el, JSMapRecord, link);+            if (!mr->empty) {+                if (s->is_weak)+                    delete_weak_ref(rt, mr);+                else+                    JS_FreeValueRT(rt, mr->key);+                JS_FreeValueRT(rt, mr->value);+            }+            js_free_rt(rt, mr);+        }+        js_free_rt(rt, s->hash_table);+        js_free_rt(rt, s);+    }+}++static void js_map_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSMapState *s;+    struct list_head *el;+    JSMapRecord *mr;++    s = p->u.map_state;+    if (s) {+        list_for_each(el, &s->records) {+            mr = list_entry(el, JSMapRecord, link);+            if (!s->is_weak)+                JS_MarkValue(rt, mr->key, mark_func);+            JS_MarkValue(rt, mr->value, mark_func);+        }+    }+}++/* Map Iterator */++typedef struct JSMapIteratorData {+    JSValue obj;+    JSIteratorKindEnum kind;+    JSMapRecord *cur_record;+} JSMapIteratorData;++static void js_map_iterator_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p;+    JSMapIteratorData *it;++    p = JS_VALUE_GET_OBJ(val);+    it = p->u.map_iterator_data;+    if (it) {+        /* During the GC sweep phase the Map finalizer may be+           called before the Map iterator finalizer */+        if (JS_IsLiveObject(rt, it->obj) && it->cur_record) {+            map_decref_record(rt, it->cur_record);+        }+        JS_FreeValueRT(rt, it->obj);+        js_free_rt(rt, it);+    }+}++static void js_map_iterator_mark(JSRuntime *rt, JSValueConst val,+                                 JS_MarkFunc *mark_func)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSMapIteratorData *it;+    it = p->u.map_iterator_data;+    if (it) {+        /* the record is already marked by the object */+        JS_MarkValue(rt, it->obj, mark_func);+    }+}++static JSValue js_create_map_iterator(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv, int magic)+{+    JSIteratorKindEnum kind;+    JSMapState *s;+    JSMapIteratorData *it;+    JSValue enum_obj;++    kind = magic >> 2;+    magic &= 3;+    s = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP + magic);+    if (!s)+        return JS_EXCEPTION;+    enum_obj = JS_NewObjectClass(ctx, JS_CLASS_MAP_ITERATOR + magic);+    if (JS_IsException(enum_obj))+        goto fail;+    it = js_malloc(ctx, sizeof(*it));+    if (!it) {+        JS_FreeValue(ctx, enum_obj);+        goto fail;+    }+    it->obj = JS_DupValue(ctx, this_val);+    it->kind = kind;+    it->cur_record = NULL;+    JS_SetOpaque(enum_obj, it);+    return enum_obj;+ fail:+    return JS_EXCEPTION;+}++static JSValue js_map_iterator_next(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv,+                                    BOOL *pdone, int magic)+{+    JSMapIteratorData *it;+    JSMapState *s;+    JSMapRecord *mr;+    struct list_head *el;++    it = JS_GetOpaque2(ctx, this_val, JS_CLASS_MAP_ITERATOR + magic);+    if (!it) {+        *pdone = FALSE;+        return JS_EXCEPTION;+    }+    if (JS_IsUndefined(it->obj))+        goto done;+    s = JS_GetOpaque(it->obj, JS_CLASS_MAP + magic);+    assert(s != NULL);+    if (!it->cur_record) {+        el = s->records.next;+    } else {+        mr = it->cur_record;+        el = mr->link.next;+        map_decref_record(ctx->rt, mr); /* the record can be freed here */+    }+    for(;;) {+        if (el == &s->records) {+            /* no more record  */+            it->cur_record = NULL;+            JS_FreeValue(ctx, it->obj);+            it->obj = JS_UNDEFINED;+        done:+            /* end of enumeration */+            *pdone = TRUE;+            return JS_UNDEFINED;+        }+        mr = list_entry(el, JSMapRecord, link);+        if (!mr->empty)+            break;+        /* get the next record */+        el = mr->link.next;+    }++    /* lock the record so that it won't be freed */+    mr->ref_count++;+    it->cur_record = mr;+    *pdone = FALSE;++    if (it->kind == JS_ITERATOR_KIND_KEY) {+        return JS_DupValue(ctx, mr->key);+    } else {+        JSValueConst args[2];+        args[0] = mr->key;+        if (magic)+            args[1] = mr->key;+        else+            args[1] = mr->value;+        if (it->kind == JS_ITERATOR_KIND_VALUE) {+            return JS_DupValue(ctx, args[1]);+        } else {+            return js_create_array(ctx, 2, args);+        }+    }+}++static const JSCFunctionListEntry js_map_funcs[] = {+    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),+};++static const JSCFunctionListEntry js_map_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, 0 ),+    JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, 0 ),+    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, 0 ),+    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, 0 ),+    JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, 0 ),+    JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, 0),+    JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, 0 ),+    JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_VALUE << 2) | 0 ),+    JS_CFUNC_MAGIC_DEF("keys", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | 0 ),+    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY_AND_VALUE << 2) | 0 ),+    JS_ALIAS_DEF("[Symbol.iterator]", "entries" ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Map", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_map_iterator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 0, js_map_iterator_next, 0 ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Map Iterator", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_set_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("add", 1, js_map_set, MAGIC_SET ),+    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_SET ),+    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_SET ),+    JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, MAGIC_SET ),+    JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),+    JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),+    JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ),+    JS_ALIAS_DEF("keys", "values" ),+    JS_ALIAS_DEF("[Symbol.iterator]", "values" ),+    JS_CFUNC_MAGIC_DEF("entries", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY_AND_VALUE << 2) | MAGIC_SET ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Set", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_set_iterator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 0, js_map_iterator_next, MAGIC_SET ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Set Iterator", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_weak_map_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, MAGIC_WEAK ),+    JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, MAGIC_WEAK ),+    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_WEAK ),+    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_WEAK ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakMap", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry js_weak_set_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("add", 1, js_map_set, MAGIC_SET | MAGIC_WEAK ),+    JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_SET | MAGIC_WEAK ),+    JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_SET | MAGIC_WEAK ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakSet", JS_PROP_CONFIGURABLE ),+};++static const JSCFunctionListEntry * const js_map_proto_funcs_ptr[6] = {+    js_map_proto_funcs,+    js_set_proto_funcs,+    js_weak_map_proto_funcs,+    js_weak_set_proto_funcs,+    js_map_iterator_proto_funcs,+    js_set_iterator_proto_funcs,+};++static const uint8_t js_map_proto_funcs_count[6] = {+    countof(js_map_proto_funcs),+    countof(js_set_proto_funcs),+    countof(js_weak_map_proto_funcs),+    countof(js_weak_set_proto_funcs),+    countof(js_map_iterator_proto_funcs),+    countof(js_set_iterator_proto_funcs),+};++void JS_AddIntrinsicMapSet(JSContext *ctx)+{+    int i;+    JSValue obj1;+    char buf[ATOM_GET_STR_BUF_SIZE];++    for(i = 0; i < 4; i++) {+        const char *name = JS_AtomGetStr(ctx, buf, sizeof(buf),+                                         JS_ATOM_Map + i);+        ctx->class_proto[JS_CLASS_MAP + i] = JS_NewObject(ctx);+        JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP + i],+                                   js_map_proto_funcs_ptr[i],+                                   js_map_proto_funcs_count[i]);+        obj1 = JS_NewCFunctionMagic(ctx, js_map_constructor, name, 0,+                                    JS_CFUNC_constructor_magic, i);+        if (i < 2) {+            JS_SetPropertyFunctionList(ctx, obj1, js_map_funcs,+                                       countof(js_map_funcs));+        }+        JS_NewGlobalCConstructor2(ctx, obj1, name, ctx->class_proto[JS_CLASS_MAP + i]);+    }++    for(i = 0; i < 2; i++) {+        ctx->class_proto[JS_CLASS_MAP_ITERATOR + i] =+            JS_NewObjectProto(ctx, ctx->iterator_proto);+        JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_MAP_ITERATOR + i],+                                   js_map_proto_funcs_ptr[i + 4],+                                   js_map_proto_funcs_count[i + 4]);+    }+}++/* Generator */+static const JSCFunctionListEntry js_generator_function_proto_funcs[] = {+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "GeneratorFunction", JS_PROP_CONFIGURABLE),+};++static const JSCFunctionListEntry js_generator_proto_funcs[] = {+    JS_ITERATOR_NEXT_DEF("next", 1, js_generator_next, GEN_MAGIC_NEXT ),+    JS_ITERATOR_NEXT_DEF("return", 1, js_generator_next, GEN_MAGIC_RETURN ),+    JS_ITERATOR_NEXT_DEF("throw", 1, js_generator_next, GEN_MAGIC_THROW ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Generator", JS_PROP_CONFIGURABLE),+};++/* Promise */++typedef enum JSPromiseStateEnum {+    JS_PROMISE_PENDING,+    JS_PROMISE_FULFILLED,+    JS_PROMISE_REJECTED,+} JSPromiseStateEnum;++typedef struct JSPromiseData {+    JSPromiseStateEnum promise_state;+    /* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */+    struct list_head promise_reactions[2];+    BOOL is_handled; /* Note: only useful to debug */+    JSValue promise_result;+} JSPromiseData;++typedef struct JSPromiseFunctionDataResolved {+    int ref_count;+    BOOL already_resolved;+} JSPromiseFunctionDataResolved;++typedef struct JSPromiseFunctionData {+    JSValue promise;+    JSPromiseFunctionDataResolved *presolved;+} JSPromiseFunctionData;++typedef struct JSPromiseReactionData {+    struct list_head link; /* not used in promise_reaction_job */+    JSValue resolving_funcs[2];+    JSValue handler;+} JSPromiseReactionData;++static int js_create_resolving_functions(JSContext *ctx, JSValue *args,+                                         JSValueConst promise);++static void promise_reaction_data_free(JSRuntime *rt,+                                       JSPromiseReactionData *rd)+{+    JS_FreeValueRT(rt, rd->resolving_funcs[0]);+    JS_FreeValueRT(rt, rd->resolving_funcs[1]);+    JS_FreeValueRT(rt, rd->handler);+    js_free_rt(rt, rd);+}++static JSValue promise_reaction_job(JSContext *ctx, int argc,+                                    JSValueConst *argv)+{+    JSValueConst handler, arg, func;+    JSValue res, res2;+    BOOL is_reject;++    assert(argc == 5);+    handler = argv[2];+    is_reject = JS_ToBool(ctx, argv[3]);+    arg = argv[4];+#ifdef DUMP_PROMISE+    printf("promise_reaction_job: is_reject=%d\n", is_reject);+#endif++    if (JS_IsUndefined(handler)) {+        if (is_reject) {+            res = JS_Throw(ctx, JS_DupValue(ctx, arg));+        } else {+            res = JS_DupValue(ctx, arg);+        }+    } else {+        res = JS_Call(ctx, handler, JS_UNDEFINED, 1, &arg);+    }+    is_reject = JS_IsException(res);+    if (is_reject)+        res = JS_GetException(ctx);+    func = argv[is_reject];+    /* as an extension, we support undefined as value to avoid+       creating a dummy promise in the 'await' implementation of async+       functions */+    if (!JS_IsUndefined(func)) {+        res2 = JS_Call(ctx, func, JS_UNDEFINED,+                       1, (JSValueConst *)&res);+    } else {+        res2 = JS_UNDEFINED;+    }+    JS_FreeValue(ctx, res);++    return res2;+}++void JS_SetHostPromiseRejectionTracker(JSRuntime *rt,+                                       JSHostPromiseRejectionTracker *cb,+                                       void *opaque)+{+    rt->host_promise_rejection_tracker = cb;+    rt->host_promise_rejection_tracker_opaque = opaque;+}++static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise,+                                      JSValueConst value, BOOL is_reject)+{+    JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);+    struct list_head *el, *el1;+    JSPromiseReactionData *rd;+    JSValueConst args[5];++    if (!s || s->promise_state != JS_PROMISE_PENDING)+        return; /* should never happen */+    set_value(ctx, &s->promise_result, JS_DupValue(ctx, value));+    s->promise_state = JS_PROMISE_FULFILLED + is_reject;+#ifdef DUMP_PROMISE+    printf("fulfill_or_reject_promise: is_reject=%d\n", is_reject);+#endif+    if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {+        JSRuntime *rt = ctx->rt;+        if (rt->host_promise_rejection_tracker) {+            rt->host_promise_rejection_tracker(ctx, promise, value, FALSE,+                                               rt->host_promise_rejection_tracker_opaque);+        }+    }++    list_for_each_safe(el, el1, &s->promise_reactions[is_reject]) {+        rd = list_entry(el, JSPromiseReactionData, link);+        args[0] = rd->resolving_funcs[0];+        args[1] = rd->resolving_funcs[1];+        args[2] = rd->handler;+        args[3] = JS_NewBool(ctx, is_reject);+        args[4] = value;+        JS_EnqueueJob(ctx, promise_reaction_job, 5, args);+        list_del(&rd->link);+        promise_reaction_data_free(ctx->rt, rd);+    }++    list_for_each_safe(el, el1, &s->promise_reactions[1 - is_reject]) {+        rd = list_entry(el, JSPromiseReactionData, link);+        list_del(&rd->link);+        promise_reaction_data_free(ctx->rt, rd);+    }+}++static void reject_promise(JSContext *ctx, JSValueConst promise,+                           JSValueConst value)+{+    fulfill_or_reject_promise(ctx, promise, value, TRUE);+}++static JSValue js_promise_resolve_thenable_job(JSContext *ctx,+                                               int argc, JSValueConst *argv)+{+    JSValueConst promise, thenable, then;+    JSValue args[2], res;++#ifdef DUMP_PROMISE+    printf("js_promise_resolve_thenable_job\n");+#endif+    assert(argc == 3);+    promise = argv[0];+    thenable = argv[1];+    then = argv[2];+    if (js_create_resolving_functions(ctx, args, promise) < 0)+        return JS_EXCEPTION;+    res = JS_Call(ctx, then, thenable, 2, (JSValueConst *)args);+    if (JS_IsException(res)) {+        JSValue error = JS_GetException(ctx);+        res = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);+        JS_FreeValue(ctx, error);+    }+    JS_FreeValue(ctx, args[0]);+    JS_FreeValue(ctx, args[1]);+    return res;+}++static void js_promise_resolve_function_free_resolved(JSRuntime *rt,+                                                      JSPromiseFunctionDataResolved *sr)+{+    if (--sr->ref_count == 0) {+        js_free_rt(rt, sr);+    }+}++static int js_create_resolving_functions(JSContext *ctx,+                                         JSValue *resolving_funcs,+                                         JSValueConst promise)++{+    JSValue obj;+    JSPromiseFunctionData *s;+    JSPromiseFunctionDataResolved *sr;+    int i, ret;++    sr = js_malloc(ctx, sizeof(*sr));+    if (!sr)+        return -1;+    sr->ref_count = 1;+    sr->already_resolved = FALSE; /* must be shared between the two functions */+    ret = 0;+    for(i = 0; i < 2; i++) {+        obj = JS_NewObjectProtoClass(ctx, ctx->function_proto,+                                     JS_CLASS_PROMISE_RESOLVE_FUNCTION + i);+        if (JS_IsException(obj))+            goto fail;+        s = js_malloc(ctx, sizeof(*s));+        if (!s) {+            JS_FreeValue(ctx, obj);+        fail:++            if (i != 0)+                JS_FreeValue(ctx, resolving_funcs[0]);+            ret = -1;+            break;+        }+        sr->ref_count++;+        s->presolved = sr;+        s->promise = JS_DupValue(ctx, promise);+        JS_SetOpaque(obj, s);+        js_function_set_properties(ctx, obj, JS_ATOM_empty_string, 1);+        resolving_funcs[i] = obj;+    }+    js_promise_resolve_function_free_resolved(ctx->rt, sr);+    return ret;+}++static void js_promise_resolve_function_finalizer(JSRuntime *rt, JSValue val)+{+    JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data;+    if (s) {+        js_promise_resolve_function_free_resolved(rt, s->presolved);+        JS_FreeValueRT(rt, s->promise);+        js_free_rt(rt, s);+    }+}++static void js_promise_resolve_function_mark(JSRuntime *rt, JSValueConst val,+                                             JS_MarkFunc *mark_func)+{+    JSPromiseFunctionData *s = JS_VALUE_GET_OBJ(val)->u.promise_function_data;+    if (s) {+        JS_MarkValue(rt, s->promise, mark_func);+    }+}++static JSValue js_promise_resolve_function_call(JSContext *ctx,+                                                JSValueConst func_obj,+                                                JSValueConst this_val,+                                                int argc, JSValueConst *argv,+                                                int flags)+{+    JSObject *p = JS_VALUE_GET_OBJ(func_obj);+    JSPromiseFunctionData *s;+    JSValueConst resolution, args[3];+    JSValue then;+    BOOL is_reject;++    s = p->u.promise_function_data;+    if (!s || s->presolved->already_resolved)+        return JS_UNDEFINED;+    s->presolved->already_resolved = TRUE;+    is_reject = p->class_id - JS_CLASS_PROMISE_RESOLVE_FUNCTION;+    if (argc > 0)+        resolution = argv[0];+    else+        resolution = JS_UNDEFINED;+#ifdef DUMP_PROMISE+    printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject);+    JS_DumpValue(ctx, resolution);+    printf("\n");+#endif+    if (is_reject || !JS_IsObject(resolution)) {+        goto done;+    } else if (js_same_value(ctx, resolution, s->promise)) {+        JS_ThrowTypeError(ctx, "promise self resolution");+        goto fail_reject;+    }+    then = JS_GetProperty(ctx, resolution, JS_ATOM_then);+    if (JS_IsException(then)) {+        JSValue error;+    fail_reject:+        error = JS_GetException(ctx);+        reject_promise(ctx, s->promise, error);+        JS_FreeValue(ctx, error);+    } else if (!JS_IsFunction(ctx, then)) {+        JS_FreeValue(ctx, then);+    done:+        fulfill_or_reject_promise(ctx, s->promise, resolution, is_reject);+    } else {+        args[0] = s->promise;+        args[1] = resolution;+        args[2] = then;+        JS_EnqueueJob(ctx, js_promise_resolve_thenable_job, 3, args);+        JS_FreeValue(ctx, then);+    }+    return JS_UNDEFINED;+}++static void js_promise_finalizer(JSRuntime *rt, JSValue val)+{+    JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE);+    struct list_head *el, *el1;+    int i;++    if (!s)+        return;+    for(i = 0; i < 2; i++) {+        list_for_each_safe(el, el1, &s->promise_reactions[i]) {+            JSPromiseReactionData *rd =+                list_entry(el, JSPromiseReactionData, link);+            promise_reaction_data_free(rt, rd);+        }+    }+    JS_FreeValueRT(rt, s->promise_result);+    js_free_rt(rt, s);+}++static void js_promise_mark(JSRuntime *rt, JSValueConst val,+                            JS_MarkFunc *mark_func)+{+    JSPromiseData *s = JS_GetOpaque(val, JS_CLASS_PROMISE);+    struct list_head *el;+    int i;++    if (!s)+        return;+    for(i = 0; i < 2; i++) {+        list_for_each(el, &s->promise_reactions[i]) {+            JSPromiseReactionData *rd =+                list_entry(el, JSPromiseReactionData, link);+            JS_MarkValue(rt, rd->resolving_funcs[0], mark_func);+            JS_MarkValue(rt, rd->resolving_funcs[1], mark_func);+            JS_MarkValue(rt, rd->handler, mark_func);+        }+    }+    JS_MarkValue(rt, s->promise_result, mark_func);+}++static JSValue js_promise_constructor(JSContext *ctx, JSValueConst new_target,+                                      int argc, JSValueConst *argv)+{+    JSValueConst executor;+    JSValue obj;+    JSPromiseData *s;+    JSValue args[2], ret;+    int i;++    executor = argv[0];+    if (check_function(ctx, executor))+        return JS_EXCEPTION;+    obj = js_create_from_ctor(ctx, new_target, JS_CLASS_PROMISE);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    s = js_mallocz(ctx, sizeof(*s));+    if (!s)+        goto fail;+    s->promise_state = JS_PROMISE_PENDING;+    s->is_handled = FALSE;+    for(i = 0; i < 2; i++)+        init_list_head(&s->promise_reactions[i]);+    s->promise_result = JS_UNDEFINED;+    JS_SetOpaque(obj, s);+    if (js_create_resolving_functions(ctx, args, obj))+        goto fail;+    ret = JS_Call(ctx, executor, JS_UNDEFINED, 2, (JSValueConst *)args);+    if (JS_IsException(ret)) {+        JSValue ret2, error;+        error = JS_GetException(ctx);+        ret2 = JS_Call(ctx, args[1], JS_UNDEFINED, 1, (JSValueConst *)&error);+        JS_FreeValue(ctx, error);+        if (JS_IsException(ret2))+            goto fail1;+        JS_FreeValue(ctx, ret2);+    }+    JS_FreeValue(ctx, ret);+    JS_FreeValue(ctx, args[0]);+    JS_FreeValue(ctx, args[1]);+    return obj;+ fail1:+    JS_FreeValue(ctx, args[0]);+    JS_FreeValue(ctx, args[1]);+ fail:+    JS_FreeValue(ctx, obj);+    return JS_EXCEPTION;+}++static JSValue js_promise_executor(JSContext *ctx,+                                   JSValueConst this_val,+                                   int argc, JSValueConst *argv,+                                   int magic, JSValue *func_data)+{+    int i;++    for(i = 0; i < 2; i++) {+        if (!JS_IsUndefined(func_data[i]))+            return JS_ThrowTypeError(ctx, "resolving function already set");+        func_data[i] = JS_DupValue(ctx, argv[i]);+    }+    return JS_UNDEFINED;+}++static JSValue js_promise_executor_new(JSContext *ctx)+{+    JSValueConst func_data[2];++    func_data[0] = JS_UNDEFINED;+    func_data[1] = JS_UNDEFINED;+    return JS_NewCFunctionData(ctx, js_promise_executor, 2,+                               0, 2, func_data);+}++static JSValue js_new_promise_capability(JSContext *ctx,+                                         JSValue *resolving_funcs,+                                         JSValueConst ctor)+{+    JSValue executor, result_promise;+    JSCFunctionDataRecord *s;+    int i;++    executor = js_promise_executor_new(ctx);+    if (JS_IsException(executor))+        return executor;++    if (JS_IsUndefined(ctor)) {+        result_promise = js_promise_constructor(ctx, ctor, 1,+                                                (JSValueConst *)&executor);+    } else {+        result_promise = JS_CallConstructor(ctx, ctor, 1,+                                            (JSValueConst *)&executor);+    }+    if (JS_IsException(result_promise))+        goto fail;+    s = JS_GetOpaque(executor, JS_CLASS_C_FUNCTION_DATA);+    for(i = 0; i < 2; i++) {+        if (check_function(ctx, s->data[i]))+            goto fail;+    }+    for(i = 0; i < 2; i++)+        resolving_funcs[i] = JS_DupValue(ctx, s->data[i]);+    JS_FreeValue(ctx, executor);+    return result_promise;+ fail:+    JS_FreeValue(ctx, executor);+    JS_FreeValue(ctx, result_promise);+    return JS_EXCEPTION;+}++JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs)+{+    return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED);+}++static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv, int magic)+{+    JSValue result_promise, resolving_funcs[2], ret;+    BOOL is_reject = magic;++    if (!JS_IsObject(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    if (!is_reject && JS_GetOpaque(argv[0], JS_CLASS_PROMISE)) {+        JSValue ctor;+        BOOL is_same;+        ctor = JS_GetProperty(ctx, argv[0], JS_ATOM_constructor);+        if (JS_IsException(ctor))+            return ctor;+        is_same = js_same_value(ctx, ctor, this_val);+        JS_FreeValue(ctx, ctor);+        if (is_same)+            return JS_DupValue(ctx, argv[0]);+    }+    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);+    if (JS_IsException(result_promise))+        return result_promise;+    ret = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, argv);+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    if (JS_IsException(ret)) {+        JS_FreeValue(ctx, result_promise);+        return ret;+    }+    JS_FreeValue(ctx, ret);+    return result_promise;+}++#if 0+static JSValue js_promise___newPromiseCapability(JSContext *ctx,+                                                 JSValueConst this_val,+                                                 int argc, JSValueConst *argv)+{+    JSValue result_promise, resolving_funcs[2], obj;+    JSValueConst ctor;+    ctor = argv[0];+    if (!JS_IsObject(ctor))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);+    if (JS_IsException(result_promise))+        return result_promise;+    obj = JS_NewObject(ctx);+    if (JS_IsException(obj)) {+        JS_FreeValue(ctx, resolving_funcs[0]);+        JS_FreeValue(ctx, resolving_funcs[1]);+        JS_FreeValue(ctx, result_promise);+        return JS_EXCEPTION;+    }+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_promise, result_promise, JS_PROP_C_W_E);+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_resolve, resolving_funcs[0], JS_PROP_C_W_E);+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_reject, resolving_funcs[1], JS_PROP_C_W_E);+    return obj;+}+#endif++static __exception int remainingElementsCount_add(JSContext *ctx,+                                                  JSValueConst resolve_element_env,+                                                  int addend)+{+    JSValue val;+    int remainingElementsCount;++    val = JS_GetPropertyUint32(ctx, resolve_element_env, 0);+    if (JS_IsException(val))+        return -1;+    if (JS_ToInt32Free(ctx, &remainingElementsCount, val))+        return -1;+    remainingElementsCount += addend;+    if (JS_SetPropertyUint32(ctx, resolve_element_env, 0,+                             JS_NewInt32(ctx, remainingElementsCount)) < 0)+        return -1;+    return (remainingElementsCount == 0);+}++#define PROMISE_MAGIC_all        0+#define PROMISE_MAGIC_allSettled 1+#define PROMISE_MAGIC_any        2++static JSValue js_promise_all_resolve_element(JSContext *ctx,+                                              JSValueConst this_val,+                                              int argc, JSValueConst *argv,+                                              int magic,+                                              JSValue *func_data)+{+    int resolve_type = magic & 3;+    int is_reject = magic & 4;+    BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]);+    JSValueConst values = func_data[2];+    JSValueConst resolve = func_data[3];+    JSValueConst resolve_element_env = func_data[4];+    JSValue ret, obj;+    int is_zero, index;+    +    if (JS_ToInt32(ctx, &index, func_data[1]))+        return JS_EXCEPTION;+    if (alreadyCalled)+        return JS_UNDEFINED;+    func_data[0] = JS_NewBool(ctx, TRUE);++    if (resolve_type == PROMISE_MAGIC_allSettled) {+        JSValue str;+        +        obj = JS_NewObject(ctx);+        if (JS_IsException(obj))+            return JS_EXCEPTION;+        str = JS_NewString(ctx, is_reject ? "rejected" : "fulfilled");+        if (JS_IsException(str))+            goto fail1;+        if (JS_DefinePropertyValue(ctx, obj, JS_ATOM_status,+                                   str,+                                   JS_PROP_C_W_E) < 0)+            goto fail1;+        if (JS_DefinePropertyValue(ctx, obj,+                                   is_reject ? JS_ATOM_reason : JS_ATOM_value,+                                   JS_DupValue(ctx, argv[0]),+                                   JS_PROP_C_W_E) < 0) {+        fail1:+            JS_FreeValue(ctx, obj);+            return JS_EXCEPTION;+        }+    } else {+        obj = JS_DupValue(ctx, argv[0]);+    }+    if (JS_DefinePropertyValueUint32(ctx, values, index,+                                     obj, JS_PROP_C_W_E) < 0)+        return JS_EXCEPTION;+    +    is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1);+    if (is_zero < 0)+        return JS_EXCEPTION;+    if (is_zero) {+        if (resolve_type == PROMISE_MAGIC_any) {+            JSValue error;+            error = js_aggregate_error_constructor(ctx, values);+            if (JS_IsException(error))+                return JS_EXCEPTION;+            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);+            JS_FreeValue(ctx, error);+        } else {+            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);+        }+        if (JS_IsException(ret))+            return ret;+        JS_FreeValue(ctx, ret);+    }+    return JS_UNDEFINED;+}++/* magic = 0: Promise.all 1: Promise.allSettled */+static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    JSValue result_promise, resolving_funcs[2], item, next_promise, ret;+    JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED;+    JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;+    JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED;+    JSValueConst then_args[2], resolve_element_data[5];+    BOOL done;+    int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);+    +    if (!JS_IsObject(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);+    if (JS_IsException(result_promise))+        return result_promise;+    promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);+    if (JS_IsException(promise_resolve) ||+        check_function(ctx, promise_resolve))+        goto fail_reject;+    iter = JS_GetIterator(ctx, argv[0], FALSE);+    if (JS_IsException(iter)) {+        JSValue error;+    fail_reject:+        error = JS_GetException(ctx);+        ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,+                       (JSValueConst *)&error);+        JS_FreeValue(ctx, error);+        if (JS_IsException(ret))+            goto fail;+        JS_FreeValue(ctx, ret);+    } else {+        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);+        if (JS_IsException(next_method))+            goto fail_reject;+        values = JS_NewArray(ctx);+        if (JS_IsException(values))+            goto fail_reject;+        resolve_element_env = JS_NewArray(ctx);+        if (JS_IsException(resolve_element_env))+            goto fail_reject;+        /* remainingElementsCount field */+        if (JS_DefinePropertyValueUint32(ctx, resolve_element_env, 0,+                                         JS_NewInt32(ctx, 1),+                                         JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)+            goto fail_reject;+        +        index = 0;+        for(;;) {+            /* XXX: conformance: should close the iterator if error on 'done'+               access, but not on 'value' access */+            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);+            if (JS_IsException(item))+                goto fail_reject;+            if (done)+                break;+            next_promise = JS_Call(ctx, promise_resolve, +                                   this_val, 1, (JSValueConst *)&item);+            JS_FreeValue(ctx, item);+            if (JS_IsException(next_promise)) {+            fail_reject1:+                JS_IteratorClose(ctx, iter, TRUE);+                goto fail_reject;+            }+            resolve_element_data[0] = JS_NewBool(ctx, FALSE);+            resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);+            resolve_element_data[2] = values;+            resolve_element_data[3] = resolving_funcs[is_promise_any];+            resolve_element_data[4] = resolve_element_env;+            resolve_element =+                JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,+                                    magic, 5, resolve_element_data);+            if (JS_IsException(resolve_element)) {+                JS_FreeValue(ctx, next_promise);+                goto fail_reject1;+            }+            +            if (magic == PROMISE_MAGIC_allSettled) {+                reject_element =+                    JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,+                                        magic | 4, 5, resolve_element_data);+                if (JS_IsException(reject_element)) {+                    JS_FreeValue(ctx, next_promise);+                    goto fail_reject1;+                }+            } else if (magic == PROMISE_MAGIC_any) {+                if (JS_DefinePropertyValueUint32(ctx, values, index,+                                                 JS_UNDEFINED, JS_PROP_C_W_E) < 0)+                    goto fail_reject1;+                reject_element = resolve_element;+                resolve_element = JS_DupValue(ctx, resolving_funcs[0]);+            } else {+                reject_element = JS_DupValue(ctx, resolving_funcs[1]);+            }++            if (remainingElementsCount_add(ctx, resolve_element_env, 1) < 0) {+                JS_FreeValue(ctx, next_promise);+                JS_FreeValue(ctx, resolve_element);+                JS_FreeValue(ctx, reject_element);+                goto fail_reject1;+            }++            then_args[0] = resolve_element;+            then_args[1] = reject_element;+            ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2, then_args);+            JS_FreeValue(ctx, resolve_element);+            JS_FreeValue(ctx, reject_element);+            if (check_exception_free(ctx, ret))+                goto fail_reject1;+            index++;+        }++        is_zero = remainingElementsCount_add(ctx, resolve_element_env, -1);+        if (is_zero < 0)+            goto fail_reject;+        if (is_zero) {+            if (magic == PROMISE_MAGIC_any) {+                JSValue error;+                error = js_aggregate_error_constructor(ctx, values);+                if (JS_IsException(error))+                    goto fail_reject;+                JS_FreeValue(ctx, values);+                values = error;+            }+            ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,+                          1, (JSValueConst *)&values);+            if (check_exception_free(ctx, ret))+                goto fail_reject;+        }+    }+ done:+    JS_FreeValue(ctx, promise_resolve);+    JS_FreeValue(ctx, resolve_element_env);+    JS_FreeValue(ctx, values);+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    return result_promise;+ fail:+    JS_FreeValue(ctx, result_promise);+    result_promise = JS_EXCEPTION;+    goto done;+}++static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    JSValue result_promise, resolving_funcs[2], item, next_promise, ret;+    JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED;+    JSValue promise_resolve = JS_UNDEFINED;+    BOOL done;++    if (!JS_IsObject(this_val))+        return JS_ThrowTypeErrorNotAnObject(ctx);+    result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);+    if (JS_IsException(result_promise))+        return result_promise;+    promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve);+    if (JS_IsException(promise_resolve) ||+        check_function(ctx, promise_resolve))+        goto fail_reject;+    iter = JS_GetIterator(ctx, argv[0], FALSE);+    if (JS_IsException(iter)) {+        JSValue error;+    fail_reject:+        error = JS_GetException(ctx);+        ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1,+                       (JSValueConst *)&error);+        JS_FreeValue(ctx, error);+        if (JS_IsException(ret))+            goto fail;+        JS_FreeValue(ctx, ret);+    } else {+        next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);+        if (JS_IsException(next_method))+            goto fail_reject;++        for(;;) {+            /* XXX: conformance: should close the iterator if error on 'done'+               access, but not on 'value' access */+            item = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);+            if (JS_IsException(item))+                goto fail_reject;+            if (done)+                break;+            next_promise = JS_Call(ctx, promise_resolve,+                                   this_val, 1, (JSValueConst *)&item);+            JS_FreeValue(ctx, item);+            if (JS_IsException(next_promise)) {+            fail_reject1:+                JS_IteratorClose(ctx, iter, TRUE);+                goto fail_reject;+            }+            ret = JS_InvokeFree(ctx, next_promise, JS_ATOM_then, 2,+                                (JSValueConst *)resolving_funcs);+            if (check_exception_free(ctx, ret))+                goto fail_reject1;+        }+    }+ done:+    JS_FreeValue(ctx, promise_resolve);+    JS_FreeValue(ctx, next_method);+    JS_FreeValue(ctx, iter);+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    return result_promise;+ fail:+    //JS_FreeValue(ctx, next_method); // why not???+    JS_FreeValue(ctx, result_promise);+    result_promise = JS_EXCEPTION;+    goto done;+}++static __exception int perform_promise_then(JSContext *ctx,+                                            JSValueConst promise,+                                            JSValueConst *resolve_reject,+                                            JSValueConst *cap_resolving_funcs)+{+    JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE);+    JSPromiseReactionData *rd_array[2], *rd;+    int i, j;++    rd_array[0] = NULL;+    rd_array[1] = NULL;+    for(i = 0; i < 2; i++) {+        JSValueConst handler;+        rd = js_mallocz(ctx, sizeof(*rd));+        if (!rd) {+            if (i == 1)+                promise_reaction_data_free(ctx->rt, rd_array[0]);+            return -1;+        }+        for(j = 0; j < 2; j++)+            rd->resolving_funcs[j] = JS_DupValue(ctx, cap_resolving_funcs[j]);+        handler = resolve_reject[i];+        if (!JS_IsFunction(ctx, handler))+            handler = JS_UNDEFINED;+        rd->handler = JS_DupValue(ctx, handler);+        rd_array[i] = rd;+    }++    if (s->promise_state == JS_PROMISE_PENDING) {+        for(i = 0; i < 2; i++)+            list_add_tail(&rd_array[i]->link, &s->promise_reactions[i]);+    } else {+        JSValueConst args[5];+        if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) {+            JSRuntime *rt = ctx->rt;+            if (rt->host_promise_rejection_tracker) {+                rt->host_promise_rejection_tracker(ctx, promise, s->promise_result,+                                                   TRUE, rt->host_promise_rejection_tracker_opaque);+            }+        }+        i = s->promise_state - JS_PROMISE_FULFILLED;+        rd = rd_array[i];+        args[0] = rd->resolving_funcs[0];+        args[1] = rd->resolving_funcs[1];+        args[2] = rd->handler;+        args[3] = JS_NewBool(ctx, i);+        args[4] = s->promise_result;+        JS_EnqueueJob(ctx, promise_reaction_job, 5, args);+        for(i = 0; i < 2; i++)+            promise_reaction_data_free(ctx->rt, rd_array[i]);+    }+    s->is_handled = TRUE;+    return 0;+}++static JSValue js_promise_then(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    JSValue ctor, result_promise, resolving_funcs[2];+    JSPromiseData *s;+    int i, ret;++    s = JS_GetOpaque2(ctx, this_val, JS_CLASS_PROMISE);+    if (!s)+        return JS_EXCEPTION;++    ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);+    if (JS_IsException(ctor))+        return ctor;+    result_promise = js_new_promise_capability(ctx, resolving_funcs, ctor);+    JS_FreeValue(ctx, ctor);+    if (JS_IsException(result_promise))+        return result_promise;+    ret = perform_promise_then(ctx, this_val, argv,+                               (JSValueConst *)resolving_funcs);+    for(i = 0; i < 2; i++)+        JS_FreeValue(ctx, resolving_funcs[i]);+    if (ret) {+        JS_FreeValue(ctx, result_promise);+        return JS_EXCEPTION;+    }+    return result_promise;+}++static JSValue js_promise_catch(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValueConst args[2];+    args[0] = JS_UNDEFINED;+    args[1] = argv[0];+    return JS_Invoke(ctx, this_val, JS_ATOM_then, 2, args);+}++static JSValue js_promise_finally_value_thunk(JSContext *ctx, JSValueConst this_val,+                                              int argc, JSValueConst *argv,+                                              int magic, JSValue *func_data)+{+    return JS_DupValue(ctx, func_data[0]);+}++static JSValue js_promise_finally_thrower(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv,+                                          int magic, JSValue *func_data)+{+    return JS_Throw(ctx, JS_DupValue(ctx, func_data[0]));+}++static JSValue js_promise_then_finally_func(JSContext *ctx, JSValueConst this_val,+                                            int argc, JSValueConst *argv,+                                            int magic, JSValue *func_data)+{+    JSValueConst ctor = func_data[0];+    JSValueConst onFinally = func_data[1];+    JSValue res, promise, ret, then_func;++    res = JS_Call(ctx, onFinally, JS_UNDEFINED, 0, NULL);+    if (JS_IsException(res))+        return res;+    promise = js_promise_resolve(ctx, ctor, 1, (JSValueConst *)&res, 0);+    JS_FreeValue(ctx, res);+    if (JS_IsException(promise))+        return promise;+    if (magic == 0) {+        then_func = JS_NewCFunctionData(ctx, js_promise_finally_value_thunk, 0,+                                        0, 1, argv);+    } else {+        then_func = JS_NewCFunctionData(ctx, js_promise_finally_thrower, 0,+                                        0, 1, argv);+    }+    if (JS_IsException(then_func)) {+        JS_FreeValue(ctx, promise);+        return then_func;+    }+    ret = JS_InvokeFree(ctx, promise, JS_ATOM_then, 1, (JSValueConst *)&then_func);+    JS_FreeValue(ctx, then_func);+    return ret;+}++static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValueConst onFinally = argv[0];+    JSValue ctor, ret;+    JSValue then_funcs[2];+    JSValueConst func_data[2];+    int i;++    ctor = JS_SpeciesConstructor(ctx, this_val, JS_UNDEFINED);+    if (JS_IsException(ctor))+        return ctor;+    if (!JS_IsFunction(ctx, onFinally)) {+        then_funcs[0] = JS_DupValue(ctx, onFinally);+        then_funcs[1] = JS_DupValue(ctx, onFinally);+    } else {+        func_data[0] = ctor;+        func_data[1] = onFinally;+        for(i = 0; i < 2; i++) {+            then_funcs[i] = JS_NewCFunctionData(ctx, js_promise_then_finally_func, 1, i, 2, func_data);+            if (JS_IsException(then_funcs[i])) {+                if (i == 1)+                    JS_FreeValue(ctx, then_funcs[0]);+                JS_FreeValue(ctx, ctor);+                return JS_EXCEPTION;+            }+        }+    }+    JS_FreeValue(ctx, ctor);+    ret = JS_Invoke(ctx, this_val, JS_ATOM_then, 2, (JSValueConst *)then_funcs);+    JS_FreeValue(ctx, then_funcs[0]);+    JS_FreeValue(ctx, then_funcs[1]);+    return ret;+}++static const JSCFunctionListEntry js_promise_funcs[] = {+    JS_CFUNC_MAGIC_DEF("resolve", 1, js_promise_resolve, 0 ),+    JS_CFUNC_MAGIC_DEF("reject", 1, js_promise_resolve, 1 ),+    JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ),+    JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),+    JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),+    JS_CFUNC_DEF("race", 1, js_promise_race ),+    //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ),+    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),+};++static const JSCFunctionListEntry js_promise_proto_funcs[] = {+    JS_CFUNC_DEF("then", 2, js_promise_then ),+    JS_CFUNC_DEF("catch", 1, js_promise_catch ),+    JS_CFUNC_DEF("finally", 1, js_promise_finally ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Promise", JS_PROP_CONFIGURABLE ),+};++/* AsyncFunction */+static const JSCFunctionListEntry js_async_function_proto_funcs[] = {+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncFunction", JS_PROP_CONFIGURABLE ),+};++static JSValue js_async_from_sync_iterator_unwrap(JSContext *ctx,+                                                  JSValueConst this_val,+                                                  int argc, JSValueConst *argv,+                                                  int magic, JSValue *func_data)+{+    return js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]),+                                     JS_ToBool(ctx, func_data[0]));+}++static JSValue js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,+                                                              BOOL done)+{+    JSValueConst func_data[1];++    func_data[0] = (JSValueConst)JS_NewBool(ctx, done);+    return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,+                               1, 0, 1, func_data);+}++/* AsyncIteratorPrototype */++static const JSCFunctionListEntry js_async_iterator_proto_funcs[] = {+    JS_CFUNC_DEF("[Symbol.asyncIterator]", 0, js_iterator_proto_iterator ),+};++/* AsyncFromSyncIteratorPrototype */++typedef struct JSAsyncFromSyncIteratorData {+    JSValue sync_iter;+    JSValue next_method;+} JSAsyncFromSyncIteratorData;++static void js_async_from_sync_iterator_finalizer(JSRuntime *rt, JSValue val)+{+    JSAsyncFromSyncIteratorData *s =+        JS_GetOpaque(val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);+    if (s) {+        JS_FreeValueRT(rt, s->sync_iter);+        JS_FreeValueRT(rt, s->next_method);+        js_free_rt(rt, s);+    }+}++static void js_async_from_sync_iterator_mark(JSRuntime *rt, JSValueConst val,+                                             JS_MarkFunc *mark_func)+{+    JSAsyncFromSyncIteratorData *s =+        JS_GetOpaque(val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);+    if (s) {+        JS_MarkValue(rt, s->sync_iter, mark_func);+        JS_MarkValue(rt, s->next_method, mark_func);+    }+}++static JSValue JS_CreateAsyncFromSyncIterator(JSContext *ctx,+                                              JSValueConst sync_iter)+{+    JSValue async_iter, next_method;+    JSAsyncFromSyncIteratorData *s;++    next_method = JS_GetProperty(ctx, sync_iter, JS_ATOM_next);+    if (JS_IsException(next_method))+        return JS_EXCEPTION;+    async_iter = JS_NewObjectClass(ctx, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);+    if (JS_IsException(async_iter)) {+        JS_FreeValue(ctx, next_method);+        return async_iter;+    }+    s = js_mallocz(ctx, sizeof(*s));+    if (!s) {+        JS_FreeValue(ctx, async_iter);+        JS_FreeValue(ctx, next_method);+        return JS_EXCEPTION;+    }+    s->sync_iter = JS_DupValue(ctx, sync_iter);+    s->next_method = next_method;+    JS_SetOpaque(async_iter, s);+    return async_iter;+}++static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst this_val,+                                                int argc, JSValueConst *argv,+                                                int magic)+{+    JSValue promise, resolving_funcs[2], value, err, method;+    JSAsyncFromSyncIteratorData *s;+    int done;+    int is_reject;++    promise = JS_NewPromiseCapability(ctx, resolving_funcs);+    if (JS_IsException(promise))+        return JS_EXCEPTION;+    s = JS_GetOpaque(this_val, JS_CLASS_ASYNC_FROM_SYNC_ITERATOR);+    if (!s) {+        JS_ThrowTypeError(ctx, "not an Async-from-Sync Iterator");+        goto reject;+    }++    if (magic == GEN_MAGIC_NEXT) {+        method = JS_DupValue(ctx, s->next_method);+    } else {+        method = JS_GetProperty(ctx, s->sync_iter,+                                magic == GEN_MAGIC_RETURN ? JS_ATOM_return :+                                JS_ATOM_throw);+        if (JS_IsException(method))+            goto reject;+        if (JS_IsUndefined(method) || JS_IsNull(method)) {+            if (magic == GEN_MAGIC_RETURN) {+                err = js_create_iterator_result(ctx, JS_DupValue(ctx, argv[0]), TRUE);+                is_reject = 0;+            } else {+                err = JS_DupValue(ctx, argv[0]);+                is_reject = 1;+            }+            goto done_resolve;+        }+    }+    value = JS_IteratorNext2(ctx, s->sync_iter, method,+                             argc >= 1 ? 1 : 0, argv, &done);+    JS_FreeValue(ctx, method);+    if (JS_IsException(value))+        goto reject;+    if (done == 2) {+        JSValue obj = value;+        value = JS_IteratorGetCompleteValue(ctx, obj, &done);+        JS_FreeValue(ctx, obj);+        if (JS_IsException(value))+            goto reject;+    }++    if (JS_IsException(value)) {+        JSValue res2;+    reject:+        err = JS_GetException(ctx);+        is_reject = 1;+    done_resolve:+        res2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED,+                       1, (JSValueConst *)&err);+        JS_FreeValue(ctx, err);+        JS_FreeValue(ctx, res2);+        JS_FreeValue(ctx, resolving_funcs[0]);+        JS_FreeValue(ctx, resolving_funcs[1]);+        return promise;+    }+    {+        JSValue value_wrapper_promise, resolve_reject[2];+        int res;++        value_wrapper_promise = js_promise_resolve(ctx, ctx->promise_ctor,+                                                   1, (JSValueConst *)&value, 0);+        if (JS_IsException(value_wrapper_promise)) {+            JS_FreeValue(ctx, value);+            goto reject;+        }++        resolve_reject[0] =+            js_async_from_sync_iterator_unwrap_func_create(ctx, done);+        if (JS_IsException(resolve_reject[0])) {+            JS_FreeValue(ctx, value_wrapper_promise);+            goto fail;+        }+        JS_FreeValue(ctx, value);+        resolve_reject[1] = JS_UNDEFINED;++        res = perform_promise_then(ctx, value_wrapper_promise,+                                   (JSValueConst *)resolve_reject,+                                   (JSValueConst *)resolving_funcs);+        JS_FreeValue(ctx, resolve_reject[0]);+        JS_FreeValue(ctx, value_wrapper_promise);+        JS_FreeValue(ctx, resolving_funcs[0]);+        JS_FreeValue(ctx, resolving_funcs[1]);+        if (res) {+            JS_FreeValue(ctx, promise);+            return JS_EXCEPTION;+        }+    }+    return promise;+ fail:+    JS_FreeValue(ctx, value);+    JS_FreeValue(ctx, resolving_funcs[0]);+    JS_FreeValue(ctx, resolving_funcs[1]);+    JS_FreeValue(ctx, promise);+    return JS_EXCEPTION;+}++static const JSCFunctionListEntry js_async_from_sync_iterator_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("next", 1, js_async_from_sync_iterator_next, GEN_MAGIC_NEXT ),+    JS_CFUNC_MAGIC_DEF("return", 1, js_async_from_sync_iterator_next, GEN_MAGIC_RETURN ),+    JS_CFUNC_MAGIC_DEF("throw", 1, js_async_from_sync_iterator_next, GEN_MAGIC_THROW ),+};++/* AsyncGeneratorFunction */++static const JSCFunctionListEntry js_async_generator_function_proto_funcs[] = {+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncGeneratorFunction", JS_PROP_CONFIGURABLE ),+};++/* AsyncGenerator prototype */++static const JSCFunctionListEntry js_async_generator_proto_funcs[] = {+    JS_CFUNC_MAGIC_DEF("next", 1, js_async_generator_next, GEN_MAGIC_NEXT ),+    JS_CFUNC_MAGIC_DEF("return", 1, js_async_generator_next, GEN_MAGIC_RETURN ),+    JS_CFUNC_MAGIC_DEF("throw", 1, js_async_generator_next, GEN_MAGIC_THROW ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "AsyncGenerator", JS_PROP_CONFIGURABLE ),+};++static JSClassShortDef const js_async_class_def[] = {+    { JS_ATOM_Promise, js_promise_finalizer, js_promise_mark },                      /* JS_CLASS_PROMISE */+    { JS_ATOM_PromiseResolveFunction, js_promise_resolve_function_finalizer, js_promise_resolve_function_mark }, /* JS_CLASS_PROMISE_RESOLVE_FUNCTION */+    { JS_ATOM_PromiseRejectFunction, js_promise_resolve_function_finalizer, js_promise_resolve_function_mark }, /* JS_CLASS_PROMISE_REJECT_FUNCTION */+    { JS_ATOM_AsyncFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_ASYNC_FUNCTION */+    { JS_ATOM_AsyncFunctionResolve, js_async_function_resolve_finalizer, js_async_function_resolve_mark }, /* JS_CLASS_ASYNC_FUNCTION_RESOLVE */+    { JS_ATOM_AsyncFunctionReject, js_async_function_resolve_finalizer, js_async_function_resolve_mark }, /* JS_CLASS_ASYNC_FUNCTION_REJECT */+    { JS_ATOM_empty_string, js_async_from_sync_iterator_finalizer, js_async_from_sync_iterator_mark }, /* JS_CLASS_ASYNC_FROM_SYNC_ITERATOR */+    { JS_ATOM_AsyncGeneratorFunction, js_bytecode_function_finalizer, js_bytecode_function_mark },  /* JS_CLASS_ASYNC_GENERATOR_FUNCTION */+    { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark },  /* JS_CLASS_ASYNC_GENERATOR */+};++void JS_AddIntrinsicPromise(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    JSValue obj1;++    if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) {+        init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE,+                         countof(js_async_class_def));+        rt->class_array[JS_CLASS_PROMISE_RESOLVE_FUNCTION].call = js_promise_resolve_function_call;+        rt->class_array[JS_CLASS_PROMISE_REJECT_FUNCTION].call = js_promise_resolve_function_call;+        rt->class_array[JS_CLASS_ASYNC_FUNCTION].call = js_async_function_call;+        rt->class_array[JS_CLASS_ASYNC_FUNCTION_RESOLVE].call = js_async_function_resolve_call;+        rt->class_array[JS_CLASS_ASYNC_FUNCTION_REJECT].call = js_async_function_resolve_call;+        rt->class_array[JS_CLASS_ASYNC_GENERATOR_FUNCTION].call = js_async_generator_function_call;+    }++    /* Promise */+    ctx->class_proto[JS_CLASS_PROMISE] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_PROMISE],+                               js_promise_proto_funcs,+                               countof(js_promise_proto_funcs));+    obj1 = JS_NewCFunction2(ctx, js_promise_constructor, "Promise", 1,+                            JS_CFUNC_constructor, 0);+    ctx->promise_ctor = JS_DupValue(ctx, obj1);+    JS_SetPropertyFunctionList(ctx, obj1,+                               js_promise_funcs,+                               countof(js_promise_funcs));+    JS_NewGlobalCConstructor2(ctx, obj1, "Promise",+                              ctx->class_proto[JS_CLASS_PROMISE]);++    /* AsyncFunction */+    ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);+    obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,+                            "AsyncFunction", 1,+                            JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC,+                            ctx->function_ctor);+    JS_SetPropertyFunctionList(ctx,+                               ctx->class_proto[JS_CLASS_ASYNC_FUNCTION],+                               js_async_function_proto_funcs,+                               countof(js_async_function_proto_funcs));+    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_FUNCTION],+                       0, JS_PROP_CONFIGURABLE);+    JS_FreeValue(ctx, obj1);++    /* AsyncIteratorPrototype */+    ctx->async_iterator_proto = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->async_iterator_proto,+                               js_async_iterator_proto_funcs,+                               countof(js_async_iterator_proto_funcs));++    /* AsyncFromSyncIteratorPrototype */+    ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR] =+        JS_NewObjectProto(ctx, ctx->async_iterator_proto);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ASYNC_FROM_SYNC_ITERATOR],+                               js_async_from_sync_iterator_proto_funcs,+                               countof(js_async_from_sync_iterator_proto_funcs));++    /* AsyncGeneratorPrototype */+    ctx->class_proto[JS_CLASS_ASYNC_GENERATOR] =+        JS_NewObjectProto(ctx, ctx->async_iterator_proto);+    JS_SetPropertyFunctionList(ctx,+                               ctx->class_proto[JS_CLASS_ASYNC_GENERATOR],+                               js_async_generator_proto_funcs,+                               countof(js_async_generator_proto_funcs));++    /* AsyncGeneratorFunction */+    ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] =+        JS_NewObjectProto(ctx, ctx->function_proto);+    obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,+                            "AsyncGeneratorFunction", 1,+                            JS_CFUNC_constructor_or_func_magic,+                            JS_FUNC_ASYNC_GENERATOR,+                            ctx->function_ctor);+    JS_SetPropertyFunctionList(ctx,+                               ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],+                               js_async_generator_function_proto_funcs,+                               countof(js_async_generator_function_proto_funcs));+    JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],+                       ctx->class_proto[JS_CLASS_ASYNC_GENERATOR],+                       JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE);+    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION],+                       0, JS_PROP_CONFIGURABLE);+    JS_FreeValue(ctx, obj1);+}++/* URI handling */++static int string_get_hex(JSString *p, int k, int n) {+    int c = 0, h;+    while (n-- > 0) {+        if ((h = from_hex(string_get(p, k++))) < 0)+            return -1;+        c = (c << 4) | h;+    }+    return c;+}++static int isURIReserved(int c) {+    return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) != NULL;+}++static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext *ctx, const char *fmt, ...)+{+    va_list ap;++    va_start(ap, fmt);+    JS_ThrowError(ctx, JS_URI_ERROR, fmt, ap);+    va_end(ap);+    return -1;+}++static int hex_decode(JSContext *ctx, JSString *p, int k) {+    int c;++    if (k >= p->len || string_get(p, k) != '%')+        return js_throw_URIError(ctx, "expecting %%");+    if (k + 2 >= p->len || (c = string_get_hex(p, k + 1, 2)) < 0)+        return js_throw_URIError(ctx, "expecting hex digit");++    return c;+}++static JSValue js_global_decodeURI(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv, int isComponent)+{+    JSValue str;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int k, c, c1, n, c_min;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return str;++    string_buffer_init(ctx, b, 0);++    p = JS_VALUE_GET_STRING(str);+    for (k = 0; k < p->len;) {+        c = string_get(p, k);+        if (c == '%') {+            c = hex_decode(ctx, p, k);+            if (c < 0)+                goto fail;+            k += 3;+            if (c < 0x80) {+                if (!isComponent && isURIReserved(c)) {+                    c = '%';+                    k -= 2;+                }+            } else {+                /* Decode URI-encoded UTF-8 sequence */+                if (c >= 0xc0 && c <= 0xdf) {+                    n = 1;+                    c_min = 0x80;+                    c &= 0x1f;+                } else if (c >= 0xe0 && c <= 0xef) {+                    n = 2;+                    c_min = 0x800;+                    c &= 0xf;+                } else if (c >= 0xf0 && c <= 0xf7) {+                    n = 3;+                    c_min = 0x10000;+                    c &= 0x7;+                } else {+                    n = 0;+                    c_min = 1;+                    c = 0;+                }+                while (n-- > 0) {+                    c1 = hex_decode(ctx, p, k);+                    if (c1 < 0)+                        goto fail;+                    k += 3;+                    if ((c1 & 0xc0) != 0x80) {+                        c = 0;+                        break;+                    }+                    c = (c << 6) | (c1 & 0x3f);+                }+                if (c < c_min || c > 0x10FFFF ||+                    (c >= 0xd800 && c < 0xe000)) {+                    js_throw_URIError(ctx, "malformed UTF-8");+                    goto fail;+                }+            }+        } else {+            k++;+        }+        string_buffer_putc(b, c);+    }+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);++fail:+    JS_FreeValue(ctx, str);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static int isUnescaped(int c) {+    static char const unescaped_chars[] =+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+        "abcdefghijklmnopqrstuvwxyz"+        "0123456789"+        "@*_+-./";+    return c < 0x100 &&+        memchr(unescaped_chars, c, sizeof(unescaped_chars) - 1);+}++static int isURIUnescaped(int c, int isComponent) {+    return c < 0x100 &&+        ((c >= 0x61 && c <= 0x7a) ||+         (c >= 0x41 && c <= 0x5a) ||+         (c >= 0x30 && c <= 0x39) ||+         memchr("-_.!~*'()", c, sizeof("-_.!~*'()") - 1) != NULL ||+         (!isComponent && isURIReserved(c)));+}++static int encodeURI_hex(StringBuffer *b, int c) {+    uint8_t buf[6];+    int n = 0;+    const char *hex = "0123456789ABCDEF";++    buf[n++] = '%';+    if (c >= 256) {+        buf[n++] = 'u';+        buf[n++] = hex[(c >> 12) & 15];+        buf[n++] = hex[(c >>  8) & 15];+    }+    buf[n++] = hex[(c >> 4) & 15];+    buf[n++] = hex[(c >> 0) & 15];+    return string_buffer_write8(b, buf, n);+}++static JSValue js_global_encodeURI(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv,+                                   int isComponent)+{+    JSValue str;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int k, c, c1;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return str;++    p = JS_VALUE_GET_STRING(str);+    string_buffer_init(ctx, b, p->len);+    for (k = 0; k < p->len;) {+        c = string_get(p, k);+        k++;+        if (isURIUnescaped(c, isComponent)) {+            string_buffer_putc16(b, c);+        } else {+            if (c >= 0xdc00 && c <= 0xdfff) {+                js_throw_URIError(ctx, "invalid character");+                goto fail;+            } else if (c >= 0xd800 && c <= 0xdbff) {+                if (k >= p->len) {+                    js_throw_URIError(ctx, "expecting surrogate pair");+                    goto fail;+                }+                c1 = string_get(p, k);+                k++;+                if (c1 < 0xdc00 || c1 > 0xdfff) {+                    js_throw_URIError(ctx, "expecting surrogate pair");+                    goto fail;+                }+                c = (((c & 0x3ff) << 10) | (c1 & 0x3ff)) + 0x10000;+            }+            if (c < 0x80) {+                encodeURI_hex(b, c);+            } else {+                /* XXX: use C UTF-8 conversion ? */+                if (c < 0x800) {+                    encodeURI_hex(b, (c >> 6) | 0xc0);+                } else {+                    if (c < 0x10000) {+                        encodeURI_hex(b, (c >> 12) | 0xe0);+                    } else {+                        encodeURI_hex(b, (c >> 18) | 0xf0);+                        encodeURI_hex(b, ((c >> 12) & 0x3f) | 0x80);+                    }+                    encodeURI_hex(b, ((c >> 6) & 0x3f) | 0x80);+                }+                encodeURI_hex(b, (c & 0x3f) | 0x80);+            }+        }+    }+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);++fail:+    JS_FreeValue(ctx, str);+    string_buffer_free(b);+    return JS_EXCEPTION;+}++static JSValue js_global_escape(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    JSValue str;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int i, len, c;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return str;++    p = JS_VALUE_GET_STRING(str);+    string_buffer_init(ctx, b, p->len);+    for (i = 0, len = p->len; i < len; i++) {+        c = string_get(p, i);+        if (isUnescaped(c)) {+            string_buffer_putc16(b, c);+        } else {+            encodeURI_hex(b, c);+        }+    }+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);+}++static JSValue js_global_unescape(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValue str;+    StringBuffer b_s, *b = &b_s;+    JSString *p;+    int i, len, c, n;++    str = JS_ToString(ctx, argv[0]);+    if (JS_IsException(str))+        return str;++    string_buffer_init(ctx, b, 0);+    p = JS_VALUE_GET_STRING(str);+    for (i = 0, len = p->len; i < len; i++) {+        c = string_get(p, i);+        if (c == '%') {+            if (i + 6 <= len+            &&  string_get(p, i + 1) == 'u'+            &&  (n = string_get_hex(p, i + 2, 4)) >= 0) {+                c = n;+                i += 6 - 1;+            } else+            if (i + 3 <= len+            &&  (n = string_get_hex(p, i + 1, 2)) >= 0) {+                c = n;+                i += 3 - 1;+            }+        }+        string_buffer_putc16(b, c);+    }+    JS_FreeValue(ctx, str);+    return string_buffer_end(b);+}++/* global object */++static const JSCFunctionListEntry js_global_funcs[] = {+    JS_CFUNC_DEF("parseInt", 2, js_parseInt ),+    JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ),+    JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ),+    JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ),++    JS_CFUNC_MAGIC_DEF("decodeURI", 1, js_global_decodeURI, 0 ),+    JS_CFUNC_MAGIC_DEF("decodeURIComponent", 1, js_global_decodeURI, 1 ),+    JS_CFUNC_MAGIC_DEF("encodeURI", 1, js_global_encodeURI, 0 ),+    JS_CFUNC_MAGIC_DEF("encodeURIComponent", 1, js_global_encodeURI, 1 ),+    JS_CFUNC_DEF("escape", 1, js_global_escape ),+    JS_CFUNC_DEF("unescape", 1, js_global_unescape ),+    JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),+    JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),+    JS_PROP_UNDEFINED_DEF("undefined", 0 ),++    /* for the 'Date' implementation */+    JS_CFUNC_DEF("__date_clock", 0, js___date_clock ),+    //JS_CFUNC_DEF("__date_now", 0, js___date_now ),+    //JS_CFUNC_DEF("__date_getTimezoneOffset", 1, js___date_getTimezoneOffset ),+    //JS_CFUNC_DEF("__date_create", 3, js___date_create ),+};++/* Date */++static int64_t math_mod(int64_t a, int64_t b) {+    /* return positive modulo */+    int64_t m = a % b;+    return m + (m < 0) * b;+}++static int64_t floor_div(int64_t a, int64_t b) {+    /* integer division rounding toward -Infinity */+    int64_t m = a % b;+    return (a - (m + (m < 0) * b)) / b;+}++static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv);++static __exception int JS_ThisTimeValue(JSContext *ctx, double *valp, JSValueConst this_val)+{+    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_DATE && JS_IsNumber(p->u.object_data))+            return JS_ToFloat64(ctx, valp, p->u.object_data);+    }+    JS_ThrowTypeError(ctx, "not a Date object");+    return -1;+}++static JSValue JS_SetThisTimeValue(JSContext *ctx, JSValueConst this_val, double v)+{+    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_DATE) {+            JS_FreeValue(ctx, p->u.object_data);+            p->u.object_data = JS_NewFloat64(ctx, v);+            return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a Date object");+}++static int64_t days_from_year(int64_t y) {+    return 365 * (y - 1970) + floor_div(y - 1969, 4) -+        floor_div(y - 1901, 100) + floor_div(y - 1601, 400);+}++static int64_t days_in_year(int64_t y) {+    return 365 + !(y % 4) - !(y % 100) + !(y % 400);+}++/* return the year, update days */+static int64_t year_from_days(int64_t *days) {+    int64_t y, d1, nd, d = *days;+    y = floor_div(d * 10000, 3652425) + 1970;+    /* the initial approximation is very good, so only a few+       iterations are necessary */+    for(;;) {+        d1 = d - days_from_year(y);+        if (d1 < 0) {+            y--;+            d1 += days_in_year(y);+        } else {+            nd = days_in_year(y);+            if (d1 < nd)+                break;+            d1 -= nd;+            y++;+        }+    }+    *days = d1;+    return y;+}++static int const month_days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };+static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";+static char const day_names[] = "SunMonTueWedThuFriSat";++static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,+                                       double fields[9], int is_local, int force)+{+    double dval;+    int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;++    if (JS_ThisTimeValue(ctx, &dval, obj))+        return -1;++    if (isnan(dval)) {+        if (!force)+            return FALSE; /* NaN */+        d = 0;        /* initialize all fields to 0 */+    } else {+        d = dval;+        if (is_local) {+            tz = -getTimezoneOffset(d);+            d += tz * 60000;+        }+    }++    /* result is >= 0, we can use % */+    h = math_mod(d, 86400000);+    days = (d - h) / 86400000;+    ms = h % 1000;+    h = (h - ms) / 1000;+    s = h % 60;+    h = (h - s) / 60;+    m = h % 60;+    h = (h - m) / 60;+    wd = math_mod(days + 4, 7); /* week day */+    y = year_from_days(&days);++    for(i = 0; i < 11; i++) {+        md = month_days[i];+        if (i == 1)+            md += days_in_year(y) - 365;+        if (days < md)+            break;+        days -= md;+    }+    fields[0] = y;+    fields[1] = i;+    fields[2] = days + 1;+    fields[3] = h;+    fields[4] = m;+    fields[5] = s;+    fields[6] = ms;+    fields[7] = wd;+    fields[8] = tz;+    return TRUE;+}++static double time_clip(double t) {+    if (t >= -8.64e15 && t <= 8.64e15)+        return trunc(t) + 0.0;  /* convert -0 to +0 */+    else+        return NAN;+}++/* The spec mandates the use of 'double' and it fixes the order+   of the operations */+static double set_date_fields(double fields[], int is_local) {+    int64_t y;+    double days, d, h, m1;+    int i, m, md;+    +    m1 = fields[1];+    m = fmod(m1, 12);+    if (m < 0)+        m += 12;+    y = (int64_t)(fields[0] + floor(m1 / 12));+    days = days_from_year(y);++    for(i = 0; i < m; i++) {+        md = month_days[i];+        if (i == 1)+            md += days_in_year(y) - 365;+        days += md;+    }+    days += fields[2] - 1;+    h = fields[3] * 3600000 + fields[4] * 60000 + +        fields[5] * 1000 + fields[6];+    d = days * 86400000 + h;+    if (is_local)+        d += getTimezoneOffset(d) * 60000;+    return time_clip(d);+}++static JSValue get_date_field(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    // get_date_field(obj, n, is_local)+    double fields[9];+    int res, n, is_local;++    is_local = magic & 0x0F;+    n = (magic >> 4) & 0x0F;+    res = get_date_fields(ctx, this_val, fields, is_local, 0);+    if (res < 0)+        return JS_EXCEPTION;+    if (!res)+        return JS_NAN;++    if (magic & 0x100) {    // getYear+        fields[0] -= 1900;+    }+    return JS_NewFloat64(ctx, fields[n]);+}++static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    // _field(obj, first_field, end_field, args, is_local)+    double fields[9];+    int res, first_field, end_field, is_local, i, n;+    double d, a;++    d = NAN;+    first_field = (magic >> 8) & 0x0F;+    end_field = (magic >> 4) & 0x0F;+    is_local = magic & 0x0F;++    res = get_date_fields(ctx, this_val, fields, is_local, first_field == 0);+    if (res < 0)+        return JS_EXCEPTION;+    if (res && argc > 0) {+        n = end_field - first_field;+        if (argc < n)+            n = argc;+        for(i = 0; i < n; i++) {+            if (JS_ToFloat64(ctx, &a, argv[i]))+                return JS_EXCEPTION;+            if (!isfinite(a))+                goto done;+            fields[first_field + i] = trunc(a);+        }+        d = set_date_fields(fields, is_local);+    }+done:+    return JS_SetThisTimeValue(ctx, this_val, d);+}++/* fmt:+   0: toUTCString: "Tue, 02 Jan 2018 23:04:46 GMT"+   1: toString: "Wed Jan 03 2018 00:05:22 GMT+0100 (CET)"+   2: toISOString: "2018-01-02T23:02:56.927Z"+   3: toLocaleString: "1/2/2018, 11:40:40 PM"+   part: 1=date, 2=time 3=all+   XXX: should use a variant of strftime().+ */+static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv, int magic)+{+    // _string(obj, fmt, part)+    char buf[64];+    double fields[9];+    int res, fmt, part, pos;+    int y, mon, d, h, m, s, ms, wd, tz;++    fmt = (magic >> 4) & 0x0F;+    part = magic & 0x0F;++    res = get_date_fields(ctx, this_val, fields, fmt & 1, 0);+    if (res < 0)+        return JS_EXCEPTION;+    if (!res) {+        if (fmt == 2)+            return JS_ThrowRangeError(ctx, "Date value is NaN");+        else+            return JS_NewString(ctx, "Invalid Date");+    }++    y = fields[0];+    mon = fields[1];+    d = fields[2];+    h = fields[3];+    m = fields[4];+    s = fields[5];+    ms = fields[6];+    wd = fields[7];+    tz = fields[8];++    pos = 0;++    if (part & 1) { /* date part */+        switch(fmt) {+        case 0:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%.3s, %02d %.3s %0*d ",+                            day_names + wd * 3, d,+                            month_names + mon * 3, 4 + (y < 0), y);+            break;+        case 1:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%.3s %.3s %02d %0*d",+                            day_names + wd * 3,+                            month_names + mon * 3, d, 4 + (y < 0), y);+            if (part == 3) {+                buf[pos++] = ' ';+            }+            break;+        case 2:+            if (y >= 0 && y <= 9999) {+                pos += snprintf(buf + pos, sizeof(buf) - pos,+                                "%04d", y);+            } else {+                pos += snprintf(buf + pos, sizeof(buf) - pos,+                                "%+07d", y);+            }+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "-%02d-%02dT", mon + 1, d);+            break;+        case 3:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d/%02d/%0*d", mon + 1, d, 4 + (y < 0), y);+            if (part == 3) {+                buf[pos++] = ',';+                buf[pos++] = ' ';+            }+            break;+        }+    }+    if (part & 2) { /* time part */+        switch(fmt) {+        case 0:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d:%02d:%02d GMT", h, m, s);+            break;+        case 1:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d:%02d:%02d GMT", h, m, s);+            if (tz < 0) {+                buf[pos++] = '-';+                tz = -tz;+            } else {+                buf[pos++] = '+';+            }+            /* tz is >= 0, can use % */+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d%02d", tz / 60, tz % 60);+            /* XXX: tack the time zone code? */+            break;+        case 2:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d:%02d:%02d.%03dZ", h, m, s, ms);+            break;+        case 3:+            pos += snprintf(buf + pos, sizeof(buf) - pos,+                            "%02d:%02d:%02d %cM", (h + 1) % 12 - 1, m, s,+                            (h < 12) ? 'A' : 'P');+            break;+        }+    }+    return JS_NewStringLen(ctx, buf, pos);+}++/* OS dependent: return the UTC time in ms since 1970. */+static int64_t date_now(void) {+    struct timeval tv;+    gettimeofday(&tv, NULL);+    return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);+}++static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,+                                   int argc, JSValueConst *argv)+{+    // Date(y, mon, d, h, m, s, ms)+    JSValue rv;+    int i, n;+    double a, val;++    if (JS_IsUndefined(new_target)) {+        /* invoked as function */+        argc = 0;+    }+    n = argc;+    if (n == 0) {+        val = date_now();+    } else if (n == 1) {+        JSValue v, dv;+        if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) {+            JSObject *p = JS_VALUE_GET_OBJ(argv[0]);+            if (p->class_id == JS_CLASS_DATE && JS_IsNumber(p->u.object_data)) {+                if (JS_ToFloat64(ctx, &val, p->u.object_data))+                    return JS_EXCEPTION;+                val = time_clip(val);+                goto has_val;+            }+        }+        v = JS_ToPrimitive(ctx, argv[0], HINT_NONE);+        if (JS_IsString(v)) {+            dv = js_Date_parse(ctx, JS_UNDEFINED, 1, (JSValueConst *)&v);+            JS_FreeValue(ctx, v);+            if (JS_IsException(dv))+                return JS_EXCEPTION;+            if (JS_ToFloat64Free(ctx, &val, dv))+                return JS_EXCEPTION;+        } else {+            if (JS_ToFloat64Free(ctx, &val, v))+                return JS_EXCEPTION;+        }+        val = time_clip(val);+    } else {+        double fields[] = { 0, 0, 1, 0, 0, 0, 0 };+        if (n > 7)+            n = 7;+        for(i = 0; i < n; i++) {+            if (JS_ToFloat64(ctx, &a, argv[i]))+                return JS_EXCEPTION;+            if (!isfinite(a))+                break;+            fields[i] = trunc(a);+            if (i == 0 && fields[0] >= 0 && fields[0] < 100)+                fields[0] += 1900;+        }+        val = (i == n) ? set_date_fields(fields, 1) : NAN;+    }+has_val:+#if 0+    JSValueConst args[3];+    args[0] = new_target;+    args[1] = ctx->class_proto[JS_CLASS_DATE];+    args[2] = JS_NewFloat64(ctx, val);+    rv = js___date_create(ctx, JS_UNDEFINED, 3, args);+#else+    rv = js_create_from_ctor(ctx, new_target, JS_CLASS_DATE);+    if (!JS_IsException(rv))+        JS_SetObjectData(ctx, rv, JS_NewFloat64(ctx, val));+#endif+    if (!JS_IsException(rv) && JS_IsUndefined(new_target)) {+        /* invoked as a function, return (new Date()).toString(); */+        JSValue s;+        s = get_date_string(ctx, rv, 0, NULL, 0x13);+        JS_FreeValue(ctx, rv);+        rv = s;+    }+    return rv;+}++static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv)+{+    // UTC(y, mon, d, h, m, s, ms)+    double fields[] = { 0, 0, 1, 0, 0, 0, 0 };+    int i, n;+    double a;++    n = argc;+    if (n == 0)+        return JS_NAN;+    if (n > 7)+        n = 7;+    for(i = 0; i < n; i++) {+        if (JS_ToFloat64(ctx, &a, argv[i]))+            return JS_EXCEPTION;+        if (!isfinite(a))+            return JS_NAN;+        fields[i] = trunc(a);+        if (i == 0 && fields[0] >= 0 && fields[0] < 100)+            fields[0] += 1900;+    }+    return JS_NewFloat64(ctx, set_date_fields(fields, 0));+}++static void string_skip_spaces(JSString *sp, int *pp) {+    while (*pp < sp->len && string_get(sp, *pp) == ' ')+        *pp += 1;+}++static void string_skip_non_spaces(JSString *sp, int *pp) {+    while (*pp < sp->len && string_get(sp, *pp) != ' ')+        *pp += 1;+}++/* parse a numeric field */+static int string_get_field(JSString *sp, int *pp, int64_t *pval) {+    int64_t v = 0;+    int c, p = *pp;++    /* skip non digits, should only skip spaces? */+    while (p < sp->len) {+        c = string_get(sp, p);+        if (c >= '0' && c <= '9')+            break;+        p++;+    }+    if (p >= sp->len)+        return -1;+    while (p < sp->len) {+        c = string_get(sp, p);+        if (!(c >= '0' && c <= '9'))+            break;+        v = v * 10 + c - '0';+        p++;+    }+    *pval = v;+    *pp = p;+    return 0;+}++/* parse a fixed width numeric field */+static int string_get_digits(JSString *sp, int *pp, int n, int64_t *pval) {+    int64_t v = 0;+    int i, c, p = *pp;++    for(i = 0; i < n; i++) {+        if (p >= sp->len)+            return -1;+        c = string_get(sp, p);+        if (!(c >= '0' && c <= '9'))+            return -1;+        v = v * 10 + c - '0';+        p++;+    }+    *pval = v;+    *pp = p;+    return 0;+}++/* parse a signed numeric field */+static int string_get_signed_field(JSString *sp, int *pp, int64_t *pval) {+    int sgn, res;++    if (*pp >= sp->len)+        return -1;++    sgn = string_get(sp, *pp);+    if (sgn == '-' || sgn == '+')+        *pp += 1;++    res = string_get_field(sp, pp, pval);+    if (res == 0 && sgn == '-')+        *pval = -*pval;+    return res;+}++static int find_abbrev(JSString *sp, int p, const char *list, int count) {+    int n, i;++    if (p + 3 <= sp->len) {+        for (n = 0; n < count; n++) {+            for (i = 0; i < 3; i++) {+                if (string_get(sp, p + i) != month_names[n * 3 + i])+                    goto next;+            }+            return n;+        next:;+        }+    }+    return -1;+}++static int string_get_month(JSString *sp, int *pp, int64_t *pval) {+    int n;++    string_skip_spaces(sp, pp);+    n = find_abbrev(sp, *pp, month_names, 12);+    if (n < 0)+        return -1;++    *pval = n;+    *pp += 3;+    return 0;+}++static JSValue js_Date_parse(JSContext *ctx, JSValueConst this_val,+                             int argc, JSValueConst *argv)+{+    // parse(s)+    JSValue s, rv;+    int64_t fields[] = { 0, 1, 1, 0, 0, 0, 0 };+    double fields1[7];+    int64_t tz, hh, mm;+    double d;+    int p, i, c, sgn;+    JSString *sp;+    BOOL is_local;+    +    rv = JS_NAN;++    s = JS_ToString(ctx, argv[0]);+    if (JS_IsException(s))+        return JS_EXCEPTION;+    +    sp = JS_VALUE_GET_STRING(s);+    p = 0;+    if (p < sp->len && (((c = string_get(sp, p)) >= '0' && c <= '9') || c == '+' || c == '-')) {+        /* ISO format */+        /* year field can be negative */+        /* XXX: could be stricter */+        if (string_get_signed_field(sp, &p, &fields[0]))+            goto done;++        is_local = TRUE;+        for (i = 1; i < 6; i++) {+            if (string_get_field(sp, &p, &fields[i]))+                break;+        }+        if (i <= 3) {+            /* no time: UTC by default */+            is_local = FALSE;+        } else if (i == 6 && p < sp->len && string_get(sp, p) == '.') {+            /* parse milliseconds as a fractional part, round to nearest */+            /* XXX: the spec does not indicate which rounding should be used */+            int mul = 1000, ms = 0;+            while (++p < sp->len) {+                int c = string_get(sp, p);+                if (!(c >= '0' && c <= '9'))+                    break;+                if (mul == 1 && c >= '5')+                    ms += 1;+                ms += (c - '0') * (mul /= 10);+            }+            fields[6] = ms;+        }+        fields[1] -= 1;++        /* parse the time zone offset if present: [+-]HH:mm */+        tz = 0;+        if (p < sp->len) {+            sgn = string_get(sp, p);+            if (sgn == '+' || sgn == '-') {+                if (string_get_field(sp, &p, &hh))+                    goto done;+                if (string_get_field(sp, &p, &mm))+                    goto done;+                tz = hh * 60 + mm;+                if (sgn == '-')+                    tz = -tz;+                is_local = FALSE;+            } else if (sgn == 'Z') {+                is_local = FALSE;+            }+        }+    } else {+        /* toString or toUTCString format */+        /* skip the day of the week */+        string_skip_non_spaces(sp, &p);+        string_skip_spaces(sp, &p);+        if (p >= sp->len)+            goto done;+        c = string_get(sp, p);+        if (c >= '0' && c <= '9') {+            /* day of month first */+            if (string_get_field(sp, &p, &fields[2]))+                goto done;+            if (string_get_month(sp, &p, &fields[1]))+                goto done;+        } else {+            /* month first */+            if (string_get_month(sp, &p, &fields[1]))+                goto done;+            if (string_get_field(sp, &p, &fields[2]))+                goto done;+        }+        string_skip_spaces(sp, &p);+        if (string_get_signed_field(sp, &p, &fields[0]))+            goto done;++        /* hour, min, seconds */+        for(i = 0; i < 3; i++) {+            if (string_get_field(sp, &p, &fields[3 + i]))+                goto done;+        }+        // XXX: parse optional milliseconds?++        /* parse the time zone offset if present: [+-]HHmm */+        is_local = FALSE;+        tz = 0;+        for (tz = 0; p < sp->len; p++) {+            sgn = string_get(sp, p);+            if (sgn == '+' || sgn == '-') {+                p++;+                if (string_get_digits(sp, &p, 2, &hh))+                    goto done;+                if (string_get_digits(sp, &p, 2, &mm))+                    goto done;+                tz = hh * 60 + mm;+                if (sgn == '-')+                    tz = -tz;+                break;+            }+        }+    }+    for(i = 0; i < 7; i++)+        fields1[i] = fields[i];+    d = set_date_fields(fields1, is_local) - tz * 60000;+    rv = JS_NewFloat64(ctx, d);++done:+    JS_FreeValue(ctx, s);+    return rv;+}++static JSValue js_Date_now(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv)+{+    // now()+    return JS_NewInt64(ctx, date_now());+}++static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,+                                          int argc, JSValueConst *argv)+{+    // Symbol_toPrimitive(hint)+    JSValueConst obj = this_val;+    JSAtom hint = JS_ATOM_NULL;+    int hint_num;++    if (!JS_IsObject(obj))+        return JS_ThrowTypeErrorNotAnObject(ctx);++    if (JS_IsString(argv[0])) {+        hint = JS_ValueToAtom(ctx, argv[0]);+        if (hint == JS_ATOM_NULL)+            return JS_EXCEPTION;+        JS_FreeAtom(ctx, hint);+    }+    switch (hint) {+    case JS_ATOM_number:+#ifdef CONFIG_BIGNUM+    case JS_ATOM_integer:+#endif+        hint_num = HINT_NUMBER;+        break;+    case JS_ATOM_string:+    case JS_ATOM_default:+        hint_num = HINT_STRING;+        break;+    default:+        return JS_ThrowTypeError(ctx, "invalid hint");+    }+    return JS_ToPrimitive(ctx, obj, hint_num | HINT_FORCE_ORDINARY);+}++static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,+                                         int argc, JSValueConst *argv)+{+    // getTimezoneOffset()+    double v;++    if (JS_ThisTimeValue(ctx, &v, this_val))+        return JS_EXCEPTION;+    if (isnan(v))+        return JS_NAN;+    else+        return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));+}++static JSValue js_date_getTime(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    // getTime()+    double v;++    if (JS_ThisTimeValue(ctx, &v, this_val))+        return JS_EXCEPTION;+    return JS_NewFloat64(ctx, v);+}++static JSValue js_date_setTime(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    // setTime(v)+    double v;++    if (JS_ThisTimeValue(ctx, &v, this_val) || JS_ToFloat64(ctx, &v, argv[0]))+        return JS_EXCEPTION;+    return JS_SetThisTimeValue(ctx, this_val, time_clip(v));+}++static JSValue js_date_setYear(JSContext *ctx, JSValueConst this_val,+                               int argc, JSValueConst *argv)+{+    // setYear(y)+    double y;+    JSValueConst args[1];++    if (JS_ThisTimeValue(ctx, &y, this_val) || JS_ToFloat64(ctx, &y, argv[0]))+        return JS_EXCEPTION;+    y = +y;+    if (isfinite(y)) {+        y = trunc(y);+        if (y >= 0 && y < 100)+            y += 1900;+    }+    args[0] = JS_NewFloat64(ctx, y);+    return set_date_field(ctx, this_val, 1, args, 0x011);+}++static JSValue js_date_toJSON(JSContext *ctx, JSValueConst this_val,+                              int argc, JSValueConst *argv)+{+    // toJSON(key)+    JSValue obj, tv, method, rv;+    double d;++    rv = JS_EXCEPTION;+    tv = JS_UNDEFINED;++    obj = JS_ToObject(ctx, this_val);+    tv = JS_ToPrimitive(ctx, obj, HINT_NUMBER);+    if (JS_IsException(tv))+        goto exception;+    if (JS_IsNumber(tv)) {+        if (JS_ToFloat64(ctx, &d, tv) < 0)+            goto exception;+        if (!isfinite(d)) {+            rv = JS_NULL;+            goto done;+        }+    }+    method = JS_GetPropertyStr(ctx, obj, "toISOString");+    if (JS_IsException(method))+        goto exception;+    if (!JS_IsFunction(ctx, method)) {+        JS_ThrowTypeError(ctx, "object needs toISOString method");+        JS_FreeValue(ctx, method);+        goto exception;+    }+    rv = JS_CallFree(ctx, method, obj, 0, NULL);+exception:+done:+    JS_FreeValue(ctx, obj);+    JS_FreeValue(ctx, tv);+    return rv;+}++static const JSCFunctionListEntry js_date_funcs[] = {+    JS_CFUNC_DEF("now", 0, js_Date_now ),+    JS_CFUNC_DEF("parse", 1, js_Date_parse ),+    JS_CFUNC_DEF("UTC", 7, js_Date_UTC ),+};++static const JSCFunctionListEntry js_date_proto_funcs[] = {+    JS_CFUNC_DEF("valueOf", 0, js_date_getTime ),+    JS_CFUNC_MAGIC_DEF("toString", 0, get_date_string, 0x13 ),+    JS_CFUNC_DEF("[Symbol.toPrimitive]", 1, js_date_Symbol_toPrimitive ),+    JS_CFUNC_MAGIC_DEF("toUTCString", 0, get_date_string, 0x03 ),+    JS_ALIAS_DEF("toGMTString", "toUTCString" ),+    JS_CFUNC_MAGIC_DEF("toISOString", 0, get_date_string, 0x23 ),+    JS_CFUNC_MAGIC_DEF("toDateString", 0, get_date_string, 0x11 ),+    JS_CFUNC_MAGIC_DEF("toTimeString", 0, get_date_string, 0x12 ),+    JS_CFUNC_MAGIC_DEF("toLocaleString", 0, get_date_string, 0x33 ),+    JS_CFUNC_MAGIC_DEF("toLocaleDateString", 0, get_date_string, 0x31 ),+    JS_CFUNC_MAGIC_DEF("toLocaleTimeString", 0, get_date_string, 0x32 ),+    JS_CFUNC_DEF("getTimezoneOffset", 0, js_date_getTimezoneOffset ),+    JS_CFUNC_DEF("getTime", 0, js_date_getTime ),+    JS_CFUNC_MAGIC_DEF("getYear", 0, get_date_field, 0x101 ),+    JS_CFUNC_MAGIC_DEF("getFullYear", 0, get_date_field, 0x01 ),+    JS_CFUNC_MAGIC_DEF("getUTCFullYear", 0, get_date_field, 0x00 ),+    JS_CFUNC_MAGIC_DEF("getMonth", 0, get_date_field, 0x11 ),+    JS_CFUNC_MAGIC_DEF("getUTCMonth", 0, get_date_field, 0x10 ),+    JS_CFUNC_MAGIC_DEF("getDate", 0, get_date_field, 0x21 ),+    JS_CFUNC_MAGIC_DEF("getUTCDate", 0, get_date_field, 0x20 ),+    JS_CFUNC_MAGIC_DEF("getHours", 0, get_date_field, 0x31 ),+    JS_CFUNC_MAGIC_DEF("getUTCHours", 0, get_date_field, 0x30 ),+    JS_CFUNC_MAGIC_DEF("getMinutes", 0, get_date_field, 0x41 ),+    JS_CFUNC_MAGIC_DEF("getUTCMinutes", 0, get_date_field, 0x40 ),+    JS_CFUNC_MAGIC_DEF("getSeconds", 0, get_date_field, 0x51 ),+    JS_CFUNC_MAGIC_DEF("getUTCSeconds", 0, get_date_field, 0x50 ),+    JS_CFUNC_MAGIC_DEF("getMilliseconds", 0, get_date_field, 0x61 ),+    JS_CFUNC_MAGIC_DEF("getUTCMilliseconds", 0, get_date_field, 0x60 ),+    JS_CFUNC_MAGIC_DEF("getDay", 0, get_date_field, 0x71 ),+    JS_CFUNC_MAGIC_DEF("getUTCDay", 0, get_date_field, 0x70 ),+    JS_CFUNC_DEF("setTime", 1, js_date_setTime ),+    JS_CFUNC_MAGIC_DEF("setMilliseconds", 1, set_date_field, 0x671 ),+    JS_CFUNC_MAGIC_DEF("setUTCMilliseconds", 1, set_date_field, 0x670 ),+    JS_CFUNC_MAGIC_DEF("setSeconds", 2, set_date_field, 0x571 ),+    JS_CFUNC_MAGIC_DEF("setUTCSeconds", 2, set_date_field, 0x570 ),+    JS_CFUNC_MAGIC_DEF("setMinutes", 3, set_date_field, 0x471 ),+    JS_CFUNC_MAGIC_DEF("setUTCMinutes", 3, set_date_field, 0x470 ),+    JS_CFUNC_MAGIC_DEF("setHours", 4, set_date_field, 0x371 ),+    JS_CFUNC_MAGIC_DEF("setUTCHours", 4, set_date_field, 0x370 ),+    JS_CFUNC_MAGIC_DEF("setDate", 1, set_date_field, 0x231 ),+    JS_CFUNC_MAGIC_DEF("setUTCDate", 1, set_date_field, 0x230 ),+    JS_CFUNC_MAGIC_DEF("setMonth", 2, set_date_field, 0x131 ),+    JS_CFUNC_MAGIC_DEF("setUTCMonth", 2, set_date_field, 0x130 ),+    JS_CFUNC_DEF("setYear", 1, js_date_setYear ),+    JS_CFUNC_MAGIC_DEF("setFullYear", 3, set_date_field, 0x031 ),+    JS_CFUNC_MAGIC_DEF("setUTCFullYear", 3, set_date_field, 0x030 ),+    JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ),+};++void JS_AddIntrinsicDate(JSContext *ctx)+{+    JSValueConst obj;++    /* Date */+    ctx->class_proto[JS_CLASS_DATE] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_DATE], js_date_proto_funcs,+                               countof(js_date_proto_funcs));+    obj = JS_NewGlobalCConstructor(ctx, "Date", js_date_constructor, 7,+                                   ctx->class_proto[JS_CLASS_DATE]);+    JS_SetPropertyFunctionList(ctx, obj, js_date_funcs, countof(js_date_funcs));+}++/* eval */++void JS_AddIntrinsicEval(JSContext *ctx)+{+    ctx->eval_internal = __JS_EvalInternal;+}++#ifdef CONFIG_BIGNUM++/* Operators */++static void js_operator_set_finalizer(JSRuntime *rt, JSValue val)+{+    JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);+    int i, j;+    JSBinaryOperatorDefEntry *ent;+    +    if (opset) {+        for(i = 0; i < JS_OVOP_COUNT; i++) {+            if (opset->self_ops[i])+                JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]));+        }+        for(j = 0; j < opset->left.count; j++) {+            ent = &opset->left.tab[j];+            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {+                if (ent->ops[i])+                    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));+            }+        }+        js_free_rt(rt, opset->left.tab);+        for(j = 0; j < opset->right.count; j++) {+            ent = &opset->right.tab[j];+            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {+                if (ent->ops[i])+                    JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]));+            }+        }+        js_free_rt(rt, opset->right.tab);+        js_free_rt(rt, opset);+    }+}++static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,+                                 JS_MarkFunc *mark_func)+{+    JSOperatorSetData *opset = JS_GetOpaque(val, JS_CLASS_OPERATOR_SET);+    int i, j;+    JSBinaryOperatorDefEntry *ent;+    +    if (opset) {+        for(i = 0; i < JS_OVOP_COUNT; i++) {+            if (opset->self_ops[i])+                JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[i]),+                             mark_func);+        }+        for(j = 0; j < opset->left.count; j++) {+            ent = &opset->left.tab[j];+            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {+                if (ent->ops[i])+                    JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),+                                 mark_func);+            }+        }+        for(j = 0; j < opset->right.count; j++) {+            ent = &opset->right.tab[j];+            for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {+                if (ent->ops[i])+                    JS_MarkValue(rt, JS_MKPTR(JS_TAG_OBJECT, ent->ops[i]),+                                 mark_func);+            }+        }+    }+}+++/* create an OperatorSet object */+static JSValue js_operators_create_internal(JSContext *ctx,+                                            int argc, JSValueConst *argv,+                                            BOOL is_primitive)+{+    JSValue opset_obj, prop, obj;+    JSOperatorSetData *opset, *opset1;+    JSBinaryOperatorDef *def;+    JSValueConst arg;+    int i, j;+    JSBinaryOperatorDefEntry *new_tab;+    JSBinaryOperatorDefEntry *ent;+    uint32_t op_count;++    if (ctx->rt->operator_count == UINT32_MAX) {+        return JS_ThrowTypeError(ctx, "too many operators");+    }+    opset_obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_OPERATOR_SET);+    if (JS_IsException(opset_obj))+        goto fail;+    opset = js_mallocz(ctx, sizeof(*opset));+    if (!opset)+        goto fail;+    JS_SetOpaque(opset_obj, opset);+    if (argc >= 1) {+        arg = argv[0];+        /* self operators */+        for(i = 0; i < JS_OVOP_COUNT; i++) {+            prop = JS_GetPropertyStr(ctx, arg, js_overloadable_operator_names[i]);+            if (JS_IsException(prop))+                goto fail;+            if (!JS_IsUndefined(prop)) {+                if (check_function(ctx, prop)) {+                    JS_FreeValue(ctx, prop);+                    goto fail;+                }+                opset->self_ops[i] = JS_VALUE_GET_OBJ(prop);+            }+        }+    }+    /* left & right operators */+    for(j = 1; j < argc; j++) {+        arg = argv[j];+        prop = JS_GetPropertyStr(ctx, arg, "left");+        if (JS_IsException(prop))+            goto fail;+        def = &opset->right;+        if (JS_IsUndefined(prop)) {+            prop = JS_GetPropertyStr(ctx, arg, "right");+            if (JS_IsException(prop))+                goto fail;+            if (JS_IsUndefined(prop)) {+                JS_ThrowTypeError(ctx, "left or right property must be present");+                goto fail;+            }+            def = &opset->left;+        }+        /* get the operator set */+        obj = JS_GetProperty(ctx, prop, JS_ATOM_prototype);+        JS_FreeValue(ctx, prop);+        if (JS_IsException(obj))+            goto fail;+        prop = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_operatorSet);+        JS_FreeValue(ctx, obj);+        if (JS_IsException(prop))+            goto fail;+        opset1 = JS_GetOpaque2(ctx, prop, JS_CLASS_OPERATOR_SET);+        if (!opset1) {+            JS_FreeValue(ctx, prop);+            goto fail;+        }+        op_count = opset1->operator_counter;+        JS_FreeValue(ctx, prop);+        +        /* we assume there are few entries */+        new_tab = js_realloc(ctx, def->tab,+                             (def->count + 1) * sizeof(def->tab[0]));+        if (!new_tab)+            goto fail;+        def->tab = new_tab;+        def->count++;+        ent = def->tab + def->count - 1;+        memset(ent, 0, sizeof(def->tab[0]));+        ent->operator_index = op_count;+        +        for(i = 0; i < JS_OVOP_BINARY_COUNT; i++) {+            prop = JS_GetPropertyStr(ctx, arg,+                                     js_overloadable_operator_names[i]);+            if (JS_IsException(prop))+                goto fail;+            if (!JS_IsUndefined(prop)) {+                if (check_function(ctx, prop)) {+                    JS_FreeValue(ctx, prop);+                    goto fail;+                }+                ent->ops[i] = JS_VALUE_GET_OBJ(prop);+            }+        }+    }+    opset->is_primitive = is_primitive;+    opset->operator_counter = ctx->rt->operator_count++;+    return opset_obj;+ fail:+    JS_FreeValue(ctx, opset_obj);+    return JS_EXCEPTION;+}++static JSValue js_operators_create(JSContext *ctx, JSValueConst this_val,+                                int argc, JSValueConst *argv)+{+    return js_operators_create_internal(ctx, argc, argv, FALSE);+}++static JSValue js_operators_updateBigIntOperators(JSContext *ctx, JSValueConst this_val,+                                                  int argc, JSValueConst *argv)+{+    JSValue opset_obj, prop;+    JSOperatorSetData *opset;+    const JSOverloadableOperatorEnum ops[2] = { JS_OVOP_DIV, JS_OVOP_POW };+    JSOverloadableOperatorEnum op;+    int i;+    +    opset_obj = JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_BIG_INT],+                               JS_ATOM_Symbol_operatorSet);+    if (JS_IsException(opset_obj))+        goto fail;+    opset = JS_GetOpaque2(ctx, opset_obj, JS_CLASS_OPERATOR_SET);+    if (!opset)+        goto fail;+    for(i = 0; i < countof(ops); i++) {+        op = ops[i];+        prop = JS_GetPropertyStr(ctx, argv[0],+                                 js_overloadable_operator_names[op]);+        if (JS_IsException(prop))+            goto fail;+        if (!JS_IsUndefined(prop)) {+            if (!JS_IsNull(prop) && check_function(ctx, prop)) {+                JS_FreeValue(ctx, prop);+                goto fail;+            }+            if (opset->self_ops[op])+                JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, opset->self_ops[op]));+            if (JS_IsNull(prop)) {+                opset->self_ops[op] = NULL;+            } else {+                opset->self_ops[op] = JS_VALUE_GET_PTR(prop);+            }+        }+    }+    JS_FreeValue(ctx, opset_obj);+    return JS_UNDEFINED;+ fail:+    JS_FreeValue(ctx, opset_obj);+    return JS_EXCEPTION;+}++static int js_operators_set_default(JSContext *ctx, JSValueConst obj)+{+    JSValue opset_obj;++    if (!JS_IsObject(obj)) /* in case the prototype is not defined */+        return 0;+    opset_obj = js_operators_create_internal(ctx, 0, NULL, TRUE);+    if (JS_IsException(opset_obj))+        return -1;+    /* cannot be modified by the user */+    JS_DefinePropertyValue(ctx, obj, JS_ATOM_Symbol_operatorSet,+                           opset_obj, 0);+    return 0;+}++static JSValue js_dummy_operators_ctor(JSContext *ctx, JSValueConst new_target,+                                       int argc, JSValueConst *argv)+{+    return js_create_from_ctor(ctx, new_target, JS_CLASS_OBJECT);+}++static JSValue js_global_operators(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    JSValue func_obj, proto, opset_obj;++    func_obj = JS_UNDEFINED;+    proto = JS_NewObject(ctx);+    if (JS_IsException(proto))+        return JS_EXCEPTION;+    opset_obj = js_operators_create_internal(ctx, argc, argv, FALSE);+    if (JS_IsException(opset_obj))+        goto fail;+    JS_DefinePropertyValue(ctx, proto, JS_ATOM_Symbol_operatorSet,+                           opset_obj, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    func_obj = JS_NewCFunction2(ctx, js_dummy_operators_ctor, "Operators",+                                0, JS_CFUNC_constructor, 0);+    if (JS_IsException(func_obj))+        goto fail;+    JS_SetConstructor2(ctx, func_obj, proto,+                       0, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    JS_FreeValue(ctx, proto);+    return func_obj;+ fail:+    JS_FreeValue(ctx, proto);+    JS_FreeValue(ctx, func_obj);+    return JS_EXCEPTION;+}++static const JSCFunctionListEntry js_operators_funcs[] = {+    JS_CFUNC_DEF("create", 1, js_operators_create ),+    JS_CFUNC_DEF("updateBigIntOperators", 2, js_operators_updateBigIntOperators ),+};++/* must be called after all overloadable base types are initialized */+void JS_AddIntrinsicOperators(JSContext *ctx)+{+    JSValue obj;++    ctx->allow_operator_overloading = TRUE;+    obj = JS_NewCFunction(ctx, js_global_operators, "Operators", 1);+    JS_SetPropertyFunctionList(ctx, obj,+                               js_operators_funcs,+                               countof(js_operators_funcs));+    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_Operators,+                           obj,+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    /* add default operatorSets */+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BOOLEAN]);+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_NUMBER]);+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_STRING]);+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_INT]);+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT]);+    js_operators_set_default(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL]);+}++/* BigInt */++static JSValue JS_ToBigIntCtorFree(JSContext *ctx, JSValue val)+{+    uint32_t tag;++ redo:+    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_INT:+    case JS_TAG_BOOL:+        val = JS_NewBigInt64(ctx, JS_VALUE_GET_INT(val));+        break;+    case JS_TAG_BIG_INT:+        break;+    case JS_TAG_FLOAT64:+    case JS_TAG_BIG_FLOAT:+        {+            bf_t *a, a_s;+            +            a = JS_ToBigFloat(ctx, &a_s, val);+            if (!bf_is_finite(a)) {+                JS_FreeValue(ctx, val);+                val = JS_ThrowRangeError(ctx, "cannot convert NaN or Infinity to bigint");+            } else {+                JSValue val1 = JS_NewBigInt(ctx);+                bf_t *r;+                int ret;+                if (JS_IsException(val1)) {+                    JS_FreeValue(ctx, val);+                    return JS_EXCEPTION;+                }+                r = JS_GetBigInt(val1);+                ret = bf_set(r, a);+                ret |= bf_rint(r, BF_RNDZ);+                JS_FreeValue(ctx, val);+                if (ret & BF_ST_MEM_ERROR) {+                    JS_FreeValue(ctx, val1);+                    val = JS_ThrowOutOfMemory(ctx);+                } else if (ret & BF_ST_INEXACT) {+                    JS_FreeValue(ctx, val1);+                    val = JS_ThrowRangeError(ctx, "cannot convert to bigint: not an integer");+                } else {+                    val = JS_CompactBigInt(ctx, val1);+                }+            }+            if (a == &a_s)+                bf_delete(a);+        }+        break;+    case JS_TAG_BIG_DECIMAL:+        val = JS_ToStringFree(ctx, val);+         if (JS_IsException(val))+            break;+        goto redo;+    case JS_TAG_STRING:+        val = JS_StringToBigIntErr(ctx, val);+        break;+    case JS_TAG_OBJECT:+        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);+        if (JS_IsException(val))+            break;+        goto redo;+    case JS_TAG_NULL:+    case JS_TAG_UNDEFINED:+    default:+        JS_FreeValue(ctx, val);+        return JS_ThrowTypeError(ctx, "cannot convert to bigint");+    }+    return val;+}++static JSValue js_bigint_constructor(JSContext *ctx,+                                     JSValueConst new_target,+                                     int argc, JSValueConst *argv)+{+    if (!JS_IsUndefined(new_target))+        return JS_ThrowTypeError(ctx, "not a constructor");+    return JS_ToBigIntCtorFree(ctx, JS_DupValue(ctx, argv[0]));+}++static JSValue js_thisBigIntValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_IsBigInt(ctx, this_val))+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_BIG_INT) {+            if (JS_IsBigInt(ctx, p->u.object_data))+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a bigint");+}++static JSValue js_bigint_toString(JSContext *ctx, JSValueConst this_val,+                                  int argc, JSValueConst *argv)+{+    JSValue val;+    int base;+    JSValue ret;++    val = js_thisBigIntValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (argc == 0 || JS_IsUndefined(argv[0])) {+        base = 10;+    } else {+        base = js_get_radix(ctx, argv[0]);+        if (base < 0)+            goto fail;+    }+    ret = js_bigint_to_string1(ctx, val, base);+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigint_valueOf(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    return js_thisBigIntValue(ctx, this_val);+}++static JSValue js_bigint_div(JSContext *ctx,+                              JSValueConst this_val,+                              int argc, JSValueConst *argv, int magic)+{+    bf_t a_s, b_s, *a, *b, *r, *q;+    int status;+    JSValue q_val, r_val;+    +    q_val = JS_NewBigInt(ctx);+    if (JS_IsException(q_val))+        return JS_EXCEPTION;+    r_val = JS_NewBigInt(ctx);+    if (JS_IsException(r_val))+        goto fail;+    b = NULL;+    a = JS_ToBigInt(ctx, &a_s, argv[0]);+    if (!a)+        goto fail;+    b = JS_ToBigInt(ctx, &b_s, argv[1]);+    if (!b) {+        JS_FreeBigInt(ctx, a, &a_s);+        goto fail;+    }+    q = JS_GetBigInt(q_val);+    r = JS_GetBigInt(r_val);+    status = bf_divrem(q, r, a, b, BF_PREC_INF, BF_RNDZ, magic & 0xf);+    JS_FreeBigInt(ctx, a, &a_s);+    JS_FreeBigInt(ctx, b, &b_s);+    if (unlikely(status)) {+        throw_bf_exception(ctx, status);+        goto fail;+    }+    q_val = JS_CompactBigInt(ctx, q_val);+    if (magic & 0x10) {+        JSValue ret;+        ret = JS_NewArray(ctx);+        if (JS_IsException(ret))+            goto fail;+        JS_SetPropertyUint32(ctx, ret, 0, q_val);+        JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, r_val));+        return ret;+    } else {+        JS_FreeValue(ctx, r_val);+        return q_val;+    }+ fail:+    JS_FreeValue(ctx, q_val);+    JS_FreeValue(ctx, r_val);+    return JS_EXCEPTION;+}++static JSValue js_bigint_sqrt(JSContext *ctx,+                               JSValueConst this_val,+                               int argc, JSValueConst *argv, int magic)+{+    bf_t a_s, *a, *r, *rem;+    int status;+    JSValue r_val, rem_val;+    +    r_val = JS_NewBigInt(ctx);+    if (JS_IsException(r_val))+        return JS_EXCEPTION;+    rem_val = JS_NewBigInt(ctx);+    if (JS_IsException(rem_val))+        return JS_EXCEPTION;+    r = JS_GetBigInt(r_val);+    rem = JS_GetBigInt(rem_val);++    a = JS_ToBigInt(ctx, &a_s, argv[0]);+    if (!a)+        goto fail;+    status = bf_sqrtrem(r, rem, a);+    JS_FreeBigInt(ctx, a, &a_s);+    if (unlikely(status & ~BF_ST_INEXACT)) {+        throw_bf_exception(ctx, status);+        goto fail;+    }+    r_val = JS_CompactBigInt(ctx, r_val);+    if (magic) {+        JSValue ret;+        ret = JS_NewArray(ctx);+        if (JS_IsException(ret))+            goto fail;+        JS_SetPropertyUint32(ctx, ret, 0, r_val);+        JS_SetPropertyUint32(ctx, ret, 1, JS_CompactBigInt(ctx, rem_val));+        return ret;+    } else {+        JS_FreeValue(ctx, rem_val);+        return r_val;+    }+ fail:+    JS_FreeValue(ctx, r_val);+    JS_FreeValue(ctx, rem_val);+    return JS_EXCEPTION;+}++static JSValue js_bigint_op1(JSContext *ctx,+                              JSValueConst this_val,+                              int argc, JSValueConst *argv,+                              int magic)+{+    bf_t a_s, *a;+    int64_t res;++    a = JS_ToBigInt(ctx, &a_s, argv[0]);+    if (!a)+        return JS_EXCEPTION;+    switch(magic) {+    case 0: /* floorLog2 */+        if (a->sign || a->expn <= 0) {+            res = -1;+        } else {+            res = a->expn - 1;+        }+        break;+    case 1: /* ctz */+        if (bf_is_zero(a)) {+            res = -1;+        } else {+            res = bf_get_exp_min(a);+        }+        break;+    default:+        abort();+    }+    JS_FreeBigInt(ctx, a, &a_s);+    return JS_NewBigInt64(ctx, res);+}++static JSValue js_bigint_asUintN(JSContext *ctx,+                                  JSValueConst this_val,+                                  int argc, JSValueConst *argv, int asIntN)+{+    uint64_t bits;+    bf_t a_s, *a = &a_s, *r, mask_s, *mask = &mask_s;+    JSValue res;+    +    if (JS_ToIndex(ctx, &bits, argv[0]))+        return JS_EXCEPTION;+    res = JS_NewBigInt(ctx);+    if (JS_IsException(res))+        return JS_EXCEPTION;+    r = JS_GetBigInt(res);+    a = JS_ToBigInt(ctx, &a_s, argv[1]);+    if (!a) {+        JS_FreeValue(ctx, res);+        return JS_EXCEPTION;+    }+    /* XXX: optimize */+    r = JS_GetBigInt(res);+    bf_init(ctx->bf_ctx, mask);+    bf_set_ui(mask, 1);+    bf_mul_2exp(mask, bits, BF_PREC_INF, BF_RNDZ);+    bf_add_si(mask, mask, -1, BF_PREC_INF, BF_RNDZ);+    bf_logic_and(r, a, mask);+    if (asIntN && bits != 0) {+        bf_set_ui(mask, 1);+        bf_mul_2exp(mask, bits - 1, BF_PREC_INF, BF_RNDZ);+        if (bf_cmpu(r, mask) >= 0) {+            bf_set_ui(mask, 1);+            bf_mul_2exp(mask, bits, BF_PREC_INF, BF_RNDZ);+            bf_sub(r, r, mask, BF_PREC_INF, BF_RNDZ);+        }+    }+    bf_delete(mask);+    JS_FreeBigInt(ctx, a, &a_s);+    return JS_CompactBigInt(ctx, res);+}++static const JSCFunctionListEntry js_bigint_funcs[] = {+    JS_CFUNC_MAGIC_DEF("asUintN", 2, js_bigint_asUintN, 0 ),+    JS_CFUNC_MAGIC_DEF("asIntN", 2, js_bigint_asUintN, 1 ),+    /* QuickJS extensions */+    JS_CFUNC_MAGIC_DEF("tdiv", 2, js_bigint_div, BF_RNDZ ),+    JS_CFUNC_MAGIC_DEF("fdiv", 2, js_bigint_div, BF_RNDD ),+    JS_CFUNC_MAGIC_DEF("cdiv", 2, js_bigint_div, BF_RNDU ),+    JS_CFUNC_MAGIC_DEF("ediv", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN ),+    JS_CFUNC_MAGIC_DEF("tdivrem", 2, js_bigint_div, BF_RNDZ | 0x10 ),+    JS_CFUNC_MAGIC_DEF("fdivrem", 2, js_bigint_div, BF_RNDD | 0x10 ),+    JS_CFUNC_MAGIC_DEF("cdivrem", 2, js_bigint_div, BF_RNDU | 0x10 ),+    JS_CFUNC_MAGIC_DEF("edivrem", 2, js_bigint_div, BF_DIVREM_EUCLIDIAN | 0x10 ),+    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigint_sqrt, 0 ),+    JS_CFUNC_MAGIC_DEF("sqrtrem", 1, js_bigint_sqrt, 1 ),+    JS_CFUNC_MAGIC_DEF("floorLog2", 1, js_bigint_op1, 0 ),+    JS_CFUNC_MAGIC_DEF("ctz", 1, js_bigint_op1, 1 ),+};++static const JSCFunctionListEntry js_bigint_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_bigint_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_bigint_valueOf ),+    JS_PROP_STRING_DEF("[Symbol.toStringTag]", "BigInt", JS_PROP_CONFIGURABLE ),+};++void JS_AddIntrinsicBigInt(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    JSValueConst obj1;++    rt->bigint_ops.to_string = js_bigint_to_string;+    rt->bigint_ops.from_string = js_string_to_bigint;+    rt->bigint_ops.unary_arith = js_unary_arith_bigint;+    rt->bigint_ops.binary_arith = js_binary_arith_bigint;+    rt->bigint_ops.compare = js_compare_bigfloat;+    +    ctx->class_proto[JS_CLASS_BIG_INT] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_INT],+                               js_bigint_proto_funcs,+                               countof(js_bigint_proto_funcs));+    obj1 = JS_NewGlobalCConstructor(ctx, "BigInt", js_bigint_constructor, 1,+                                    ctx->class_proto[JS_CLASS_BIG_INT]);+    JS_SetPropertyFunctionList(ctx, obj1, js_bigint_funcs,+                               countof(js_bigint_funcs));+}++/* BigFloat */++static JSValue js_thisBigFloatValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_IsBigFloat(this_val))+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_BIG_FLOAT) {+            if (JS_IsBigFloat(p->u.object_data))+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a bigfloat");+}++static JSValue js_bigfloat_toString(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValue val;+    int base;+    JSValue ret;++    val = js_thisBigFloatValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (argc == 0 || JS_IsUndefined(argv[0])) {+        base = 10;+    } else {+        base = js_get_radix(ctx, argv[0]);+        if (base < 0)+            goto fail;+    }+    ret = js_ftoa(ctx, val, base, 0, BF_RNDN | BF_FTOA_FORMAT_FREE_MIN);+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigfloat_valueOf(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    return js_thisBigFloatValue(ctx, this_val);+}++static int bigfloat_get_rnd_mode(JSContext *ctx, JSValueConst val)+{+    int rnd_mode;+    if (JS_ToInt32Sat(ctx, &rnd_mode, val))+        return -1;+    if (rnd_mode < BF_RNDN || rnd_mode > BF_RNDF) {+        JS_ThrowRangeError(ctx, "invalid rounding mode");+        return -1;+    }+    return rnd_mode;+}++static JSValue js_bigfloat_toFixed(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t f;+    int rnd_mode, radix;++    val = js_thisBigFloatValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToInt64Sat(ctx, &f, argv[0]))+        goto fail;+    if (f < 0 || f > BF_PREC_MAX) {+        JS_ThrowRangeError(ctx, "invalid number of digits");+        goto fail;+    }+    rnd_mode = BF_RNDNA;+    radix = 10;+    /* XXX: swap parameter order for rounding mode and radix */+    if (argc > 1) {+        rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);+        if (rnd_mode < 0)+            goto fail;+    }+    if (argc > 2) {+        radix = js_get_radix(ctx, argv[2]);+        if (radix < 0)+            goto fail;+    }+    ret = js_ftoa(ctx, val, radix, f, rnd_mode | BF_FTOA_FORMAT_FRAC);+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static BOOL js_bigfloat_is_finite(JSContext *ctx, JSValueConst val)+{+    BOOL res;+    uint32_t tag;++    tag = JS_VALUE_GET_NORM_TAG(val);+    switch(tag) {+    case JS_TAG_BIG_FLOAT:+        {+            JSBigFloat *p = JS_VALUE_GET_PTR(val);+            res = bf_is_finite(&p->num);+        }+        break;+    default:+        res = FALSE;+        break;+    }+    return res;+}++static JSValue js_bigfloat_toExponential(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t f;+    int rnd_mode, radix;++    val = js_thisBigFloatValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToInt64Sat(ctx, &f, argv[0]))+        goto fail;+    if (!js_bigfloat_is_finite(ctx, val)) {+        ret = JS_ToString(ctx, val);+    } else if (JS_IsUndefined(argv[0])) {+        ret = js_ftoa(ctx, val, 10, 0,+                      BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);+    } else {+        if (f < 0 || f > BF_PREC_MAX) {+            JS_ThrowRangeError(ctx, "invalid number of digits");+            goto fail;+        }+        rnd_mode = BF_RNDNA;+        radix = 10;+        if (argc > 1) {+            rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);+            if (rnd_mode < 0)+                goto fail;+        }+        if (argc > 2) {+            radix = js_get_radix(ctx, argv[2]);+            if (radix < 0)+                goto fail;+        }+        ret = js_ftoa(ctx, val, radix, f + 1,+                      rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);+    }+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigfloat_toPrecision(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t p;+    int rnd_mode, radix;++    val = js_thisBigFloatValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_IsUndefined(argv[0]))+        goto to_string;+    if (JS_ToInt64Sat(ctx, &p, argv[0]))+        goto fail;+    if (!js_bigfloat_is_finite(ctx, val)) {+    to_string:+        ret = JS_ToString(ctx, this_val);+    } else {+        if (p < 1 || p > BF_PREC_MAX) {+            JS_ThrowRangeError(ctx, "invalid number of digits");+            goto fail;+        }+        rnd_mode = BF_RNDNA;+        radix = 10;+        if (argc > 1) {+            rnd_mode = bigfloat_get_rnd_mode(ctx, argv[1]);+            if (rnd_mode < 0)+                goto fail;+        }+        if (argc > 2) {+            radix = js_get_radix(ctx, argv[2]);+            if (radix < 0)+                goto fail;+        }+        ret = js_ftoa(ctx, val, radix, p, rnd_mode | BF_FTOA_FORMAT_FIXED);+    }+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static const JSCFunctionListEntry js_bigfloat_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_bigfloat_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_bigfloat_valueOf ),+    JS_CFUNC_DEF("toPrecision", 1, js_bigfloat_toPrecision ),+    JS_CFUNC_DEF("toFixed", 1, js_bigfloat_toFixed ),+    JS_CFUNC_DEF("toExponential", 1, js_bigfloat_toExponential ),+};++static JSValue js_bigfloat_constructor(JSContext *ctx,+                                       JSValueConst new_target,+                                       int argc, JSValueConst *argv)+{+    JSValue val;+    if (!JS_IsUndefined(new_target))+        return JS_ThrowTypeError(ctx, "not a constructor");+    if (argc == 0) {+        bf_t *r;+        val = JS_NewBigFloat(ctx);+        if (JS_IsException(val))+            return val;+        r = JS_GetBigFloat(val);+        bf_set_zero(r, 0);+    } else {+        val = JS_DupValue(ctx, argv[0]);+    redo:+        switch(JS_VALUE_GET_NORM_TAG(val)) {+        case JS_TAG_BIG_FLOAT:+            break;+        case JS_TAG_FLOAT64:+            {+                bf_t *r;+                double d = JS_VALUE_GET_FLOAT64(val);+                val = JS_NewBigFloat(ctx);+                if (JS_IsException(val))+                    break;+                r = JS_GetBigFloat(val);+                if (bf_set_float64(r, d))+                    goto fail;+            }+            break;+        case JS_TAG_INT:+            {+                bf_t *r;+                int32_t v = JS_VALUE_GET_INT(val);+                val = JS_NewBigFloat(ctx);+                if (JS_IsException(val))+                    break;+                r = JS_GetBigFloat(val);+                if (bf_set_si(r, v))+                    goto fail;+            }+            break;+        case JS_TAG_BIG_INT:+            /* We keep the full precision of the integer */+            {+                JSBigFloat *p = JS_VALUE_GET_PTR(val);+                val = JS_MKPTR(JS_TAG_BIG_FLOAT, p);+            }+            break;+        case JS_TAG_BIG_DECIMAL:+            val = JS_ToStringFree(ctx, val);+            if (JS_IsException(val))+                break;+            goto redo;+        case JS_TAG_STRING:+            {+                const char *str, *p;+                size_t len;+                int err;++                str = JS_ToCStringLen(ctx, &len, val);+                JS_FreeValue(ctx, val);+                if (!str)+                    return JS_EXCEPTION;+                p = str;+                p += skip_spaces(p);+                if ((p - str) == len) {+                    bf_t *r;+                    val = JS_NewBigFloat(ctx);+                    if (JS_IsException(val))+                        break;+                    r = JS_GetBigFloat(val);+                    bf_set_zero(r, 0);+                    err = 0;+                } else {+                    val = js_atof(ctx, p, &p, 0, ATOD_ACCEPT_BIN_OCT |+                                  ATOD_TYPE_BIG_FLOAT |+                                  ATOD_ACCEPT_PREFIX_AFTER_SIGN);+                    if (JS_IsException(val)) {+                        JS_FreeCString(ctx, str);+                        return JS_EXCEPTION;+                    }+                    p += skip_spaces(p);+                    err = ((p - str) != len);+                }+                JS_FreeCString(ctx, str);+                if (err) {+                    JS_FreeValue(ctx, val);+                    return JS_ThrowSyntaxError(ctx, "invalid bigfloat literal");+                }+            }+            break;+        case JS_TAG_OBJECT:+            val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);+            if (JS_IsException(val))+                break;+            goto redo;+        case JS_TAG_NULL:+        case JS_TAG_UNDEFINED:+        default:+            JS_FreeValue(ctx, val);+            return JS_ThrowTypeError(ctx, "cannot convert to bigfloat");+        }+    }+    return val;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigfloat_get_const(JSContext *ctx,+                                     JSValueConst this_val, int magic)+{+    bf_t *r;+    JSValue val;+    val = JS_NewBigFloat(ctx);+    if (JS_IsException(val))+        return val;+    r = JS_GetBigFloat(val);+    switch(magic) {+    case 0: /* PI */+        bf_const_pi(r, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case 1: /* LN2 */+        bf_const_log2(r, ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    case 2: /* MIN_VALUE */+    case 3: /* MAX_VALUE */+        {+            slimb_t e_range, e;+            e_range = (limb_t)1 << (bf_get_exp_bits(ctx->fp_env.flags) - 1);+            bf_set_ui(r, 1);+            if (magic == 2) {+                e = -e_range + 2;+                if (ctx->fp_env.flags & BF_FLAG_SUBNORMAL)+                    e -= ctx->fp_env.prec - 1;+                bf_mul_2exp(r, e, ctx->fp_env.prec, ctx->fp_env.flags);+            } else {+                bf_mul_2exp(r, ctx->fp_env.prec, ctx->fp_env.prec,+                            ctx->fp_env.flags);+                bf_add_si(r, r, -1, ctx->fp_env.prec, ctx->fp_env.flags);+                bf_mul_2exp(r, e_range - ctx->fp_env.prec, ctx->fp_env.prec,+                            ctx->fp_env.flags);+            }+        }+        break;+    case 4: /* EPSILON */+        bf_set_ui(r, 1);+        bf_mul_2exp(r, 1 - ctx->fp_env.prec,+                    ctx->fp_env.prec, ctx->fp_env.flags);+        break;+    default:+        abort();+    }+    return val;+}++static JSValue js_bigfloat_parseFloat(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    bf_t *a;+    const char *str;+    JSValue ret;+    int radix;+    JSFloatEnv *fe;++    str = JS_ToCString(ctx, argv[0]);+    if (!str)+        return JS_EXCEPTION;+    if (JS_ToInt32(ctx, &radix, argv[1])) {+    fail:+        JS_FreeCString(ctx, str);+        return JS_EXCEPTION;+    }+    if (radix != 0 && (radix < 2 || radix > 36)) {+        JS_ThrowRangeError(ctx, "radix must be between 2 and 36");+        goto fail;+    }+    fe = &ctx->fp_env;+    if (argc > 2) {+        fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);+        if (!fe)+            goto fail;+    }+    ret = JS_NewBigFloat(ctx);+    if (JS_IsException(ret))+        goto done;+    a = JS_GetBigFloat(ret);+    /* XXX: use js_atof() */+    bf_atof(a, str, NULL, radix, fe->prec, fe->flags);+ done:+    JS_FreeCString(ctx, str);+    return ret;+}++static JSValue js_bigfloat_isFinite(JSContext *ctx, JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValueConst val = argv[0];+    JSBigFloat *p;+    +    if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)+        return JS_FALSE;+    p = JS_VALUE_GET_PTR(val);+    return JS_NewBool(ctx, bf_is_finite(&p->num));+}++static JSValue js_bigfloat_isNaN(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValueConst val = argv[0];+    JSBigFloat *p;+    +    if (JS_VALUE_GET_NORM_TAG(val) != JS_TAG_BIG_FLOAT)+        return JS_FALSE;+    p = JS_VALUE_GET_PTR(val);+    return JS_NewBool(ctx, bf_is_nan(&p->num));+}++enum {+    MATH_OP_ABS,+    MATH_OP_FLOOR,+    MATH_OP_CEIL,+    MATH_OP_ROUND,+    MATH_OP_TRUNC,+    MATH_OP_SQRT,+    MATH_OP_FPROUND,+    MATH_OP_ACOS,+    MATH_OP_ASIN,+    MATH_OP_ATAN,+    MATH_OP_ATAN2,+    MATH_OP_COS,+    MATH_OP_EXP,+    MATH_OP_LOG,+    MATH_OP_POW,+    MATH_OP_SIN,+    MATH_OP_TAN,+    MATH_OP_FMOD,+    MATH_OP_REM,+    MATH_OP_SIGN,++    MATH_OP_ADD,+    MATH_OP_SUB,+    MATH_OP_MUL,+    MATH_OP_DIV,+};++static JSValue js_bigfloat_fop(JSContext *ctx, JSValueConst this_val,+                           int argc, JSValueConst *argv, int magic)+{+    bf_t a_s, *a, *r;+    JSFloatEnv *fe;+    int rnd_mode;+    JSValue op1, res;++    op1 = JS_ToNumeric(ctx, argv[0]);+    if (JS_IsException(op1))+        return op1;+    a = JS_ToBigFloat(ctx, &a_s, op1);+    fe = &ctx->fp_env;+    if (argc > 1) {+        fe = JS_GetOpaque2(ctx, argv[1], JS_CLASS_FLOAT_ENV);+        if (!fe)+            goto fail;+    }+    res = JS_NewBigFloat(ctx);+    if (JS_IsException(res)) {+    fail:+        if (a == &a_s)+            bf_delete(a);+        JS_FreeValue(ctx, op1);+        return JS_EXCEPTION;+    }+    r = JS_GetBigFloat(res);+    switch (magic) {+    case MATH_OP_ABS:+        bf_set(r, a);+        r->sign = 0;+        break;+    case MATH_OP_FLOOR:+        rnd_mode = BF_RNDD;+        goto rint;+    case MATH_OP_CEIL:+        rnd_mode = BF_RNDU;+        goto rint;+    case MATH_OP_ROUND:+        rnd_mode = BF_RNDNA;+        goto rint;+    case MATH_OP_TRUNC:+        rnd_mode = BF_RNDZ;+    rint:+        bf_set(r, a);+        fe->status |= bf_rint(r, rnd_mode);+        break;+    case MATH_OP_SQRT:+        fe->status |= bf_sqrt(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_FPROUND:+        bf_set(r, a);+        fe->status |= bf_round(r, fe->prec, fe->flags);+        break;+    case MATH_OP_ACOS:+        fe->status |= bf_acos(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_ASIN:+        fe->status |= bf_asin(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_ATAN:+        fe->status |= bf_atan(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_COS:+        fe->status |= bf_cos(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_EXP:+        fe->status |= bf_exp(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_LOG:+        fe->status |= bf_log(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_SIN:+        fe->status |= bf_sin(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_TAN:+        fe->status |= bf_tan(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_SIGN:+        if (bf_is_nan(a) || bf_is_zero(a)) {+            bf_set(r, a);+        } else {+            bf_set_si(r, 1 - 2 * a->sign);+        }+        break;+    default:+        abort();+    }+    if (a == &a_s)+        bf_delete(a);+    JS_FreeValue(ctx, op1);+    return res;+}++static JSValue js_bigfloat_fop2(JSContext *ctx, JSValueConst this_val,+                            int argc, JSValueConst *argv, int magic)+{+    bf_t a_s, *a, b_s, *b, r_s, *r = &r_s;+    JSFloatEnv *fe;+    JSValue op1, op2, res;++    op1 = JS_ToNumeric(ctx, argv[0]);+    if (JS_IsException(op1))+        return op1;+    op2 = JS_ToNumeric(ctx, argv[1]);+    if (JS_IsException(op2)) {+        JS_FreeValue(ctx, op1);+        return op2;+    }+    a = JS_ToBigFloat(ctx, &a_s, op1);+    b = JS_ToBigFloat(ctx, &b_s, op2);+    fe = &ctx->fp_env;+    if (argc > 2) {+        fe = JS_GetOpaque2(ctx, argv[2], JS_CLASS_FLOAT_ENV);+        if (!fe)+            goto fail;+    }+    res = JS_NewBigFloat(ctx);+    if (JS_IsException(res)) {+    fail:+        if (a == &a_s)+            bf_delete(a);+        if (b == &b_s)+            bf_delete(b);+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+        return JS_EXCEPTION;+    }+    r = JS_GetBigFloat(res);+    switch (magic) {+    case MATH_OP_ATAN2:+        fe->status |= bf_atan2(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_POW:+        fe->status |= bf_pow(r, a, b, fe->prec, fe->flags | BF_POW_JS_QUIRKS);+        break;+    case MATH_OP_FMOD:+        fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);+        break;+    case MATH_OP_REM:+        fe->status |= bf_rem(r, a, b, fe->prec, fe->flags, BF_RNDN);+        break;+    case MATH_OP_ADD:+        fe->status |= bf_add(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_SUB:+        fe->status |= bf_sub(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_MUL:+        fe->status |= bf_mul(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_DIV:+        fe->status |= bf_div(r, a, b, fe->prec, fe->flags);+        break;+    default:+        abort();+    }+    if (a == &a_s)+        bf_delete(a);+    if (b == &b_s)+        bf_delete(b);+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    return res;+}++static const JSCFunctionListEntry js_bigfloat_funcs[] = {+    JS_CGETSET_MAGIC_DEF("PI", js_bigfloat_get_const, NULL, 0 ),+    JS_CGETSET_MAGIC_DEF("LN2", js_bigfloat_get_const, NULL, 1 ),+    JS_CGETSET_MAGIC_DEF("MIN_VALUE", js_bigfloat_get_const, NULL, 2 ),+    JS_CGETSET_MAGIC_DEF("MAX_VALUE", js_bigfloat_get_const, NULL, 3 ),+    JS_CGETSET_MAGIC_DEF("EPSILON", js_bigfloat_get_const, NULL, 4 ),+    JS_CFUNC_DEF("parseFloat", 1, js_bigfloat_parseFloat ),+    JS_CFUNC_DEF("isFinite", 1, js_bigfloat_isFinite ),+    JS_CFUNC_DEF("isNaN", 1, js_bigfloat_isNaN ),+    JS_CFUNC_MAGIC_DEF("abs", 1, js_bigfloat_fop, MATH_OP_ABS ),+    JS_CFUNC_MAGIC_DEF("fpRound", 1, js_bigfloat_fop, MATH_OP_FPROUND ),+    JS_CFUNC_MAGIC_DEF("floor", 1, js_bigfloat_fop, MATH_OP_FLOOR ),+    JS_CFUNC_MAGIC_DEF("ceil", 1, js_bigfloat_fop, MATH_OP_CEIL ),+    JS_CFUNC_MAGIC_DEF("round", 1, js_bigfloat_fop, MATH_OP_ROUND ),+    JS_CFUNC_MAGIC_DEF("trunc", 1, js_bigfloat_fop, MATH_OP_TRUNC ),+    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigfloat_fop, MATH_OP_SQRT ),+    JS_CFUNC_MAGIC_DEF("acos", 1, js_bigfloat_fop, MATH_OP_ACOS ),+    JS_CFUNC_MAGIC_DEF("asin", 1, js_bigfloat_fop, MATH_OP_ASIN ),+    JS_CFUNC_MAGIC_DEF("atan", 1, js_bigfloat_fop, MATH_OP_ATAN ),+    JS_CFUNC_MAGIC_DEF("atan2", 2, js_bigfloat_fop2, MATH_OP_ATAN2 ),+    JS_CFUNC_MAGIC_DEF("cos", 1, js_bigfloat_fop, MATH_OP_COS ),+    JS_CFUNC_MAGIC_DEF("exp", 1, js_bigfloat_fop, MATH_OP_EXP ),+    JS_CFUNC_MAGIC_DEF("log", 1, js_bigfloat_fop, MATH_OP_LOG ),+    JS_CFUNC_MAGIC_DEF("pow", 2, js_bigfloat_fop2, MATH_OP_POW ),+    JS_CFUNC_MAGIC_DEF("sin", 1, js_bigfloat_fop, MATH_OP_SIN ),+    JS_CFUNC_MAGIC_DEF("tan", 1, js_bigfloat_fop, MATH_OP_TAN ),+    JS_CFUNC_MAGIC_DEF("sign", 1, js_bigfloat_fop, MATH_OP_SIGN ),+    JS_CFUNC_MAGIC_DEF("add", 2, js_bigfloat_fop2, MATH_OP_ADD ),+    JS_CFUNC_MAGIC_DEF("sub", 2, js_bigfloat_fop2, MATH_OP_SUB ),+    JS_CFUNC_MAGIC_DEF("mul", 2, js_bigfloat_fop2, MATH_OP_MUL ),+    JS_CFUNC_MAGIC_DEF("div", 2, js_bigfloat_fop2, MATH_OP_DIV ),+    JS_CFUNC_MAGIC_DEF("fmod", 2, js_bigfloat_fop2, MATH_OP_FMOD ),+    JS_CFUNC_MAGIC_DEF("remainder", 2, js_bigfloat_fop2, MATH_OP_REM ),+};++/* FloatEnv */++static JSValue js_float_env_constructor(JSContext *ctx,+                                        JSValueConst new_target,+                                        int argc, JSValueConst *argv)+{+    JSValue obj;+    JSFloatEnv *fe;+    int64_t prec;+    int flags, rndmode;++    prec = ctx->fp_env.prec;+    flags = ctx->fp_env.flags;+    if (!JS_IsUndefined(argv[0])) {+        if (JS_ToInt64Sat(ctx, &prec, argv[0]))+            return JS_EXCEPTION;+        if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)+            return JS_ThrowRangeError(ctx, "invalid precision");+        flags = BF_RNDN; /* RNDN, max exponent size, no subnormal */+        if (argc > 1 && !JS_IsUndefined(argv[1])) {+            if (JS_ToInt32Sat(ctx, &rndmode, argv[1]))+                return JS_EXCEPTION;+            if (rndmode < BF_RNDN || rndmode > BF_RNDF)+                return JS_ThrowRangeError(ctx, "invalid rounding mode");+            flags = rndmode;+        }+    }++    obj = JS_NewObjectClass(ctx, JS_CLASS_FLOAT_ENV);+    if (JS_IsException(obj))+        return JS_EXCEPTION;+    fe = js_malloc(ctx, sizeof(*fe));+    if (!fe)+        return JS_EXCEPTION;+    fe->prec = prec;+    fe->flags = flags;+    fe->status = 0;+    JS_SetOpaque(obj, fe);+    return obj;+}++static void js_float_env_finalizer(JSRuntime *rt, JSValue val)+{+    JSFloatEnv *fe = JS_GetOpaque(val, JS_CLASS_FLOAT_ENV);+    js_free_rt(rt, fe);+}++static JSValue js_float_env_get_prec(JSContext *ctx, JSValueConst this_val)+{+    return JS_NewInt64(ctx, ctx->fp_env.prec);+}++static JSValue js_float_env_get_expBits(JSContext *ctx, JSValueConst this_val)+{+    return JS_NewInt32(ctx, bf_get_exp_bits(ctx->fp_env.flags));+}++static JSValue js_float_env_setPrec(JSContext *ctx,+                                    JSValueConst this_val,+                                    int argc, JSValueConst *argv)+{+    JSValueConst func;+    int exp_bits, flags, saved_flags;+    JSValue ret;+    limb_t saved_prec;+    int64_t prec;++    func = argv[0];+    if (JS_ToInt64Sat(ctx, &prec, argv[1]))+        return JS_EXCEPTION;+    if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)+        return JS_ThrowRangeError(ctx, "invalid precision");+    exp_bits = BF_EXP_BITS_MAX;++    if (argc > 2 && !JS_IsUndefined(argv[2])) {+        if (JS_ToInt32Sat(ctx, &exp_bits, argv[2]))+            return JS_EXCEPTION;+        if (exp_bits < BF_EXP_BITS_MIN || exp_bits > BF_EXP_BITS_MAX)+            return JS_ThrowRangeError(ctx, "invalid number of exponent bits");+    }++    flags = BF_RNDN | BF_FLAG_SUBNORMAL | bf_set_exp_bits(exp_bits);++    saved_prec = ctx->fp_env.prec;+    saved_flags = ctx->fp_env.flags;++    ctx->fp_env.prec = prec;+    ctx->fp_env.flags = flags;++    ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL);+    /* always restore the floating point precision */+    ctx->fp_env.prec = saved_prec;+    ctx->fp_env.flags = saved_flags;+    return ret;+}++#define FE_PREC      (-1)+#define FE_EXP       (-2)+#define FE_RNDMODE   (-3)+#define FE_SUBNORMAL (-4)++static JSValue js_float_env_proto_get_status(JSContext *ctx, JSValueConst this_val, int magic)+{+    JSFloatEnv *fe;+    fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);+    if (!fe)+        return JS_EXCEPTION;+    switch(magic) {+    case FE_PREC:+        return JS_NewInt64(ctx, fe->prec);+    case FE_EXP:+        return JS_NewInt32(ctx, bf_get_exp_bits(fe->flags));+    case FE_RNDMODE:+        return JS_NewInt32(ctx, fe->flags & BF_RND_MASK);+    case FE_SUBNORMAL:+        return JS_NewBool(ctx, (fe->flags & BF_FLAG_SUBNORMAL) != 0);+    default:+        return JS_NewBool(ctx, (fe->status & magic) != 0);+    }+}++static JSValue js_float_env_proto_set_status(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic)+{+    JSFloatEnv *fe;+    int b;+    int64_t prec;++    fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);+    if (!fe)+        return JS_EXCEPTION;+    switch(magic) {+    case FE_PREC:+        if (JS_ToInt64Sat(ctx, &prec, val))+            return JS_EXCEPTION;+        if (prec < BF_PREC_MIN || prec > BF_PREC_MAX)+            return JS_ThrowRangeError(ctx, "invalid precision");+        fe->prec = prec;+        break;+    case FE_EXP:+        if (JS_ToInt32Sat(ctx, &b, val))+            return JS_EXCEPTION;+        if (b < BF_EXP_BITS_MIN || b > BF_EXP_BITS_MAX)+            return JS_ThrowRangeError(ctx, "invalid number of exponent bits");+        fe->flags = (fe->flags & ~(BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)) |+            bf_set_exp_bits(b);+        break;+    case FE_RNDMODE:+        b = bigfloat_get_rnd_mode(ctx, val);+        if (b < 0)+            return JS_EXCEPTION;+        fe->flags = (fe->flags & ~BF_RND_MASK) | b;+        break;+    case FE_SUBNORMAL:+        b = JS_ToBool(ctx, val);+        fe->flags = (fe->flags & ~BF_FLAG_SUBNORMAL) | (b ? BF_FLAG_SUBNORMAL: 0);+        break;+    default:+        b = JS_ToBool(ctx, val);+        fe->status = (fe->status & ~magic) & ((-b) & magic);+        break;+    }+    return JS_UNDEFINED;+}++static JSValue js_float_env_clearStatus(JSContext *ctx,+                                        JSValueConst this_val,+                                        int argc, JSValueConst *argv)+{+    JSFloatEnv *fe = JS_GetOpaque2(ctx, this_val, JS_CLASS_FLOAT_ENV);+    if (!fe)+        return JS_EXCEPTION;+    fe->status = 0;+    return JS_UNDEFINED;+}++static const JSCFunctionListEntry js_float_env_funcs[] = {+    JS_CGETSET_DEF("prec", js_float_env_get_prec, NULL ),+    JS_CGETSET_DEF("expBits", js_float_env_get_expBits, NULL ),+    JS_CFUNC_DEF("setPrec", 2, js_float_env_setPrec ),+    JS_PROP_INT32_DEF("RNDN", BF_RNDN, 0 ),+    JS_PROP_INT32_DEF("RNDZ", BF_RNDZ, 0 ),+    JS_PROP_INT32_DEF("RNDU", BF_RNDU, 0 ),+    JS_PROP_INT32_DEF("RNDD", BF_RNDD, 0 ),+    JS_PROP_INT32_DEF("RNDNA", BF_RNDNA, 0 ),+    JS_PROP_INT32_DEF("RNDA", BF_RNDA, 0 ),+    JS_PROP_INT32_DEF("RNDF", BF_RNDF, 0 ),+    JS_PROP_INT32_DEF("precMin", BF_PREC_MIN, 0 ),+    JS_PROP_INT64_DEF("precMax", BF_PREC_MAX, 0 ),+    JS_PROP_INT32_DEF("expBitsMin", BF_EXP_BITS_MIN, 0 ),+    JS_PROP_INT32_DEF("expBitsMax", BF_EXP_BITS_MAX, 0 ),+};++static const JSCFunctionListEntry js_float_env_proto_funcs[] = {+    JS_CGETSET_MAGIC_DEF("prec", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, FE_PREC ),+    JS_CGETSET_MAGIC_DEF("expBits", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, FE_EXP ),+    JS_CGETSET_MAGIC_DEF("rndMode", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, FE_RNDMODE ),+    JS_CGETSET_MAGIC_DEF("subnormal", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, FE_SUBNORMAL ),+    JS_CGETSET_MAGIC_DEF("invalidOperation", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, BF_ST_INVALID_OP ),+    JS_CGETSET_MAGIC_DEF("divideByZero", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, BF_ST_DIVIDE_ZERO ),+    JS_CGETSET_MAGIC_DEF("overflow", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, BF_ST_OVERFLOW ),+    JS_CGETSET_MAGIC_DEF("underflow", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, BF_ST_UNDERFLOW ),+    JS_CGETSET_MAGIC_DEF("inexact", js_float_env_proto_get_status,+                         js_float_env_proto_set_status, BF_ST_INEXACT ),+    JS_CFUNC_DEF("clearStatus", 0, js_float_env_clearStatus ),+};++void JS_AddIntrinsicBigFloat(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    JSValueConst obj1;+    +    rt->bigfloat_ops.to_string = js_bigfloat_to_string;+    rt->bigfloat_ops.from_string = js_string_to_bigfloat;+    rt->bigfloat_ops.unary_arith = js_unary_arith_bigfloat;+    rt->bigfloat_ops.binary_arith = js_binary_arith_bigfloat;+    rt->bigfloat_ops.compare = js_compare_bigfloat;+    rt->bigfloat_ops.mul_pow10_to_float64 = js_mul_pow10_to_float64;+    rt->bigfloat_ops.mul_pow10 = js_mul_pow10;+    +    ctx->class_proto[JS_CLASS_BIG_FLOAT] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_FLOAT],+                               js_bigfloat_proto_funcs,+                               countof(js_bigfloat_proto_funcs));+    obj1 = JS_NewGlobalCConstructor(ctx, "BigFloat", js_bigfloat_constructor, 1,+                                    ctx->class_proto[JS_CLASS_BIG_FLOAT]);+    JS_SetPropertyFunctionList(ctx, obj1, js_bigfloat_funcs,+                               countof(js_bigfloat_funcs));++    ctx->class_proto[JS_CLASS_FLOAT_ENV] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_FLOAT_ENV],+                               js_float_env_proto_funcs,+                               countof(js_float_env_proto_funcs));+    obj1 = JS_NewGlobalCConstructorOnly(ctx, "BigFloatEnv",+                                        js_float_env_constructor, 1,+                                        ctx->class_proto[JS_CLASS_FLOAT_ENV]);+    JS_SetPropertyFunctionList(ctx, obj1, js_float_env_funcs,+                               countof(js_float_env_funcs));+}++/* BigDecimal */++static JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val,+                                   BOOL allow_null_or_undefined)+{+ redo:+    switch(JS_VALUE_GET_NORM_TAG(val)) {+    case JS_TAG_BIG_DECIMAL:+        break;+    case JS_TAG_NULL:+        if (!allow_null_or_undefined)+            goto fail;+        /* fall thru */+    case JS_TAG_BOOL:+    case JS_TAG_INT:+        {+            bfdec_t *r;+            int32_t v = JS_VALUE_GET_INT(val);++            val = JS_NewBigDecimal(ctx);+            if (JS_IsException(val))+                break;+            r = JS_GetBigDecimal(val);+            if (bfdec_set_si(r, v)) {+                JS_FreeValue(ctx, val);+                val = JS_EXCEPTION;+                break;+            }+        }+        break;+    case JS_TAG_FLOAT64:+    case JS_TAG_BIG_INT:+    case JS_TAG_BIG_FLOAT:+        val = JS_ToStringFree(ctx, val);+        if (JS_IsException(val))+            break;+        goto redo;+    case JS_TAG_STRING:+        {+            const char *str, *p;+            size_t len;+            int err;++            str = JS_ToCStringLen(ctx, &len, val);+            JS_FreeValue(ctx, val);+            if (!str)+                return JS_EXCEPTION;+            p = str;+            p += skip_spaces(p);+            if ((p - str) == len) {+                bfdec_t *r;+                val = JS_NewBigDecimal(ctx);+                if (JS_IsException(val))+                    break;+                r = JS_GetBigDecimal(val);+                bfdec_set_zero(r, 0);+                err = 0;+            } else {+                val = js_atof(ctx, p, &p, 0, ATOD_TYPE_BIG_DECIMAL);+                if (JS_IsException(val)) {+                    JS_FreeCString(ctx, str);+                    return JS_EXCEPTION;+                }+                p += skip_spaces(p);+                err = ((p - str) != len);+            }+            JS_FreeCString(ctx, str);+            if (err) {+                JS_FreeValue(ctx, val);+                return JS_ThrowSyntaxError(ctx, "invalid bigdecimal literal");+            }+        }+        break;+    case JS_TAG_OBJECT:+        val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER);+        if (JS_IsException(val))+            break;+        goto redo;+    case JS_TAG_UNDEFINED:+        {+            bfdec_t *r;+            if (!allow_null_or_undefined)+                goto fail;+            val = JS_NewBigDecimal(ctx);+            if (JS_IsException(val))+                break;+            r = JS_GetBigDecimal(val);+            bfdec_set_nan(r);+        }+        break;+    default:+    fail:+        JS_FreeValue(ctx, val);+        return JS_ThrowTypeError(ctx, "cannot convert to bigdecimal");+    }+    return val;+}++static JSValue js_bigdecimal_constructor(JSContext *ctx,+                                         JSValueConst new_target,+                                         int argc, JSValueConst *argv)+{+    JSValue val;+    if (!JS_IsUndefined(new_target))+        return JS_ThrowTypeError(ctx, "not a constructor");+    if (argc == 0) {+        bfdec_t *r;+        val = JS_NewBigDecimal(ctx);+        if (JS_IsException(val))+            return val;+        r = JS_GetBigDecimal(val);+        bfdec_set_zero(r, 0);+    } else {+        val = JS_ToBigDecimalFree(ctx, JS_DupValue(ctx, argv[0]), FALSE);+    }+    return val;+}++static JSValue js_thisBigDecimalValue(JSContext *ctx, JSValueConst this_val)+{+    if (JS_IsBigDecimal(this_val))+        return JS_DupValue(ctx, this_val);++    if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) {+        JSObject *p = JS_VALUE_GET_OBJ(this_val);+        if (p->class_id == JS_CLASS_BIG_DECIMAL) {+            if (JS_IsBigDecimal(p->u.object_data))+                return JS_DupValue(ctx, p->u.object_data);+        }+    }+    return JS_ThrowTypeError(ctx, "not a bigdecimal");+}++static JSValue js_bigdecimal_toString(JSContext *ctx, JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    JSValue val;++    val = js_thisBigDecimalValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    return JS_ToStringFree(ctx, val);+}++static JSValue js_bigdecimal_valueOf(JSContext *ctx, JSValueConst this_val,+                                   int argc, JSValueConst *argv)+{+    return js_thisBigDecimalValue(ctx, this_val);+}++static int js_bigdecimal_get_rnd_mode(JSContext *ctx, JSValueConst obj)+{+    const char *str;+    size_t size;+    int rnd_mode;+    +    str = JS_ToCStringLen(ctx, &size, obj);+    if (!str)+        return -1;+    if (strlen(str) != size)+        goto invalid_rounding_mode;+    if (!strcmp(str, "floor")) {+        rnd_mode = BF_RNDD;+    } else if (!strcmp(str, "ceiling")) {+        rnd_mode = BF_RNDU;+    } else if (!strcmp(str, "down")) {+        rnd_mode = BF_RNDZ;+    } else if (!strcmp(str, "up")) {+        rnd_mode = BF_RNDA;+    } else if (!strcmp(str, "half-even")) {+        rnd_mode = BF_RNDN;+    } else if (!strcmp(str, "half-up")) {+        rnd_mode = BF_RNDNA;+    } else {+    invalid_rounding_mode:+        JS_FreeCString(ctx, str);+        JS_ThrowTypeError(ctx, "invalid rounding mode");+        return -1;+    }+    JS_FreeCString(ctx, str);+    return rnd_mode;+}++typedef struct {+    int64_t prec;+    bf_flags_t flags;+} BigDecimalEnv;++static int js_bigdecimal_get_env(JSContext *ctx, BigDecimalEnv *fe,+                                 JSValueConst obj)+{+    JSValue prop;+    int64_t val;+    BOOL has_prec;+    int rnd_mode;+    +    if (!JS_IsObject(obj)) {+        JS_ThrowTypeErrorNotAnObject(ctx);+        return -1;+    }+    prop = JS_GetProperty(ctx, obj, JS_ATOM_roundingMode);+    if (JS_IsException(prop))+        return -1;+    rnd_mode = js_bigdecimal_get_rnd_mode(ctx, prop);+    JS_FreeValue(ctx, prop);+    if (rnd_mode < 0)+        return -1;+    fe->flags = rnd_mode;+    +    prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumSignificantDigits);+    if (JS_IsException(prop))+        return -1;+    has_prec = FALSE;+    if (!JS_IsUndefined(prop)) {+        if (JS_ToInt64SatFree(ctx, &val, prop))+            return -1;+        if (val < 1 || val > BF_PREC_MAX)+            goto invalid_precision;+        fe->prec = val;+        has_prec = TRUE;+    }++    prop = JS_GetProperty(ctx, obj, JS_ATOM_maximumFractionDigits);+    if (JS_IsException(prop))+        return -1;+    if (!JS_IsUndefined(prop)) {+        if (has_prec) {+            JS_FreeValue(ctx, prop);+            JS_ThrowTypeError(ctx, "cannot provide both maximumSignificantDigits and maximumFractionDigits");+            return -1;+        }+        if (JS_ToInt64SatFree(ctx, &val, prop))+            return -1;+        if (val < 0 || val > BF_PREC_MAX) {+        invalid_precision:+            JS_ThrowTypeError(ctx, "invalid precision");+            return -1;+        }+        fe->prec = val;+        fe->flags |= BF_FLAG_RADPNT_PREC;+        has_prec = TRUE;+    }+    if (!has_prec) {+        JS_ThrowTypeError(ctx, "precision must be present");+        return -1;+    }+    return 0;+}+++static JSValue js_bigdecimal_fop(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv, int magic)+{+    bfdec_t *a, *b, r_s, *r = &r_s;+    JSValue op1, op2, res;+    BigDecimalEnv fe_s, *fe = &fe_s;+    int op_count, ret;++    if (magic == MATH_OP_SQRT ||+        magic == MATH_OP_ROUND)+        op_count = 1;+    else+        op_count = 2;+    +    op1 = JS_ToNumeric(ctx, argv[0]);+    if (JS_IsException(op1))+        return op1;+    a = JS_ToBigDecimal(ctx, op1);+    if (!a) {+        JS_FreeValue(ctx, op1);+        return JS_EXCEPTION;+    }+    if (op_count >= 2) {+        op2 = JS_ToNumeric(ctx, argv[1]);+        if (JS_IsException(op2)) {+            JS_FreeValue(ctx, op1);+            return op2;+        }+        b = JS_ToBigDecimal(ctx, op2);+        if (!b)+            goto fail;+    } else {+        op2 = JS_UNDEFINED;+        b = NULL;+    }+    fe->flags = BF_RNDZ;+    fe->prec = BF_PREC_INF;+    if (op_count < argc) {+        if (js_bigdecimal_get_env(ctx, fe, argv[op_count]))+            goto fail;+    }++    res = JS_NewBigDecimal(ctx);+    if (JS_IsException(res)) {+    fail:+        JS_FreeValue(ctx, op1);+        JS_FreeValue(ctx, op2);+        return JS_EXCEPTION;+    }+    r = JS_GetBigDecimal(res);+    switch (magic) {+    case MATH_OP_ADD:+        ret = bfdec_add(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_SUB:+        ret = bfdec_sub(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_MUL:+        ret = bfdec_mul(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_DIV:+        ret = bfdec_div(r, a, b, fe->prec, fe->flags);+        break;+    case MATH_OP_FMOD:+        ret = bfdec_rem(r, a, b, fe->prec, fe->flags, BF_RNDZ);+        break;+    case MATH_OP_SQRT:+        ret = bfdec_sqrt(r, a, fe->prec, fe->flags);+        break;+    case MATH_OP_ROUND:+        ret = bfdec_set(r, a);+        if (!(ret & BF_ST_MEM_ERROR))+            ret = bfdec_round(r, fe->prec, fe->flags);+        break;+    default:+        abort();+    }+    JS_FreeValue(ctx, op1);+    JS_FreeValue(ctx, op2);+    ret &= BF_ST_MEM_ERROR | BF_ST_DIVIDE_ZERO | BF_ST_INVALID_OP |+        BF_ST_OVERFLOW;+    if (ret != 0) {+        JS_FreeValue(ctx, res);+        return throw_bf_exception(ctx, ret);+    } else {+        return res;+    }+}++static JSValue js_bigdecimal_toFixed(JSContext *ctx, JSValueConst this_val,+                                 int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t f;+    int rnd_mode;++    val = js_thisBigDecimalValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToInt64Sat(ctx, &f, argv[0]))+        goto fail;+    if (f < 0 || f > BF_PREC_MAX) {+        JS_ThrowRangeError(ctx, "invalid number of digits");+        goto fail;+    }+    rnd_mode = BF_RNDNA;+    if (argc > 1) {+        rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);+        if (rnd_mode < 0)+            goto fail;+    }+    ret = js_bigdecimal_to_string1(ctx, val, f, rnd_mode | BF_FTOA_FORMAT_FRAC);+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigdecimal_toExponential(JSContext *ctx, JSValueConst this_val,+                                       int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t f;+    int rnd_mode;++    val = js_thisBigDecimalValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_ToInt64Sat(ctx, &f, argv[0]))+        goto fail;+    if (JS_IsUndefined(argv[0])) {+        ret = js_bigdecimal_to_string1(ctx, val, 0,+                  BF_RNDN | BF_FTOA_FORMAT_FREE_MIN | BF_FTOA_FORCE_EXP);+    } else {+        if (f < 0 || f > BF_PREC_MAX) {+            JS_ThrowRangeError(ctx, "invalid number of digits");+            goto fail;+        }+        rnd_mode = BF_RNDNA;+        if (argc > 1) {+            rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);+            if (rnd_mode < 0)+                goto fail;+        }+        ret = js_bigdecimal_to_string1(ctx, val, f + 1,+                      rnd_mode | BF_FTOA_FORMAT_FIXED | BF_FTOA_FORCE_EXP);+    }+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static JSValue js_bigdecimal_toPrecision(JSContext *ctx, JSValueConst this_val,+                                     int argc, JSValueConst *argv)+{+    JSValue val, ret;+    int64_t p;+    int rnd_mode;++    val = js_thisBigDecimalValue(ctx, this_val);+    if (JS_IsException(val))+        return val;+    if (JS_IsUndefined(argv[0])) {+        return JS_ToStringFree(ctx, val);+    }+    if (JS_ToInt64Sat(ctx, &p, argv[0]))+        goto fail;+    if (p < 1 || p > BF_PREC_MAX) {+        JS_ThrowRangeError(ctx, "invalid number of digits");+        goto fail;+    }+    rnd_mode = BF_RNDNA;+    if (argc > 1) {+        rnd_mode = js_bigdecimal_get_rnd_mode(ctx, argv[1]);+        if (rnd_mode < 0)+            goto fail;+    }+    ret = js_bigdecimal_to_string1(ctx, val, p,+                                   rnd_mode | BF_FTOA_FORMAT_FIXED);+    JS_FreeValue(ctx, val);+    return ret;+ fail:+    JS_FreeValue(ctx, val);+    return JS_EXCEPTION;+}++static const JSCFunctionListEntry js_bigdecimal_proto_funcs[] = {+    JS_CFUNC_DEF("toString", 0, js_bigdecimal_toString ),+    JS_CFUNC_DEF("valueOf", 0, js_bigdecimal_valueOf ),+    JS_CFUNC_DEF("toPrecision", 1, js_bigdecimal_toPrecision ),+    JS_CFUNC_DEF("toFixed", 1, js_bigdecimal_toFixed ),+    JS_CFUNC_DEF("toExponential", 1, js_bigdecimal_toExponential ),+};++static const JSCFunctionListEntry js_bigdecimal_funcs[] = {+    JS_CFUNC_MAGIC_DEF("add", 2, js_bigdecimal_fop, MATH_OP_ADD ),+    JS_CFUNC_MAGIC_DEF("sub", 2, js_bigdecimal_fop, MATH_OP_SUB ),+    JS_CFUNC_MAGIC_DEF("mul", 2, js_bigdecimal_fop, MATH_OP_MUL ),+    JS_CFUNC_MAGIC_DEF("div", 2, js_bigdecimal_fop, MATH_OP_DIV ),+    JS_CFUNC_MAGIC_DEF("mod", 2, js_bigdecimal_fop, MATH_OP_FMOD ),+    JS_CFUNC_MAGIC_DEF("round", 1, js_bigdecimal_fop, MATH_OP_ROUND ),+    JS_CFUNC_MAGIC_DEF("sqrt", 1, js_bigdecimal_fop, MATH_OP_SQRT ),+};++void JS_AddIntrinsicBigDecimal(JSContext *ctx)+{+    JSRuntime *rt = ctx->rt;+    JSValueConst obj1;++    rt->bigdecimal_ops.to_string = js_bigdecimal_to_string;+    rt->bigdecimal_ops.from_string = js_string_to_bigdecimal;+    rt->bigdecimal_ops.unary_arith = js_unary_arith_bigdecimal;+    rt->bigdecimal_ops.binary_arith = js_binary_arith_bigdecimal;+    rt->bigdecimal_ops.compare = js_compare_bigdecimal;++    ctx->class_proto[JS_CLASS_BIG_DECIMAL] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BIG_DECIMAL],+                               js_bigdecimal_proto_funcs,+                               countof(js_bigdecimal_proto_funcs));+    obj1 = JS_NewGlobalCConstructor(ctx, "BigDecimal",+                                    js_bigdecimal_constructor, 1,+                                    ctx->class_proto[JS_CLASS_BIG_DECIMAL]);+    JS_SetPropertyFunctionList(ctx, obj1, js_bigdecimal_funcs,+                               countof(js_bigdecimal_funcs));+}++void JS_EnableBignumExt(JSContext *ctx, BOOL enable)+{+    ctx->bignum_ext = enable;+}++#endif /* CONFIG_BIGNUM */++static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = {+    "EvalError", "RangeError", "ReferenceError",+    "SyntaxError", "TypeError", "URIError",+    "InternalError", "AggregateError",+};++/* Minimum amount of objects to be able to compile code and display+   error messages. No JSAtom should be allocated by this function. */+static void JS_AddIntrinsicBasicObjects(JSContext *ctx)+{+    JSValue proto;+    int i;++    ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL);+    ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0,+                                           JS_CFUNC_generic, 0,+                                           ctx->class_proto[JS_CLASS_OBJECT]);+    ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto);+    ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx);+#if 0+    /* these are auto-initialized from js_error_proto_funcs,+       but delaying might be a problem */+    JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_name,+                           JS_AtomToString(ctx, JS_ATOM_Error),+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+    JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ERROR], JS_ATOM_message,+                           JS_AtomToString(ctx, JS_ATOM_empty_string),+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+#endif+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ERROR],+                               js_error_proto_funcs,+                               countof(js_error_proto_funcs));++    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {+        proto = JS_NewObjectProto(ctx, ctx->class_proto[JS_CLASS_ERROR]);+        JS_DefinePropertyValue(ctx, proto, JS_ATOM_name,+                               JS_NewAtomString(ctx, native_error_name[i]),+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+        JS_DefinePropertyValue(ctx, proto, JS_ATOM_message,+                               JS_AtomToString(ctx, JS_ATOM_empty_string),+                               JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);+        ctx->native_error_proto[i] = proto;+    }++    /* the array prototype is an array */+    ctx->class_proto[JS_CLASS_ARRAY] =+        JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                               JS_CLASS_ARRAY);++    ctx->array_shape = js_new_shape2(ctx, get_proto_obj(ctx->class_proto[JS_CLASS_ARRAY]),+                                     JS_PROP_INITIAL_HASH_SIZE, 1);+    add_shape_property(ctx, &ctx->array_shape, NULL,+                       JS_ATOM_length, JS_PROP_WRITABLE | JS_PROP_LENGTH);++    /* XXX: could test it on first context creation to ensure that no+       new atoms are created in JS_AddIntrinsicBasicObjects(). It is+       necessary to avoid useless renumbering of atoms after+       JS_EvalBinary() if it is done just after+       JS_AddIntrinsicBasicObjects(). */+    //    assert(ctx->rt->atom_count == JS_ATOM_END);+}++void JS_AddIntrinsicBaseObjects(JSContext *ctx)+{+    int i;+    JSValueConst obj, number_obj;+    JSValue obj1;++    ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0);++    /* add caller and arguments properties to throw a TypeError */+    obj1 = JS_NewCFunction(ctx, js_function_proto_caller, NULL, 0);+    JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_caller, JS_UNDEFINED,+                      obj1, ctx->throw_type_error,+                      JS_PROP_HAS_GET | JS_PROP_HAS_SET |+                      JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);+    JS_DefineProperty(ctx, ctx->function_proto, JS_ATOM_arguments, JS_UNDEFINED,+                      obj1, ctx->throw_type_error,+                      JS_PROP_HAS_GET | JS_PROP_HAS_SET |+                      JS_PROP_HAS_CONFIGURABLE | JS_PROP_CONFIGURABLE);+    JS_FreeValue(ctx, obj1);+    JS_FreeValue(ctx, js_object_seal(ctx, JS_UNDEFINED, 1, (JSValueConst *)&ctx->throw_type_error, 1));++    ctx->global_obj = JS_NewObject(ctx);+    ctx->global_var_obj = JS_NewObjectProto(ctx, JS_NULL);++    /* Object */+    obj = JS_NewGlobalCConstructor(ctx, "Object", js_object_constructor, 1,+                                   ctx->class_proto[JS_CLASS_OBJECT]);+    JS_SetPropertyFunctionList(ctx, obj, js_object_funcs, countof(js_object_funcs));+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                               js_object_proto_funcs, countof(js_object_proto_funcs));++    /* Function */+    JS_SetPropertyFunctionList(ctx, ctx->function_proto, js_function_proto_funcs, countof(js_function_proto_funcs));+    ctx->function_ctor = JS_NewCFunctionMagic(ctx, js_function_constructor,+                                              "Function", 1, JS_CFUNC_constructor_or_func_magic,+                                              JS_FUNC_NORMAL);+    JS_NewGlobalCConstructor2(ctx, JS_DupValue(ctx, ctx->function_ctor), "Function",+                              ctx->function_proto);++    /* Error */+    obj1 = JS_NewCFunctionMagic(ctx, js_error_constructor,+                                "Error", 1, JS_CFUNC_constructor_or_func_magic, -1);+    JS_NewGlobalCConstructor2(ctx, obj1,+                              "Error", ctx->class_proto[JS_CLASS_ERROR]);++    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {+        JSValue func_obj;+        int n_args;+        n_args = 1 + (i == JS_AGGREGATE_ERROR);+        func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,+                                    native_error_name[i], n_args,+                                    JS_CFUNC_constructor_or_func_magic, i, obj1);+        JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],+                                  ctx->native_error_proto[i]);+    }++    /* Iterator prototype */+    ctx->iterator_proto = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->iterator_proto,+                               js_iterator_proto_funcs,+                               countof(js_iterator_proto_funcs));++    /* Array */+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY],+                               js_array_proto_funcs,+                               countof(js_array_proto_funcs));++    obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1,+                                   ctx->class_proto[JS_CLASS_ARRAY]);+    ctx->array_ctor = JS_DupValue(ctx, obj);+    JS_SetPropertyFunctionList(ctx, obj, js_array_funcs,+                               countof(js_array_funcs));++    /* XXX: create auto_initializer */+    {+        /* initialize Array.prototype[Symbol.unscopables] */+        char const unscopables[] = "copyWithin" "\0" "entries" "\0" "fill" "\0" "find" "\0"+            "findIndex" "\0" "flat" "\0" "flatMap" "\0" "includes" "\0" "keys" "\0" "values" "\0";+        const char *p = unscopables;+        obj1 = JS_NewObjectProto(ctx, JS_NULL);+        for(p = unscopables; *p; p += strlen(p) + 1) {+            JS_DefinePropertyValueStr(ctx, obj1, p, JS_TRUE, JS_PROP_C_W_E);+        }+        JS_DefinePropertyValue(ctx, ctx->class_proto[JS_CLASS_ARRAY],+                               JS_ATOM_Symbol_unscopables, obj1,+                               JS_PROP_CONFIGURABLE);+    }++    /* needed to initialize arguments[Symbol.iterator] */+    ctx->array_proto_values =+        JS_GetProperty(ctx, ctx->class_proto[JS_CLASS_ARRAY], JS_ATOM_values);++    ctx->class_proto[JS_CLASS_ARRAY_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_ARRAY_ITERATOR],+                               js_array_iterator_proto_funcs,+                               countof(js_array_iterator_proto_funcs));++    /* parseFloat and parseInteger must be defined before Number+       because of the Number.parseFloat and Number.parseInteger+       aliases */+    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs,+                               countof(js_global_funcs));++    /* Number */+    ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                                                               JS_CLASS_NUMBER);+    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_NUMBER], JS_NewInt32(ctx, 0));+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_NUMBER],+                               js_number_proto_funcs,+                               countof(js_number_proto_funcs));+    number_obj = JS_NewGlobalCConstructor(ctx, "Number", js_number_constructor, 1,+                                          ctx->class_proto[JS_CLASS_NUMBER]);+    JS_SetPropertyFunctionList(ctx, number_obj, js_number_funcs, countof(js_number_funcs));++    /* Boolean */+    ctx->class_proto[JS_CLASS_BOOLEAN] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                                                                JS_CLASS_BOOLEAN);+    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], JS_NewBool(ctx, FALSE));+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_BOOLEAN], js_boolean_proto_funcs,+                               countof(js_boolean_proto_funcs));+    JS_NewGlobalCConstructor(ctx, "Boolean", js_boolean_constructor, 1,+                             ctx->class_proto[JS_CLASS_BOOLEAN]);++    /* String */+    ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],+                                                               JS_CLASS_STRING);+    JS_SetObjectData(ctx, ctx->class_proto[JS_CLASS_STRING], JS_AtomToString(ctx, JS_ATOM_empty_string));+    obj = JS_NewGlobalCConstructor(ctx, "String", js_string_constructor, 1,+                                   ctx->class_proto[JS_CLASS_STRING]);+    JS_SetPropertyFunctionList(ctx, obj, js_string_funcs,+                               countof(js_string_funcs));+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_funcs,+                               countof(js_string_proto_funcs));++    ctx->class_proto[JS_CLASS_STRING_ITERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING_ITERATOR],+                               js_string_iterator_proto_funcs,+                               countof(js_string_iterator_proto_funcs));++    /* Math: create as autoinit object */+    js_random_init(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj));++    /* ES6 Reflect: create as autoinit object */+    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_reflect_obj, countof(js_reflect_obj));++    /* ES6 Symbol */+    ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs,+                               countof(js_symbol_proto_funcs));+    obj = JS_NewGlobalCConstructor(ctx, "Symbol", js_symbol_constructor, 0,+                                   ctx->class_proto[JS_CLASS_SYMBOL]);+    JS_SetPropertyFunctionList(ctx, obj, js_symbol_funcs,+                               countof(js_symbol_funcs));+    for(i = JS_ATOM_Symbol_toPrimitive; i < JS_ATOM_END; i++) {+        char buf[ATOM_GET_STR_BUF_SIZE];+        const char *str, *p;+        str = JS_AtomGetStr(ctx, buf, sizeof(buf), i);+        /* skip "Symbol." */+        p = strchr(str, '.');+        if (p)+            str = p + 1;+        JS_DefinePropertyValueStr(ctx, obj, str, JS_AtomToValue(ctx, i), 0);+    }++    /* ES6 Generator */+    ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto);+    JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR],+                               js_generator_proto_funcs,+                               countof(js_generator_proto_funcs));++    ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);+    obj1 = JS_NewCFunctionMagic(ctx, js_function_constructor,+                                "GeneratorFunction", 1,+                                JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR);+    JS_SetPropertyFunctionList(ctx,+                               ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],+                               js_generator_function_proto_funcs,+                               countof(js_generator_function_proto_funcs));+    JS_SetConstructor2(ctx, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],+                       ctx->class_proto[JS_CLASS_GENERATOR],+                       JS_PROP_CONFIGURABLE, JS_PROP_CONFIGURABLE);+    JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION],+                       0, JS_PROP_CONFIGURABLE);+    JS_FreeValue(ctx, obj1);++    /* global properties */+    ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1);+    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval,+                           JS_DupValue(ctx, ctx->eval_obj),+                           JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);++    JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,+                           JS_DupValue(ctx, ctx->global_obj),+                           JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);+}++/* Typed Arrays */++static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {+    0, 0, 0, 1, 1, 2, 2,+#ifdef CONFIG_BIGNUM+    3, 3, /* BigInt64Array, BigUint64Array */+#endif+    2, 3+};++static JSValue js_array_buffer_constructor3(JSContext *ctx,+                                            JSValueConst new_target,+                                            uint64_t len, JSClassID class_id,+                                            uint8_t *buf,+                                            JSFreeArrayBufferDataFunc *free_func,+                                            void *opaque, BOOL alloc_flag)+{+    JSRuntime *rt = ctx->rt;+    JSValue obj;+    JSArrayBuffer *abuf = NULL;++    obj = js_create_from_ctor(ctx, new_target, class_id);+    if (JS_IsException(obj))+        return obj;+    /* XXX: we are currently limited to 2 GB */+    if (len > INT32_MAX) {+        JS_ThrowRangeError(ctx, "invalid array buffer length");+        goto fail;+    }+    abuf = js_malloc(ctx, sizeof(*abuf));+    if (!abuf)+        goto fail;+    abuf->byte_length = len;+    if (alloc_flag) {+        if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&+            rt->sab_funcs.sab_alloc) {+            abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque,+                                                 max_int(len, 1));+            if (!abuf->data)+                goto fail;+            memset(abuf->data, 0, len);+        } else {+            /* the allocation must be done after the object creation */+            abuf->data = js_mallocz(ctx, max_int(len, 1));+            if (!abuf->data)+                goto fail;+        }+    } else {+        if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER &&+            rt->sab_funcs.sab_dup) {+            rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf);+        }+        abuf->data = buf;+    }+    init_list_head(&abuf->array_list);+    abuf->detached = FALSE;+    abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER);+    abuf->opaque = opaque;+    abuf->free_func = free_func;+    if (alloc_flag && buf)+        memcpy(abuf->data, buf, len);+    JS_SetOpaque(obj, abuf);+    return obj;+ fail:+    JS_FreeValue(ctx, obj);+    js_free(ctx, abuf);+    return JS_EXCEPTION;+}++static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr)+{+    js_free_rt(rt, ptr);+}++static JSValue js_array_buffer_constructor2(JSContext *ctx,+                                            JSValueConst new_target,+                                            uint64_t len, JSClassID class_id)+{+    return js_array_buffer_constructor3(ctx, new_target, len, class_id,+                                        NULL, js_array_buffer_free, NULL,+                                        TRUE);+}++static JSValue js_array_buffer_constructor1(JSContext *ctx,+                                            JSValueConst new_target,+                                            uint64_t len)+{+    return js_array_buffer_constructor2(ctx, new_target, len,+                                        JS_CLASS_ARRAY_BUFFER);+}++JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,+                          JSFreeArrayBufferDataFunc *free_func, void *opaque,+                          BOOL is_shared)+{+    return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,+                                        is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER,+                                        buf, free_func, opaque, FALSE);+}++/* create a new ArrayBuffer of length 'len' and copy 'buf' to it */+JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len)+{+    return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len,+                                        JS_CLASS_ARRAY_BUFFER,+                                        (uint8_t *)buf,+                                        js_array_buffer_free, NULL,+                                        TRUE);+}++static JSValue js_array_buffer_constructor(JSContext *ctx,+                                           JSValueConst new_target,+                                           int argc, JSValueConst *argv)+{+    uint64_t len;+    if (JS_ToIndex(ctx, &len, argv[0]))+        return JS_EXCEPTION;+    return js_array_buffer_constructor1(ctx, new_target, len);+}++static JSValue js_shared_array_buffer_constructor(JSContext *ctx,+                                                  JSValueConst new_target,+                                                  int argc, JSValueConst *argv)+{+    uint64_t len;+    if (JS_ToIndex(ctx, &len, argv[0]))+        return JS_EXCEPTION;+    return js_array_buffer_constructor2(ctx, new_target, len,+                                        JS_CLASS_SHARED_ARRAY_BUFFER);+}++/* also used for SharedArrayBuffer */+static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val)+{+    JSObject *p = JS_VALUE_GET_OBJ(val);+    JSArrayBuffer *abuf = p->u.array_buffer;+    if (abuf) {+        /* The ArrayBuffer finalizer may be called before the typed+           array finalizers using it, so abuf->array_list is not+           necessarily empty. */+        // assert(list_empty(&abuf->array_list));+        if (abuf->shared && rt->sab_funcs.sab_free) {+            rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data);+        } else {+            if (abuf->free_func)+                abuf->free_func(rt, abuf->opaque, abuf->data);+        }+        js_free_rt(rt, abuf);+    }+}++static JSValue js_array_buffer_isView(JSContext *ctx,+                                      JSValueConst this_val,+                                      int argc, JSValueConst *argv)+{+    JSObject *p;+    BOOL res;+    res = FALSE;+    if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_OBJECT) {+        p = JS_VALUE_GET_OBJ(argv[0]);+        if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&+            p->class_id <= JS_CLASS_DATAVIEW) {+            res = TRUE;+        }+    }+    return JS_NewBool(ctx, res);+}++static const JSCFunctionListEntry js_array_buffer_funcs[] = {+    JS_CFUNC_DEF("isView", 1, js_array_buffer_isView ),+    JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),+};++static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx)+{+    return JS_ThrowTypeError(ctx, "ArrayBuffer is detached");+}++static JSValue js_array_buffer_get_byteLength(JSContext *ctx,+                                              JSValueConst this_val,+                                              int class_id)+{+    JSArrayBuffer *abuf = JS_GetOpaque2(ctx, this_val, class_id);+    if (!abuf)+        return JS_EXCEPTION;+    /* return 0 if detached */     return JS_NewUint32(ctx, abuf->byte_length); } 
quickjs/quickjs.h view
@@ -776,7 +776,10 @@ /* '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);-JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);+/* 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 eval_flags); JSValue JS_GetGlobalObject(JSContext *ctx); int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj); int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,@@ -885,7 +888,9 @@ #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);-+/* 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); /* load the dependencies of the module 'obj'. Useful when JS_ReadObject()    returns a module. */ int JS_ResolveModule(JSContext *ctx, JSValueConst obj);