| @@ -71,6 +71,12 @@ · 70 unmodified lines |
| 71 | #define CONFIG_ATOMICS | 71 | #define CONFIG_ATOMICS |
| 72 | #endif | 72 | #endif |
| 73 | | 73 | |
| | 74 | #if !defined(EMSCRIPTEN) |
| | 75 | /* enable stack limitation */ |
| | 76 | #define CONFIG_STACK_CHECK |
| | 77 | #endif |
| | 78 | |
| | 79 | |
| 74 | /* dump object free */ | 80 | /* dump object free */ |
| 75 | //#define DUMP_FREE | 81 | //#define DUMP_FREE |
| 76 | //#define DUMP_CLOSURE | 82 | //#define DUMP_CLOSURE |
| @@ -281,7 +287,9 @@ struct JSRuntime { · 204 unmodified lines |
| 281 | void *module_loader_opaque; | 287 | void *module_loader_opaque; |
| 282 | | 288 | |
| 283 | BOOL can_block : 8; /* TRUE if Atomics.wait can block */ | 289 | BOOL can_block : 8; /* TRUE if Atomics.wait can block */ |
| 284 | | 290 | /* used to allocate, free and clone SharedArrayBuffers */ |
| | 291 | JSSharedArrayBufferFunctions sab_funcs; |
| | 292 | |
| 285 | /* Shape hash table */ | 293 | /* Shape hash table */ |
| 286 | int shape_hash_bits; | 294 | int shape_hash_bits; |
| 287 | int shape_hash_size; | 295 | int shape_hash_size; |
| @@ -392,7 +400,7 @@ typedef struct JSBigDecimal { · 104 unmodified lines |
| 392 | typedef enum { | 400 | typedef enum { |
| 393 | JS_AUTOINIT_ID_PROTOTYPE, | 401 | JS_AUTOINIT_ID_PROTOTYPE, |
| 394 | JS_AUTOINIT_ID_MODULE_NS, | 402 | JS_AUTOINIT_ID_MODULE_NS, |
| 395 | JS_AUTOINIT_ID_PROP, /* must be last */ | 403 | JS_AUTOINIT_ID_PROP, |
| 396 | } JSAutoInitIDEnum; | 404 | } JSAutoInitIDEnum; |
| 397 | | 405 | |
| 398 | /* must be large enough to have a negligible runtime cost and small | 406 | /* must be large enough to have a negligible runtime cost and small |
| @@ -625,7 +633,6 @@ typedef struct JSRegExp { · 226 unmodified lines |
| 625 | typedef struct JSProxyData { | 633 | typedef struct JSProxyData { |
| 626 | JSValue target; | 634 | JSValue target; |
| 627 | JSValue handler; | 635 | JSValue handler; |
| 628 | JSValue proto; | | |
| 629 | uint8_t is_func; | 636 | uint8_t is_func; |
| 630 | uint8_t is_revoked; | 637 | uint8_t is_revoked; |
| 631 | } JSProxyData; | 638 | } JSProxyData; |
| @@ -770,6 +777,7 @@ struct JSModuleDef { · 138 unmodified lines |
| 770 | JSValue func_obj; /* only used for JS modules */ | 777 | JSValue func_obj; /* only used for JS modules */ |
| 771 | JSModuleInitFunc *init_func; /* only used for C modules */ | 778 | JSModuleInitFunc *init_func; /* only used for C modules */ |
| 772 | BOOL resolved : 8; | 779 | BOOL resolved : 8; |
| | 780 | BOOL func_created : 8; |
| 773 | BOOL instantiated : 8; | 781 | BOOL instantiated : 8; |
| 774 | BOOL evaluated : 8; | 782 | BOOL evaluated : 8; |
| 775 | BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */ | 783 | BOOL eval_mark : 8; /* temporary use during js_evaluate_module() */ |
| @@ -799,10 +807,8 @@ typedef struct JSProperty { · 23 unmodified lines |
| 799 | struct { /* JS_PROP_AUTOINIT */ | 807 | struct { /* JS_PROP_AUTOINIT */ |
| 800 | /* in order to use only 2 pointers, we compress the realm | 808 | /* in order to use only 2 pointers, we compress the realm |
| 801 | and the init function pointer */ | 809 | and the init function pointer */ |
| 802 | union { | 810 | uintptr_t realm_and_id; /* realm and init_id (JS_AUTOINIT_ID_x) |
| 803 | JSContext *realm; /* for JS_AUTOINIT_ID_PROP */ | 811 | in the 2 low bits */ |
| 804 | uintptr_t init_id; /* JS_AUTOINIT_ID_x */ | | |
| 805 | } u; | | |
| 806 | void *opaque; | 812 | void *opaque; |
| 807 | } init; | 813 | } init; |
| 808 | } u; | 814 | } u; |
| @@ -832,11 +838,13 @@ struct JSShape { · 23 unmodified lines |
| 832 | uint32_t hash; /* current hash value */ | 838 | uint32_t hash; /* current hash value */ |
| 833 | uint32_t prop_hash_mask; | 839 | uint32_t prop_hash_mask; |
| 834 | int prop_size; /* allocated properties */ | 840 | int prop_size; /* allocated properties */ |
| 835 | int prop_count; | 841 | int prop_count; /* include deleted properties */ |
| | 842 | int deleted_prop_count; |
| 836 | JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ | 843 | JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ |
| 837 | JSObject *proto; | 844 | JSObject *proto; |
| 838 | JSShapeProperty prop[0]; /* prop_size elements */ | 845 | JSShapeProperty prop[0]; /* prop_size elements */ |
| 839 | }; | 846 | }; |
| | 847 | |
| 840 | struct JSObject { | 848 | struct JSObject { |
| 841 | union { | 849 | union { |
| 842 | JSGCObjectHeader header; | 850 | JSGCObjectHeader header; |
| @@ -850,7 +858,6 @@ struct JSObject { · 7 unmodified lines |
| 850 | uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */ | 858 | uint8_t fast_array : 1; /* TRUE if u.array is used for get/put */ |
| 851 | uint8_t is_constructor : 1; /* TRUE if object is a constructor function */ | 859 | uint8_t is_constructor : 1; /* TRUE if object is a constructor function */ |
| 852 | uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */ | 860 | uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */ |
| 853 | uint8_t is_class : 1; /* TRUE if object is a class constructor */ | | |
| 854 | uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ | 861 | uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ |
| 855 | uint16_t class_id; /* see JS_CLASS_x */ | 862 | uint16_t class_id; /* see JS_CLASS_x */ |
| 856 | }; | 863 | }; |
| @@ -1124,7 +1131,7 @@ static bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val); · 267 unmodified lines |
| 1124 | #endif | 1131 | #endif |
| 1125 | JSValue JS_ThrowOutOfMemory(JSContext *ctx); | 1132 | JSValue JS_ThrowOutOfMemory(JSContext *ctx); |
| 1126 | static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); | 1133 | static JSValue JS_ThrowTypeErrorRevokedProxy(JSContext *ctx); |
| 1127 | static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); | 1134 | static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); |
| 1128 | static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, | 1135 | static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, |
| 1129 | JSValueConst proto_val, BOOL throw_flag); | 1136 | JSValueConst proto_val, BOOL throw_flag); |
| 1130 | static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); | 1137 | static int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); |
| @@ -1136,6 +1143,17 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, · 5 unmodified lines |
| 1136 | int flags); | 1143 | int flags); |
| 1137 | static int js_string_memcmp(const JSString *p1, const JSString *p2, int len); | 1144 | static int js_string_memcmp(const JSString *p1, const JSString *p2, int len); |
| 1138 | static void reset_weak_ref(JSRuntime *rt, JSObject *p); | 1145 | static void reset_weak_ref(JSRuntime *rt, JSObject *p); |
| | 1146 | static JSValue js_array_buffer_constructor3(JSContext *ctx, |
| | 1147 | JSValueConst new_target, |
| | 1148 | uint64_t len, JSClassID class_id, |
| | 1149 | uint8_t *buf, |
| | 1150 | JSFreeArrayBufferDataFunc *free_func, |
| | 1151 | void *opaque, BOOL alloc_flag); |
| | 1152 | static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); |
| | 1153 | static JSValue js_typed_array_constructor(JSContext *ctx, |
| | 1154 | JSValueConst this_val, |
| | 1155 | int argc, JSValueConst *argv, |
| | 1156 | int classid); |
| 1139 | static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p); | 1157 | static BOOL typed_array_is_detached(JSContext *ctx, JSObject *p); |
| 1140 | static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p); | 1158 | static uint32_t typed_array_get_length(JSContext *ctx, JSObject *p); |
| 1141 | static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); | 1159 | static JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext *ctx); |
| @@ -1212,6 +1230,7 @@ static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom, · 70 unmodified lines |
| 1212 | void *opaque); | 1230 | void *opaque); |
| 1213 | static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p, | 1231 | static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p, |
| 1214 | JSAtom atom, void *opaque); | 1232 | JSAtom atom, void *opaque); |
| | 1233 | void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag); |
| 1215 | | 1234 | |
| 1216 | static const JSClassExoticMethods js_arguments_exotic_methods; | 1235 | static const JSClassExoticMethods js_arguments_exotic_methods; |
| 1217 | static const JSClassExoticMethods js_string_exotic_methods; | 1236 | static const JSClassExoticMethods js_string_exotic_methods; |
| @@ -1361,6 +1380,33 @@ char *js_strdup(JSContext *ctx, const char *str) · 143 unmodified lines |
| 1361 | return js_strndup(ctx, str, strlen(str)); | 1380 | return js_strndup(ctx, str, strlen(str)); |
| 1362 | } | 1381 | } |
| 1363 | | 1382 | |
| | 1383 | static no_inline int js_realloc_array(JSContext *ctx, void **parray, |
| | 1384 | int elem_size, int *psize, int req_size) |
| | 1385 | { |
| | 1386 | int new_size; |
| | 1387 | size_t slack; |
| | 1388 | void *new_array; |
| | 1389 | /* XXX: potential arithmetic overflow */ |
| | 1390 | new_size = max_int(req_size, *psize * 3 / 2); |
| | 1391 | new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack); |
| | 1392 | if (!new_array) |
| | 1393 | return -1; |
| | 1394 | new_size += slack / elem_size; |
| | 1395 | *psize = new_size; |
| | 1396 | *parray = new_array; |
| | 1397 | return 0; |
| | 1398 | } |
| | 1399 | |
| | 1400 | /* resize the array and update its size if req_size > *psize */ |
| | 1401 | static inline int js_resize_array(JSContext *ctx, void **parray, int elem_size, |
| | 1402 | int *psize, int req_size) |
| | 1403 | { |
| | 1404 | if (unlikely(req_size > *psize)) |
| | 1405 | return js_realloc_array(ctx, parray, elem_size, psize, req_size); |
| | 1406 | else |
| | 1407 | return 0; |
| | 1408 | } |
| | 1409 | |
| 1364 | static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) | 1410 | static inline void js_dbuf_init(JSContext *ctx, DynBuf *s) |
| 1365 | { | 1411 | { |
| 1366 | dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt); | 1412 | dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt); |
| @@ -1379,7 +1425,7 @@ typedef struct JSClassShortDef { · 12 unmodified lines |
| 1379 | static JSClassShortDef const js_std_class_def[] = { | 1425 | static JSClassShortDef const js_std_class_def[] = { |
| 1380 | { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */ | 1426 | { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */ |
| 1381 | { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */ | 1427 | { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */ |
| 1382 | { JS_ATOM_Error, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_ERROR */ | 1428 | { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */ |
| 1383 | { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */ | 1429 | { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */ |
| 1384 | { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */ | 1430 | { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */ |
| 1385 | { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ | 1431 | { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ |
| @@ -1426,7 +1472,7 @@ static JSClassShortDef const js_std_class_def[] = { · 40 unmodified lines |
| 1426 | { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */ | 1472 | { JS_ATOM_Set_Iterator, js_map_iterator_finalizer, js_map_iterator_mark }, /* JS_CLASS_SET_ITERATOR */ |
| 1427 | { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */ | 1473 | { JS_ATOM_Array_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_ARRAY_ITERATOR */ |
| 1428 | { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ | 1474 | { JS_ATOM_String_Iterator, js_array_iterator_finalizer, js_array_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ |
| 1429 | { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_STRING_ITERATOR */ | 1475 | { JS_ATOM_RegExp_String_Iterator, js_regexp_string_iterator_finalizer, js_regexp_string_iterator_mark }, /* JS_CLASS_REGEXP_STRING_ITERATOR */ |
| 1430 | { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */ | 1476 | { JS_ATOM_Generator, js_generator_finalizer, js_generator_mark }, /* JS_CLASS_GENERATOR */ |
| 1431 | }; | 1477 | }; |
| 1432 | | 1478 | |
| @@ -1505,8 +1551,8 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops) · 72 unmodified lines |
| 1505 | | 1551 | |
| 1506 | #endif /* CONFIG_BIGNUM */ | 1552 | #endif /* CONFIG_BIGNUM */ |
| 1507 | | 1553 | |
| 1508 | #if defined(EMSCRIPTEN) | 1554 | #if !defined(CONFIG_STACK_CHECK) |
| 1509 | /* currently no stack limitation */ | 1555 | /* no stack limitation */ |
| 1510 | static inline uint8_t *js_get_stack_pointer(void) | 1556 | static inline uint8_t *js_get_stack_pointer(void) |
| 1511 | { | 1557 | { |
| 1512 | return NULL; | 1558 | return NULL; |
| @@ -1729,6 +1775,12 @@ void JS_SetCanBlock(JSRuntime *rt, BOOL can_block) · 216 unmodified lines |
| 1729 | rt->can_block = can_block; | 1775 | rt->can_block = can_block; |
| 1730 | } | 1776 | } |
| 1731 | | 1777 | |
| | 1778 | void JS_SetSharedArrayBufferFunctions(JSRuntime *rt, |
| | 1779 | const JSSharedArrayBufferFunctions *sf) |
| | 1780 | { |
| | 1781 | rt->sab_funcs = *sf; |
| | 1782 | } |
| | 1783 | |
| 1732 | /* return 0 if OK, < 0 if exception */ | 1784 | /* return 0 if OK, < 0 if exception */ |
| 1733 | int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, | 1785 | int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, |
| 1734 | int argc, JSValueConst *argv) | 1786 | int argc, JSValueConst *argv) |
| @@ -4262,9 +4314,10 @@ static no_inline JSShape *js_new_shape2(JSContext *ctx, JSObject *proto, · 2527 unmodified lines |
| 4262 | memset(sh->prop_hash_end - hash_size, 0, sizeof(sh->prop_hash_end[0]) * | 4314 | memset(sh->prop_hash_end - hash_size, 0, sizeof(sh->prop_hash_end[0]) * |
| 4263 | hash_size); | 4315 | hash_size); |
| 4264 | sh->prop_hash_mask = hash_size - 1; | 4316 | sh->prop_hash_mask = hash_size - 1; |
| 4265 | sh->prop_count = 0; | | |
| 4266 | sh->prop_size = prop_size; | 4317 | sh->prop_size = prop_size; |
| 4267 | | 4318 | sh->prop_count = 0; |
| | 4319 | sh->deleted_prop_count = 0; |
| | 4320 | |
| 4268 | /* insert in the hash table */ | 4321 | /* insert in the hash table */ |
| 4269 | sh->hash = shape_initial_hash(proto); | 4322 | sh->hash = shape_initial_hash(proto); |
| 4270 | sh->is_hashed = TRUE; | 4323 | sh->is_hashed = TRUE; |
| @@ -4415,6 +4468,74 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, · 144 unmodified lines |
| 4415 | return 0; | 4468 | return 0; |
| 4416 | } | 4469 | } |
| 4417 | | 4470 | |
| | 4471 | /* remove the deleted properties. */ |
| | 4472 | static int compact_properties(JSContext *ctx, JSObject *p) |
| | 4473 | { |
| | 4474 | JSShape *sh, *old_sh; |
| | 4475 | void *sh_alloc; |
| | 4476 | intptr_t h; |
| | 4477 | uint32_t new_hash_size, i, j, new_hash_mask, new_size; |
| | 4478 | JSShapeProperty *old_pr, *pr; |
| | 4479 | JSProperty *prop, *new_prop; |
| | 4480 | |
| | 4481 | sh = p->shape; |
| | 4482 | assert(!sh->is_hashed); |
| | 4483 | |
| | 4484 | new_size = max_int(JS_PROP_INITIAL_SIZE, |
| | 4485 | sh->prop_count - sh->deleted_prop_count); |
| | 4486 | assert(new_size <= sh->prop_size); |
| | 4487 | |
| | 4488 | new_hash_size = sh->prop_hash_mask + 1; |
| | 4489 | while ((new_hash_size / 2) >= new_size) |
| | 4490 | new_hash_size = new_hash_size / 2; |
| | 4491 | new_hash_mask = new_hash_size - 1; |
| | 4492 | |
| | 4493 | /* resize the hash table and the properties */ |
| | 4494 | old_sh = sh; |
| | 4495 | sh_alloc = js_malloc(ctx, get_shape_size(new_hash_size, new_size)); |
| | 4496 | if (!sh_alloc) |
| | 4497 | return -1; |
| | 4498 | sh = get_shape_from_alloc(sh_alloc, new_hash_size); |
| | 4499 | list_del(&old_sh->header.link); |
| | 4500 | memcpy(sh, old_sh, sizeof(JSShape)); |
| | 4501 | list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); |
| | 4502 | |
| | 4503 | memset(sh->prop_hash_end - new_hash_size, 0, |
| | 4504 | sizeof(sh->prop_hash_end[0]) * new_hash_size); |
| | 4505 | |
| | 4506 | j = 0; |
| | 4507 | old_pr = old_sh->prop; |
| | 4508 | pr = sh->prop; |
| | 4509 | prop = p->prop; |
| | 4510 | for(i = 0; i < sh->prop_count; i++) { |
| | 4511 | if (old_pr->atom != JS_ATOM_NULL) { |
| | 4512 | pr->atom = old_pr->atom; |
| | 4513 | pr->flags = old_pr->flags; |
| | 4514 | h = ((uintptr_t)old_pr->atom & new_hash_mask); |
| | 4515 | pr->hash_next = sh->prop_hash_end[-h - 1]; |
| | 4516 | sh->prop_hash_end[-h - 1] = j + 1; |
| | 4517 | prop[j] = prop[i]; |
| | 4518 | j++; |
| | 4519 | pr++; |
| | 4520 | } |
| | 4521 | old_pr++; |
| | 4522 | } |
| | 4523 | assert(j == (sh->prop_count - sh->deleted_prop_count)); |
| | 4524 | sh->prop_hash_mask = new_hash_mask; |
| | 4525 | sh->prop_size = new_size; |
| | 4526 | sh->deleted_prop_count = 0; |
| | 4527 | sh->prop_count = j; |
| | 4528 | |
| | 4529 | p->shape = sh; |
| | 4530 | js_free(ctx, get_alloc_from_shape(old_sh)); |
| | 4531 | |
| | 4532 | /* reduce the size of the object properties */ |
| | 4533 | new_prop = js_realloc(ctx, p->prop, sizeof(new_prop[0]) * new_size); |
| | 4534 | if (new_prop) |
| | 4535 | p->prop = new_prop; |
| | 4536 | return 0; |
| | 4537 | } |
| | 4538 | |
| 4418 | static int add_shape_property(JSContext *ctx, JSShape **psh, | 4539 | static int add_shape_property(JSContext *ctx, JSShape **psh, |
| 4419 | JSObject *p, JSAtom atom, int prop_flags) | 4540 | JSObject *p, JSAtom atom, int prop_flags) |
| 4420 | { | 4541 | { |
| @@ -4571,7 +4692,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 150 unmodified lines |
| 4571 | p->fast_array = 0; | 4692 | p->fast_array = 0; |
| 4572 | p->is_constructor = 0; | 4693 | p->is_constructor = 0; |
| 4573 | p->is_uncatchable_error = 0; | 4694 | p->is_uncatchable_error = 0; |
| 4574 | p->is_class = 0; | | |
| 4575 | p->tmp_mark = 0; | 4695 | p->tmp_mark = 0; |
| 4576 | p->first_weak_ref = NULL; | 4696 | p->first_weak_ref = NULL; |
| 4577 | p->u.opaque = NULL; | 4697 | p->u.opaque = NULL; |
| @@ -4621,7 +4741,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas · 43 unmodified lines |
| 4621 | p->u.array.u.ptr = NULL; | 4741 | p->u.array.u.ptr = NULL; |
| 4622 | p->u.array.count = 0; | 4742 | p->u.array.count = 0; |
| 4623 | break; | 4743 | break; |
| 4624 | case JS_CLASS_ERROR: | | |
| 4625 | case JS_CLASS_NUMBER: | 4744 | case JS_CLASS_NUMBER: |
| 4626 | case JS_CLASS_STRING: | 4745 | case JS_CLASS_STRING: |
| 4627 | case JS_CLASS_BOOLEAN: | 4746 | case JS_CLASS_BOOLEAN: |
| @@ -4967,19 +5086,25 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func, · 339 unmodified lines |
| 4967 | return func_obj; | 5086 | return func_obj; |
| 4968 | } | 5087 | } |
| 4969 | | 5088 | |
| | 5089 | static JSContext *js_autoinit_get_realm(JSProperty *pr) |
| | 5090 | { |
| | 5091 | return (JSContext *)(pr->u.init.realm_and_id & ~3); |
| | 5092 | } |
| | 5093 | |
| | 5094 | static JSAutoInitIDEnum js_autoinit_get_id(JSProperty *pr) |
| | 5095 | { |
| | 5096 | return pr->u.init.realm_and_id & 3; |
| | 5097 | } |
| | 5098 | |
| 4970 | static void js_autoinit_free(JSRuntime *rt, JSProperty *pr) | 5099 | static void js_autoinit_free(JSRuntime *rt, JSProperty *pr) |
| 4971 | { | 5100 | { |
| 4972 | if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) { | 5101 | JS_FreeContext(js_autoinit_get_realm(pr)); |
| 4973 | JS_FreeContext(pr->u.init.u.realm); | | |
| 4974 | } | | |
| 4975 | } | 5102 | } |
| 4976 | | 5103 | |
| 4977 | static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr, | 5104 | static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr, |
| 4978 | JS_MarkFunc *mark_func) | 5105 | JS_MarkFunc *mark_func) |
| 4979 | { | 5106 | { |
| 4980 | if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) { | 5107 | mark_func(rt, &js_autoinit_get_realm(pr)->header); |
| 4981 | mark_func(rt, &pr->u.init.u.realm->header); | | |
| 4982 | } | | |
| 4983 | } | 5108 | } |
| 4984 | | 5109 | |
| 4985 | static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags) | 5110 | static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags) |
| @@ -6331,7 +6456,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, · 1345 unmodified lines |
| 6331 | backtrace_barrier = FALSE; | 6456 | backtrace_barrier = FALSE; |
| 6332 | if (js_class_has_bytecode(p->class_id)) { | 6457 | if (js_class_has_bytecode(p->class_id)) { |
| 6333 | JSFunctionBytecode *b; | 6458 | JSFunctionBytecode *b; |
| 6334 | char atom_buf[ATOM_GET_STR_BUF_SIZE]; | 6459 | const char *atom_str; |
| 6335 | int line_num1; | 6460 | int line_num1; |
| 6336 | | 6461 | |
| 6337 | b = p->u.func.function_bytecode; | 6462 | b = p->u.func.function_bytecode; |
| @@ -6339,9 +6464,10 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj, · 1 unmodified line |
| 6339 | if (b->has_debug) { | 6464 | if (b->has_debug) { |
| 6340 | line_num1 = find_line_num(ctx, b, | 6465 | line_num1 = find_line_num(ctx, b, |
| 6341 | sf->cur_pc - b->byte_code_buf - 1); | 6466 | sf->cur_pc - b->byte_code_buf - 1); |
| | 6467 | atom_str = JS_AtomToCString(ctx, b->debug.filename); |
| 6342 | dbuf_printf(&dbuf, " (%s", | 6468 | dbuf_printf(&dbuf, " (%s", |
| 6343 | JS_AtomGetStr(ctx, atom_buf, sizeof(atom_buf), | 6469 | atom_str ? atom_str : "<null>"); |
| 6344 | b->debug.filename)); | 6470 | JS_FreeCString(ctx, atom_str); |
| 6345 | if (line_num1 != -1) | 6471 | if (line_num1 != -1) |
| 6346 | dbuf_printf(&dbuf, ":%d", line_num1); | 6472 | dbuf_printf(&dbuf, ":%d", line_num1); |
| 6347 | dbuf_putc(&dbuf, ')'); | 6473 | dbuf_putc(&dbuf, ')'); |
| @@ -6459,13 +6585,32 @@ static int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSCont · 111 unmodified lines |
| 6459 | } | 6585 | } |
| 6460 | } | 6586 | } |
| 6461 | | 6587 | |
| | 6588 | /* never use it directly */ |
| | 6589 | static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...) |
| | 6590 | { |
| | 6591 | char buf[ATOM_GET_STR_BUF_SIZE]; |
| | 6592 | return JS_ThrowTypeError(ctx, fmt, |
| | 6593 | JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); |
| | 6594 | } |
| | 6595 | |
| | 6596 | /* never use it directly */ |
| | 6597 | static JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext *ctx, JSAtom atom, const char *fmt, ...) |
| | 6598 | { |
| | 6599 | char buf[ATOM_GET_STR_BUF_SIZE]; |
| | 6600 | return JS_ThrowSyntaxError(ctx, fmt, |
| | 6601 | JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); |
| | 6602 | } |
| | 6603 | |
| | 6604 | /* %s is replaced by 'atom'. The macro is used so that gcc can check |
| | 6605 | the format string. */ |
| | 6606 | #define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "") |
| | 6607 | #define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "") |
| | 6608 | |
| 6462 | static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) | 6609 | static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int flags, JSAtom atom) |
| 6463 | { | 6610 | { |
| 6464 | if ((flags & JS_PROP_THROW) || | 6611 | if ((flags & JS_PROP_THROW) || |
| 6465 | ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { | 6612 | ((flags & JS_PROP_THROW_STRICT) && is_strict_mode(ctx))) { |
| 6466 | char buf[ATOM_GET_STR_BUF_SIZE]; | 6613 | JS_ThrowTypeErrorAtom(ctx, "'%s' is read-only", atom); |
| 6467 | JS_ThrowTypeError(ctx, "%s is read-only", | | |
| 6468 | JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); | | |
| 6469 | return -1; | 6614 | return -1; |
| 6470 | } else { | 6615 | } else { |
| 6471 | return FALSE; | 6616 | return FALSE; |
| @@ -6534,7 +6679,7 @@ static JSValue JS_ThrowTypeErrorNotASymbol(JSContext *ctx) · 62 unmodified lines |
| 6534 | static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name) | 6679 | static JSValue JS_ThrowReferenceErrorNotDefined(JSContext *ctx, JSAtom name) |
| 6535 | { | 6680 | { |
| 6536 | char buf[ATOM_GET_STR_BUF_SIZE]; | 6681 | char buf[ATOM_GET_STR_BUF_SIZE]; |
| 6537 | return JS_ThrowReferenceError(ctx, "%s is not defined", | 6682 | return JS_ThrowReferenceError(ctx, "'%s' is not defined", |
| 6538 | JS_AtomGetStr(ctx, buf, sizeof(buf), name)); | 6683 | JS_AtomGetStr(ctx, buf, sizeof(buf), name)); |
| 6539 | } | 6684 | } |
| 6540 | | 6685 | |
| @@ -6549,11 +6694,33 @@ static JSValue JS_ThrowReferenceErrorUninitialized(JSContext *ctx, JSAtom name) · 8 unmodified lines |
| 6549 | static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id) | 6694 | static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id) |
| 6550 | { | 6695 | { |
| 6551 | JSRuntime *rt = ctx->rt; | 6696 | JSRuntime *rt = ctx->rt; |
| 6552 | char buf[ATOM_GET_STR_BUF_SIZE]; | | |
| 6553 | JSAtom name; | 6697 | JSAtom name; |
| 6554 | name = rt->class_array[class_id].class_name; | 6698 | name = rt->class_array[class_id].class_name; |
| 6555 | return JS_ThrowTypeError(ctx, "%s object expected", | 6699 | return JS_ThrowTypeErrorAtom(ctx, "%s object expected", name); |
| 6556 | JS_AtomGetStr(ctx, buf, sizeof(buf), name)); | 6700 | } |
| | 6701 | |
| | 6702 | static no_inline __exception int __js_poll_interrupts(JSContext *ctx) |
| | 6703 | { |
| | 6704 | JSRuntime *rt = ctx->rt; |
| | 6705 | ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT; |
| | 6706 | if (rt->interrupt_handler) { |
| | 6707 | if (rt->interrupt_handler(rt, rt->interrupt_opaque)) { |
| | 6708 | /* XXX: should set a specific flag to avoid catching */ |
| | 6709 | JS_ThrowInternalError(ctx, "interrupted"); |
| | 6710 | JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE); |
| | 6711 | return -1; |
| | 6712 | } |
| | 6713 | } |
| | 6714 | return 0; |
| | 6715 | } |
| | 6716 | |
| | 6717 | static inline __exception int js_poll_interrupts(JSContext *ctx) |
| | 6718 | { |
| | 6719 | if (unlikely(--ctx->interrupt_counter <= 0)) { |
| | 6720 | return __js_poll_interrupts(ctx); |
| | 6721 | } else { |
| | 6722 | return 0; |
| | 6723 | } |
| 6557 | } | 6724 | } |
| 6558 | | 6725 | |
| 6559 | /* return -1 (exception) or TRUE/FALSE */ | 6726 | /* return -1 (exception) or TRUE/FALSE */ |
| @@ -6633,11 +6800,9 @@ int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val) · 73 unmodified lines |
| 6633 | return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE); | 6800 | return JS_SetPrototypeInternal(ctx, obj, proto_val, TRUE); |
| 6634 | } | 6801 | } |
| 6635 | | 6802 | |
| 6636 | /* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */ | 6803 | /* Only works for primitive types, otherwise return JS_NULL. */ |
| 6637 | JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val) | 6804 | static JSValueConst JS_GetPrototypePrimitive(JSContext *ctx, JSValueConst val) |
| 6638 | { | 6805 | { |
| 6639 | JSObject *p; | | |
| 6640 | | | |
| 6641 | switch(JS_VALUE_GET_NORM_TAG(val)) { | 6806 | switch(JS_VALUE_GET_NORM_TAG(val)) { |
| 6642 | #ifdef CONFIG_BIGNUM | 6807 | #ifdef CONFIG_BIGNUM |
| 6643 | case JS_TAG_BIG_INT: | 6808 | case JS_TAG_BIG_INT: |
| @@ -6664,26 +6829,45 @@ JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val) · 20 unmodified lines |
| 6664 | val = ctx->class_proto[JS_CLASS_SYMBOL]; | 6829 | val = ctx->class_proto[JS_CLASS_SYMBOL]; |
| 6665 | break; | 6830 | break; |
| 6666 | case JS_TAG_OBJECT: | 6831 | case JS_TAG_OBJECT: |
| 6667 | p = JS_VALUE_GET_OBJ(val); | 6832 | case JS_TAG_NULL: |
| | 6833 | case JS_TAG_UNDEFINED: |
| | 6834 | default: |
| | 6835 | val = JS_NULL; |
| | 6836 | break; |
| | 6837 | } |
| | 6838 | return val; |
| | 6839 | } |
| | 6840 | |
| | 6841 | /* Return an Object, JS_NULL or JS_EXCEPTION in case of Proxy object. */ |
| | 6842 | JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) |
| | 6843 | { |
| | 6844 | JSValue val; |
| | 6845 | if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { |
| | 6846 | JSObject *p; |
| | 6847 | p = JS_VALUE_GET_OBJ(obj); |
| 6668 | if (unlikely(p->class_id == JS_CLASS_PROXY)) { | 6848 | if (unlikely(p->class_id == JS_CLASS_PROXY)) { |
| 6669 | val = js_proxy_getPrototypeOf(ctx, val); | 6849 | val = js_proxy_getPrototypeOf(ctx, obj); |
| 6670 | } else { | 6850 | } else { |
| 6671 | p = p->shape->proto; | 6851 | p = p->shape->proto; |
| 6672 | if (!p) | 6852 | if (!p) |
| 6673 | val = JS_NULL; | 6853 | val = JS_NULL; |
| 6674 | else | 6854 | else |
| 6675 | val = JS_MKPTR(JS_TAG_OBJECT, p); | 6855 | val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| 6676 | } | 6856 | } |
| 6677 | break; | 6857 | } else { |
| 6678 | case JS_TAG_NULL: | 6858 | val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj)); |
| 6679 | case JS_TAG_UNDEFINED: | | |
| 6680 | default: | | |
| 6681 | val = JS_NULL; | | |
| 6682 | break; | | |
| 6683 | } | 6859 | } |
| 6684 | return val; | 6860 | return val; |
| 6685 | } | 6861 | } |
| 6686 | | 6862 | |
| | 6863 | static JSValue JS_GetPrototypeFree(JSContext *ctx, JSValue obj) |
| | 6864 | { |
| | 6865 | JSValue obj1; |
| | 6866 | obj1 = JS_GetPrototype(ctx, obj); |
| | 6867 | JS_FreeValue(ctx, obj); |
| | 6868 | return obj1; |
| | 6869 | } |
| | 6870 | |
| 6687 | /* return TRUE, FALSE or (-1) in case of exception */ | 6871 | /* return TRUE, FALSE or (-1) in case of exception */ |
| 6688 | static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, | 6872 | static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, |
| 6689 | JSValueConst obj) | 6873 | JSValueConst obj) |
| @@ -6704,7 +6888,6 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, · 14 unmodified lines |
| 6704 | /* Only explicitly boxed values are instances of constructors */ | 6888 | /* Only explicitly boxed values are instances of constructors */ |
| 6705 | if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) | 6889 | if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) |
| 6706 | return FALSE; | 6890 | return FALSE; |
| 6707 | ret = FALSE; | | |
| 6708 | obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype); | 6891 | obj_proto = JS_GetProperty(ctx, obj, JS_ATOM_prototype); |
| 6709 | if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) { | 6892 | if (JS_VALUE_GET_TAG(obj_proto) != JS_TAG_OBJECT) { |
| 6710 | if (!JS_IsException(obj_proto)) | 6893 | if (!JS_IsException(obj_proto)) |
| @@ -6717,19 +6900,36 @@ static int JS_OrdinaryIsInstanceOf(JSContext *ctx, JSValueConst val, · 6 unmodified lines |
| 6717 | for(;;) { | 6900 | for(;;) { |
| 6718 | proto1 = p->shape->proto; | 6901 | proto1 = p->shape->proto; |
| 6719 | if (!proto1) { | 6902 | if (!proto1) { |
| 6720 | if (p->class_id == JS_CLASS_PROXY) { | 6903 | /* slow case if proxy in the prototype chain */ |
| 6721 | JSValueConst proto_val; | 6904 | if (unlikely(p->class_id == JS_CLASS_PROXY)) { |
| 6722 | proto_val = JS_GetPrototype(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); | 6905 | JSValue obj1; |
| 6723 | if (JS_IsException(proto_val)) { | 6906 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)p)); |
| 6724 | ret = -1; | 6907 | for(;;) { |
| 6725 | goto done; | 6908 | obj1 = JS_GetPrototypeFree(ctx, obj1); |
| | 6909 | if (JS_IsException(obj1)) { |
| | 6910 | ret = -1; |
| | 6911 | break; |
| | 6912 | } |
| | 6913 | if (JS_IsNull(obj1)) { |
| | 6914 | ret = FALSE; |
| | 6915 | break; |
| | 6916 | } |
| | 6917 | if (proto == JS_VALUE_GET_OBJ(obj1)) { |
| | 6918 | JS_FreeValue(ctx, obj1); |
| | 6919 | ret = TRUE; |
| | 6920 | break; |
| | 6921 | } |
| | 6922 | /* must check for timeout to avoid infinite loop */ |
| | 6923 | if (js_poll_interrupts(ctx)) { |
| | 6924 | JS_FreeValue(ctx, obj1); |
| | 6925 | ret = -1; |
| | 6926 | break; |
| | 6927 | } |
| 6726 | } | 6928 | } |
| 6727 | proto1 = JS_VALUE_GET_OBJ(proto_val); | | |
| 6728 | if (!proto1) | | |
| 6729 | break; | | |
| 6730 | } else { | 6929 | } else { |
| 6731 | break; | 6930 | ret = FALSE; |
| 6732 | } | 6931 | } |
| | 6932 | break; |
| 6733 | } | 6933 | } |
| 6734 | p = proto1; | 6934 | p = proto1; |
| 6735 | if (proto == p) { | 6935 | if (proto == p) { |
| @@ -6767,28 +6967,24 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj) · 31 unmodified lines |
| 6767 | return JS_OrdinaryIsInstanceOf(ctx, val, obj); | 6967 | return JS_OrdinaryIsInstanceOf(ctx, val, obj); |
| 6768 | } | 6968 | } |
| 6769 | | 6969 | |
| 6770 | static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSProperty *pr) | 6970 | typedef int JSAutoInitFunc(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque); |
| | 6971 | |
| | 6972 | static JSAutoInitFunc *js_autoinit_func_table[] = { |
| | 6973 | js_instantiate_prototype, /* JS_AUTOINIT_ID_PROTOTYPE */ |
| | 6974 | js_module_ns_autoinit, /* JS_AUTOINIT_ID_MODULE_NS */ |
| | 6975 | JS_InstantiateFunctionListItem, /* JS_AUTOINIT_ID_PROP */ |
| | 6976 | }; |
| | 6977 | |
| | 6978 | static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, |
| | 6979 | JSProperty *pr) |
| 6771 | { | 6980 | { |
| 6772 | int ret; | 6981 | int ret; |
| 6773 | JSContext *realm; | 6982 | JSContext *realm; |
| 6774 | | 6983 | JSAutoInitFunc *func; |
| 6775 | if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) { | 6984 | |
| 6776 | realm = pr->u.init.u.realm; | 6985 | realm = js_autoinit_get_realm(pr); |
| 6777 | ret = JS_InstantiateFunctionListItem(realm, p, prop, pr->u.init.opaque); | 6986 | func = js_autoinit_func_table[js_autoinit_get_id(pr)]; |
| 6778 | if (ret) | 6987 | ret = func(realm, p, prop, pr->u.init.opaque); |
| 6779 | return ret; | | |
| 6780 | } else { | | |
| 6781 | switch(pr->u.init.u.init_id) { | | |
| 6782 | case JS_AUTOINIT_ID_PROTOTYPE: | | |
| 6783 | ret = js_instantiate_prototype(ctx, p, prop, pr->u.init.opaque); | | |
| 6784 | break; | | |
| 6785 | case JS_AUTOINIT_ID_MODULE_NS: | | |
| 6786 | ret = js_module_ns_autoinit(ctx, p, prop, pr->u.init.opaque); | | |
| 6787 | break; | | |
| 6788 | default: | | |
| 6789 | abort(); | | |
| 6790 | } | | |
| 6791 | } | | |
| 6792 | return ret; | 6988 | return ret; |
| 6793 | } | 6989 | } |
| 6794 | | 6990 | |
| @@ -6805,8 +7001,9 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 10 unmodified lines |
| 6805 | if (unlikely(tag != JS_TAG_OBJECT)) { | 7001 | if (unlikely(tag != JS_TAG_OBJECT)) { |
| 6806 | switch(tag) { | 7002 | switch(tag) { |
| 6807 | case JS_TAG_NULL: | 7003 | case JS_TAG_NULL: |
| | 7004 | return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of null", prop); |
| 6808 | case JS_TAG_UNDEFINED: | 7005 | case JS_TAG_UNDEFINED: |
| 6809 | return JS_ThrowTypeError(ctx, "value has no property"); | 7006 | return JS_ThrowTypeErrorAtom(ctx, "cannot read property '%s' of undefined", prop); |
| 6810 | case JS_TAG_EXCEPTION: | 7007 | case JS_TAG_EXCEPTION: |
| 6811 | return JS_EXCEPTION; | 7008 | return JS_EXCEPTION; |
| 6812 | case JS_TAG_STRING: | 7009 | case JS_TAG_STRING: |
| @@ -6831,7 +7028,7 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 18 unmodified lines |
| 6831 | break; | 7028 | break; |
| 6832 | } | 7029 | } |
| 6833 | /* cannot raise an exception */ | 7030 | /* cannot raise an exception */ |
| 6834 | p = JS_VALUE_GET_OBJ(JS_GetPrototype(ctx, obj)); | 7031 | p = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, obj)); |
| 6835 | if (!p) | 7032 | if (!p) |
| 6836 | return JS_UNDEFINED; | 7033 | return JS_UNDEFINED; |
| 6837 | } else { | 7034 | } else { |
| @@ -6896,15 +7093,25 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 58 unmodified lines |
| 6896 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; | 7093 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; |
| 6897 | if (em) { | 7094 | if (em) { |
| 6898 | if (em->get_property) { | 7095 | if (em->get_property) { |
| | 7096 | JSValue obj1, retval; |
| 6899 | /* XXX: should pass throw_ref_error */ | 7097 | /* XXX: should pass throw_ref_error */ |
| 6900 | return em->get_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), | 7098 | /* Note: if 'p' is a prototype, it can be |
| 6901 | prop, this_obj); | 7099 | freed in the called function */ |
| | 7100 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| | 7101 | retval = em->get_property(ctx, obj1, prop, this_obj); |
| | 7102 | JS_FreeValue(ctx, obj1); |
| | 7103 | return retval; |
| 6902 | } | 7104 | } |
| 6903 | if (em->get_own_property) { | 7105 | if (em->get_own_property) { |
| 6904 | JSPropertyDescriptor desc; | 7106 | JSPropertyDescriptor desc; |
| 6905 | int ret; | 7107 | int ret; |
| | 7108 | JSValue obj1; |
| 6906 | | 7109 | |
| 6907 | ret = em->get_own_property(ctx, &desc, JS_MKPTR(JS_TAG_OBJECT, p), prop); | 7110 | /* Note: if 'p' is a prototype, it can be |
| | 7111 | freed in the called function */ |
| | 7112 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| | 7113 | ret = em->get_own_property(ctx, &desc, obj1, prop); |
| | 7114 | JS_FreeValue(ctx, obj1); |
| 6908 | if (ret < 0) | 7115 | if (ret < 0) |
| 6909 | return JS_EXCEPTION; | 7116 | return JS_EXCEPTION; |
| 6910 | if (ret) { | 7117 | if (ret) { |
| @@ -6932,9 +7139,8 @@ JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj, · 21 unmodified lines |
| 6932 | | 7139 | |
| 6933 | static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) | 7140 | static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) |
| 6934 | { | 7141 | { |
| 6935 | char buf[ATOM_GET_STR_BUF_SIZE]; | 7142 | return JS_ThrowTypeErrorAtom(ctx, "private class field '%s' does not exist", |
| 6936 | return JS_ThrowTypeError(ctx, "private class field %s does not exist", | 7143 | atom); |
| 6937 | JS_AtomGetStr(ctx, buf, sizeof(buf), atom)); | | |
| 6938 | } | 7144 | } |
| 6939 | | 7145 | |
| 6940 | /* Private fields can be added even on non extensible objects or | 7146 | /* Private fields can be added even on non extensible objects or |
| @@ -6960,9 +7166,8 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, · 19 unmodified lines |
| 6960 | p = JS_VALUE_GET_OBJ(obj); | 7166 | p = JS_VALUE_GET_OBJ(obj); |
| 6961 | prs = find_own_property(&pr, p, prop); | 7167 | prs = find_own_property(&pr, p, prop); |
| 6962 | if (prs) { | 7168 | if (prs) { |
| 6963 | char buf[ATOM_GET_STR_BUF_SIZE]; | 7169 | JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists", |
| 6964 | JS_ThrowTypeError(ctx, "private class field %s already exists", | 7170 | prop); |
| 6965 | JS_AtomGetStr(ctx, buf, sizeof(buf), prop)); | | |
| 6966 | goto fail; | 7171 | goto fail; |
| 6967 | } | 7172 | } |
| 6968 | pr = add_property(ctx, p, prop, JS_PROP_C_W_E); | 7173 | pr = add_property(ctx, p, prop, JS_PROP_C_W_E); |
| @@ -7211,7 +7416,9 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, · 242 unmodified lines |
| 7211 | JS_ThrowTypeErrorDetachedArrayBuffer(ctx); | 7416 | JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| 7212 | return -1; | 7417 | return -1; |
| 7213 | } | 7418 | } |
| 7214 | num_keys_count += p->u.array.count; | 7419 | if (flags & JS_GPN_STRING_MASK) { |
| | 7420 | num_keys_count += p->u.array.count; |
| | 7421 | } |
| 7215 | } else { | 7422 | } else { |
| 7216 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; | 7423 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; |
| 7217 | if (em && em->get_own_property_names) { | 7424 | if (em && em->get_own_property_names) { |
| @@ -7293,15 +7500,17 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, · 75 unmodified lines |
| 7293 | | 7500 | |
| 7294 | if (p->is_exotic) { | 7501 | if (p->is_exotic) { |
| 7295 | if (p->fast_array) { | 7502 | if (p->fast_array) { |
| 7296 | for(i = 0; i < p->u.array.count; i++) { | 7503 | if (flags & JS_GPN_STRING_MASK) { |
| 7297 | tab_atom[num_index].atom = __JS_AtomFromUInt32(i); | 7504 | for(i = 0; i < p->u.array.count; i++) { |
| 7298 | if (tab_atom[num_index].atom == JS_ATOM_NULL) { | 7505 | tab_atom[num_index].atom = __JS_AtomFromUInt32(i); |
| 7299 | js_free_prop_enum(ctx, tab_exotic, exotic_count); | 7506 | if (tab_atom[num_index].atom == JS_ATOM_NULL) { |
| 7300 | js_free_prop_enum(ctx, tab_atom, num_index); | 7507 | js_free_prop_enum(ctx, tab_exotic, exotic_count); |
| 7301 | return -1; | 7508 | js_free_prop_enum(ctx, tab_atom, num_index); |
| | 7509 | return -1; |
| | 7510 | } |
| | 7511 | tab_atom[num_index].is_enumerable = TRUE; |
| | 7512 | num_index++; |
| 7302 | } | 7513 | } |
| 7303 | tab_atom[num_index].is_enumerable = TRUE; | | |
| 7304 | num_index++; | | |
| 7305 | } | 7514 | } |
| 7306 | } | 7515 | } |
| 7307 | if (exotic_count > 0) { | 7516 | if (exotic_count > 0) { |
| @@ -7492,6 +7701,7 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) · 184 unmodified lines |
| 7492 | { | 7701 | { |
| 7493 | JSObject *p; | 7702 | JSObject *p; |
| 7494 | int ret; | 7703 | int ret; |
| | 7704 | JSValue obj1; |
| 7495 | | 7705 | |
| 7496 | if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) | 7706 | if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) |
| 7497 | return FALSE; | 7707 | return FALSE; |
| @@ -7499,10 +7709,18 @@ int JS_HasProperty(JSContext *ctx, JSValueConst obj, JSAtom prop) · 1 unmodified line |
| 7499 | for(;;) { | 7709 | for(;;) { |
| 7500 | if (p->is_exotic) { | 7710 | if (p->is_exotic) { |
| 7501 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; | 7711 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; |
| 7502 | if (em && em->has_property) | 7712 | if (em && em->has_property) { |
| 7503 | return em->has_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop); | 7713 | /* has_property can free the prototype */ |
| | 7714 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| | 7715 | ret = em->has_property(ctx, obj1, prop); |
| | 7716 | JS_FreeValue(ctx, obj1); |
| | 7717 | return ret; |
| | 7718 | } |
| 7504 | } | 7719 | } |
| | 7720 | /* JS_GetOwnPropertyInternal can free the prototype */ |
| | 7721 | JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| 7505 | ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop); | 7722 | ret = JS_GetOwnPropertyInternal(ctx, NULL, p, prop); |
| | 7723 | JS_FreeValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| 7506 | if (ret != 0) | 7724 | if (ret != 0) |
| 7507 | return ret; | 7725 | return ret; |
| 7508 | if (p->class_id >= JS_CLASS_UINT8C_ARRAY && | 7726 | if (p->class_id >= JS_CLASS_UINT8C_ARRAY && |
| @@ -7799,6 +8017,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 290 unmodified lines |
| 7799 | } else { | 8017 | } else { |
| 7800 | sh->prop_hash_end[-h1 - 1] = pr->hash_next; | 8018 | sh->prop_hash_end[-h1 - 1] = pr->hash_next; |
| 7801 | } | 8019 | } |
| | 8020 | sh->deleted_prop_count++; |
| 7802 | /* free the entry */ | 8021 | /* free the entry */ |
| 7803 | pr1 = &p->prop[h - 1]; | 8022 | pr1 = &p->prop[h - 1]; |
| 7804 | free_property(ctx->rt, pr1, pr->flags); | 8023 | free_property(ctx->rt, pr1, pr->flags); |
| @@ -7807,6 +8026,12 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) · 2 unmodified lines |
| 7807 | pr->flags = 0; | 8026 | pr->flags = 0; |
| 7808 | pr->atom = JS_ATOM_NULL; | 8027 | pr->atom = JS_ATOM_NULL; |
| 7809 | pr1->u.value = JS_UNDEFINED; | 8028 | pr1->u.value = JS_UNDEFINED; |
| | 8029 | |
| | 8030 | /* compact the properties if too many deleted properties */ |
| | 8031 | if (sh->deleted_prop_count >= 8 && |
| | 8032 | sh->deleted_prop_count >= ((unsigned)sh->prop_count / 2)) { |
| | 8033 | compact_properties(ctx, p); |
| | 8034 | } |
| 7810 | return TRUE; | 8035 | return TRUE; |
| 7811 | } | 8036 | } |
| 7812 | lpr = pr; | 8037 | lpr = pr; |
| @@ -8016,8 +8241,12 @@ static int JS_SetPropertyGeneric(JSContext *ctx, · 203 unmodified lines |
| 8016 | if (p->is_exotic) { | 8241 | if (p->is_exotic) { |
| 8017 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; | 8242 | const JSClassExoticMethods *em = ctx->rt->class_array[p->class_id].exotic; |
| 8018 | if (em && em->set_property) { | 8243 | if (em && em->set_property) { |
| 8019 | ret = em->set_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p), prop, | 8244 | JSValue obj1; |
| | 8245 | /* set_property can free the prototype */ |
| | 8246 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); |
| | 8247 | ret = em->set_property(ctx, obj1, prop, |
| 8020 | val, this_obj, flags); | 8248 | val, this_obj, flags); |
| | 8249 | JS_FreeValue(ctx, obj1); |
| 8021 | JS_FreeValue(ctx, val); | 8250 | JS_FreeValue(ctx, val); |
| 8022 | return ret; | 8251 | return ret; |
| 8023 | } | 8252 | } |
| @@ -8110,14 +8339,17 @@ int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj, · 86 unmodified lines |
| 8110 | if (unlikely(tag != JS_TAG_OBJECT)) { | 8339 | if (unlikely(tag != JS_TAG_OBJECT)) { |
| 8111 | switch(tag) { | 8340 | switch(tag) { |
| 8112 | case JS_TAG_NULL: | 8341 | case JS_TAG_NULL: |
| | 8342 | JS_FreeValue(ctx, val); |
| | 8343 | JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of null", prop); |
| | 8344 | return -1; |
| 8113 | case JS_TAG_UNDEFINED: | 8345 | case JS_TAG_UNDEFINED: |
| 8114 | JS_FreeValue(ctx, val); | 8346 | JS_FreeValue(ctx, val); |
| 8115 | JS_ThrowTypeError(ctx, "value has no property"); | 8347 | JS_ThrowTypeErrorAtom(ctx, "cannot set property '%s' of undefined", prop); |
| 8116 | return -1; | 8348 | return -1; |
| 8117 | default: | 8349 | default: |
| 8118 | /* even on a primitive type we can have setters on the prototype */ | 8350 | /* even on a primitive type we can have setters on the prototype */ |
| 8119 | p = NULL; | 8351 | p = NULL; |
| 8120 | p1 = JS_VALUE_GET_OBJ(JS_GetPrototype(ctx, this_obj)); | 8352 | p1 = JS_VALUE_GET_OBJ(JS_GetPrototypePrimitive(ctx, this_obj)); |
| 8121 | goto prototype_lookup; | 8353 | goto prototype_lookup; |
| 8122 | } | 8354 | } |
| 8123 | } | 8355 | } |
| @@ -8195,15 +8427,22 @@ retry: · 71 unmodified lines |
| 8195 | } else { | 8427 | } else { |
| 8196 | const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic; | 8428 | const JSClassExoticMethods *em = ctx->rt->class_array[p1->class_id].exotic; |
| 8197 | if (em) { | 8429 | if (em) { |
| | 8430 | JSValue obj1; |
| 8198 | if (em->set_property) { | 8431 | if (em->set_property) { |
| 8199 | ret = em->set_property(ctx, JS_MKPTR(JS_TAG_OBJECT, p1), prop, | 8432 | /* set_property can free the prototype */ |
| | 8433 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); |
| | 8434 | ret = em->set_property(ctx, obj1, prop, |
| 8200 | val, this_obj, flags); | 8435 | val, this_obj, flags); |
| | 8436 | JS_FreeValue(ctx, obj1); |
| 8201 | JS_FreeValue(ctx, val); | 8437 | JS_FreeValue(ctx, val); |
| 8202 | return ret; | 8438 | return ret; |
| 8203 | } | 8439 | } |
| 8204 | if (em->get_own_property) { | 8440 | if (em->get_own_property) { |
| | 8441 | /* get_own_property can free the prototype */ |
| | 8442 | obj1 = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p1)); |
| 8205 | ret = em->get_own_property(ctx, &desc, | 8443 | ret = em->get_own_property(ctx, &desc, |
| 8206 | JS_MKPTR(JS_TAG_OBJECT, p1), prop); | 8444 | obj1, prop); |
| | 8445 | JS_FreeValue(ctx, obj1); |
| 8207 | if (ret < 0) { | 8446 | if (ret < 0) { |
| 8208 | JS_FreeValue(ctx, val); | 8447 | JS_FreeValue(ctx, val); |
| 8209 | return ret; | 8448 | return ret; |
| @@ -8973,11 +9212,10 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj, · 763 unmodified lines |
| 8973 | pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT); | 9212 | pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT); |
| 8974 | if (unlikely(!pr)) | 9213 | if (unlikely(!pr)) |
| 8975 | return -1; | 9214 | return -1; |
| 8976 | if (id == JS_AUTOINIT_ID_PROP) { | 9215 | pr->u.init.realm_and_id = (uintptr_t)JS_DupContext(ctx); |
| 8977 | pr->u.init.u.realm = JS_DupContext(ctx); | 9216 | assert((pr->u.init.realm_and_id & 3) == 0); |
| 8978 | } else { | 9217 | assert(id <= 3); |
| 8979 | pr->u.init.u.init_id = id; | 9218 | pr->u.init.realm_and_id |= id; |
| 8980 | } | | |
| 8981 | pr->u.init.opaque = opaque; | 9219 | pr->u.init.opaque = opaque; |
| 8982 | return TRUE; | 9220 | return TRUE; |
| 8983 | } | 9221 | } |
| @@ -9114,9 +9352,7 @@ static int JS_DefineObjectNameComputed(JSContext *ctx, JSValueConst obj, · 130 unmodified lines |
| 9114 | | 9352 | |
| 9115 | static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop) | 9353 | static JSValue JS_ThrowSyntaxErrorVarRedeclaration(JSContext *ctx, JSAtom prop) |
| 9116 | { | 9354 | { |
| 9117 | char buf[ATOM_GET_STR_BUF_SIZE]; | 9355 | return JS_ThrowSyntaxErrorAtom(ctx, "redeclaration of '%s'", prop); |
| 9118 | return JS_ThrowSyntaxError(ctx, "redeclaration of %s", | | |
| 9119 | JS_AtomGetStr(ctx, buf, sizeof(buf), prop)); | | |
| 9120 | } | 9356 | } |
| 9121 | | 9357 | |
| 9122 | /* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */ | 9358 | /* flags is 0, DEFINE_GLOBAL_LEX_VAR or DEFINE_GLOBAL_FUNC_VAR */ |
| @@ -9125,7 +9361,6 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) · 2 unmodified lines |
| 9125 | { | 9361 | { |
| 9126 | JSObject *p; | 9362 | JSObject *p; |
| 9127 | JSShapeProperty *prs; | 9363 | JSShapeProperty *prs; |
| 9128 | char buf[ATOM_GET_STR_BUF_SIZE]; | | |
| 9129 | | 9364 | |
| 9130 | p = JS_VALUE_GET_OBJ(ctx->global_obj); | 9365 | p = JS_VALUE_GET_OBJ(ctx->global_obj); |
| 9131 | prs = find_own_property1(p, prop); | 9366 | prs = find_own_property1(p, prop); |
| @@ -9143,8 +9378,8 @@ static int JS_CheckDefineGlobalVar(JSContext *ctx, JSAtom prop, int flags) · 11 unmodified lines |
| 9143 | ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) != | 9378 | ((prs->flags & (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)) != |
| 9144 | (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) { | 9379 | (JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)))) { |
| 9145 | define_error: | 9380 | define_error: |
| 9146 | JS_ThrowTypeError(ctx, "cannot define variable %s", | 9381 | JS_ThrowTypeErrorAtom(ctx, "cannot define variable '%s'", |
| 9147 | JS_AtomGetStr(ctx, buf, sizeof(buf), prop)); | 9382 | prop); |
| 9148 | return -1; | 9383 | return -1; |
| 9149 | } | 9384 | } |
| 9150 | } | 9385 | } |
| @@ -11395,7 +11630,9 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) · 2244 unmodified lines |
| 11395 | } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { | 11630 | } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { |
| 11396 | printf("[varref %p]", (void *)pr->u.var_ref); | 11631 | printf("[varref %p]", (void *)pr->u.var_ref); |
| 11397 | } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { | 11632 | } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) { |
| 11398 | printf("[autoinit %p %p]", (void *)pr->u.init.u.realm, | 11633 | printf("[autoinit %p %d %p]", |
| | 11634 | (void *)js_autoinit_get_realm(pr), |
| | 11635 | js_autoinit_get_id(pr), |
| 11399 | (void *)pr->u.init.opaque); | 11636 | (void *)pr->u.init.opaque); |
| 11400 | } else { | 11637 | } else { |
| 11401 | JS_DumpValueShort(rt, pr->u.value); | 11638 | JS_DumpValueShort(rt, pr->u.value); |
| @@ -15726,30 +15963,6 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj, · 4324 unmodified lines |
| 15726 | } | 15963 | } |
| 15727 | } | 15964 | } |
| 15728 | | 15965 | |
| 15729 | static no_inline __exception int __js_poll_interrupts(JSContext *ctx) | | |
| 15730 | { | | |
| 15731 | JSRuntime *rt = ctx->rt; | | |
| 15732 | ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT; | | |
| 15733 | if (rt->interrupt_handler) { | | |
| 15734 | if (rt->interrupt_handler(rt, rt->interrupt_opaque)) { | | |
| 15735 | /* XXX: should set a specific flag to avoid catching */ | | |
| 15736 | JS_ThrowInternalError(ctx, "interrupted"); | | |
| 15737 | JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE); | | |
| 15738 | return -1; | | |
| 15739 | } | | |
| 15740 | } | | |
| 15741 | return 0; | | |
| 15742 | } | | |
| 15743 | | | |
| 15744 | static inline __exception int js_poll_interrupts(JSContext *ctx) | | |
| 15745 | { | | |
| 15746 | if (unlikely(--ctx->interrupt_counter <= 0)) { | | |
| 15747 | return __js_poll_interrupts(ctx); | | |
| 15748 | } else { | | |
| 15749 | return 0; | | |
| 15750 | } | | |
| 15751 | } | | |
| 15752 | | | |
| 15753 | /* argument of OP_special_object */ | 15966 | /* argument of OP_special_object */ |
| 15754 | typedef enum { | 15967 | typedef enum { |
| 15755 | OP_SPECIAL_OBJECT_ARGUMENTS, | 15968 | OP_SPECIAL_OBJECT_ARGUMENTS, |
| @@ -16440,7 +16653,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, · 684 unmodified lines |
| 16440 | CASE(OP_get_super): | 16653 | CASE(OP_get_super): |
| 16441 | { | 16654 | { |
| 16442 | JSValue proto; | 16655 | JSValue proto; |
| 16443 | proto = JS_DupValue(ctx, JS_GetPrototype(ctx, sp[-1])); | 16656 | proto = JS_GetPrototype(ctx, sp[-1]); |
| 16444 | if (JS_IsException(proto)) | 16657 | if (JS_IsException(proto)) |
| 16445 | goto exception; | 16658 | goto exception; |
| 16446 | JS_FreeValue(ctx, sp[-1]); | 16659 | JS_FreeValue(ctx, sp[-1]); |
| @@ -18543,6 +18756,9 @@ static JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s) · 2096 unmodified lines |
| 18543 | { | 18756 | { |
| 18544 | JSValue func_obj; | 18757 | JSValue func_obj; |
| 18545 | | 18758 | |
| | 18759 | if (js_check_stack_overflow(ctx->rt, 0)) |
| | 18760 | return JS_ThrowStackOverflow(ctx); |
| | 18761 | |
| 18546 | /* the tag does not matter provided it is not an object */ | 18762 | /* the tag does not matter provided it is not an object */ |
| 18547 | func_obj = JS_MKPTR(JS_TAG_INT, s); | 18763 | func_obj = JS_MKPTR(JS_TAG_INT, s); |
| 18548 | return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED, | 18764 | return JS_CallInternal(ctx, func_obj, s->this_val, JS_UNDEFINED, |
| @@ -19670,8 +19886,8 @@ typedef struct JSFunctionDef { · 1121 unmodified lines |
| 19670 | | 19886 | |
| 19671 | /* constant pool (strings, functions, numbers) */ | 19887 | /* constant pool (strings, functions, numbers) */ |
| 19672 | JSValue *cpool; | 19888 | JSValue *cpool; |
| 19673 | uint32_t cpool_count; | 19889 | int cpool_count; |
| 19674 | uint32_t cpool_size; | 19890 | int cpool_size; |
| 19675 | | 19891 | |
| 19676 | /* list of variables in the closure */ | 19892 | /* list of variables in the closure */ |
| 19677 | int closure_var_count; | 19893 | int closure_var_count; |
| @@ -19741,6 +19957,7 @@ typedef struct JSParseState { · 63 unmodified lines |
| 19741 | JSFunctionDef *cur_func; | 19957 | JSFunctionDef *cur_func; |
| 19742 | BOOL is_module; /* parsing a module */ | 19958 | BOOL is_module; /* parsing a module */ |
| 19743 | BOOL allow_html_comments; | 19959 | BOOL allow_html_comments; |
| | 19960 | BOOL ext_json; /* true if accepting JSON superset */ |
| 19744 | } JSParseState; | 19961 | } JSParseState; |
| 19745 | | 19962 | |
| 19746 | typedef struct JSOpCode { | 19963 | typedef struct JSOpCode { |
| @@ -20308,23 +20525,18 @@ static __exception int next_token(JSParseState *s) · 561 unmodified lines |
| 20308 | c = *p; | 20525 | c = *p; |
| 20309 | switch(c) { | 20526 | switch(c) { |
| 20310 | case 0: | 20527 | case 0: |
| 20311 | s->token.val = TOK_EOF; | 20528 | if (p >= s->buf_end) { |
| 20312 | break; | 20529 | s->token.val = TOK_EOF; |
| 20313 | case '`': | 20530 | } else { |
| 20314 | if (!s->cur_func) { | | |
| 20315 | /* JSON does not accept templates */ | | |
| 20316 | goto def_token; | 20531 | goto def_token; |
| 20317 | } | 20532 | } |
| | 20533 | break; |
| | 20534 | case '`': |
| 20318 | if (js_parse_template_part(s, p + 1)) | 20535 | if (js_parse_template_part(s, p + 1)) |
| 20319 | goto fail; | 20536 | goto fail; |
| 20320 | p = s->buf_ptr; | 20537 | p = s->buf_ptr; |
| 20321 | break; | 20538 | break; |
| 20322 | case '\'': | 20539 | case '\'': |
| 20323 | if (!s->cur_func) { | | |
| 20324 | /* JSON does not accept single quoted strings */ | | |
| 20325 | goto def_token; | | |
| 20326 | } | | |
| 20327 | /* fall through */ | | |
| 20328 | case '\"': | 20540 | case '\"': |
| 20329 | if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p)) | 20541 | if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p)) |
| 20330 | goto fail; | 20542 | goto fail; |
| @@ -20342,11 +20554,6 @@ static __exception int next_token(JSParseState *s) · 11 unmodified lines |
| 20342 | goto redo; | 20554 | goto redo; |
| 20343 | case '\f': | 20555 | case '\f': |
| 20344 | case '\v': | 20556 | case '\v': |
| 20345 | if (!s->cur_func) { | | |
| 20346 | /* JSONWhitespace does not match <VT>, nor <FF> */ | | |
| 20347 | goto def_token; | | |
| 20348 | } | | |
| 20349 | /* fall through */ | | |
| 20350 | case ' ': | 20557 | case ' ': |
| 20351 | case '\t': | 20558 | case '\t': |
| 20352 | p++; | 20559 | p++; |
| @@ -20443,16 +20650,15 @@ static __exception int next_token(JSParseState *s) · 90 unmodified lines |
| 20443 | s->token.u.ident.is_reserved = FALSE; | 20650 | s->token.u.ident.is_reserved = FALSE; |
| 20444 | if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || | 20651 | if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD || |
| 20445 | (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && | 20652 | (s->token.u.ident.atom <= JS_ATOM_LAST_STRICT_KEYWORD && |
| 20446 | s->cur_func && (s->cur_func->js_mode & JS_MODE_STRICT)) || | 20653 | (s->cur_func->js_mode & JS_MODE_STRICT)) || |
| 20447 | (s->token.u.ident.atom == JS_ATOM_yield && s->cur_func && | 20654 | (s->token.u.ident.atom == JS_ATOM_yield && |
| 20448 | ((s->cur_func->func_kind & JS_FUNC_GENERATOR) || | 20655 | ((s->cur_func->func_kind & JS_FUNC_GENERATOR) || |
| 20449 | (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && | 20656 | (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && |
| 20450 | !s->cur_func->in_function_body && s->cur_func->parent && | 20657 | !s->cur_func->in_function_body && s->cur_func->parent && |
| 20451 | (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) || | 20658 | (s->cur_func->parent->func_kind & JS_FUNC_GENERATOR)))) || |
| 20452 | (s->token.u.ident.atom == JS_ATOM_await && | 20659 | (s->token.u.ident.atom == JS_ATOM_await && |
| 20453 | (s->is_module || | 20660 | (s->is_module || |
| 20454 | (s->cur_func && | 20661 | (((s->cur_func->func_kind & JS_FUNC_ASYNC) || |
| 20455 | ((s->cur_func->func_kind & JS_FUNC_ASYNC) || | | |
| 20456 | (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && | 20662 | (s->cur_func->func_type == JS_PARSE_FUNC_ARROW && |
| 20457 | !s->cur_func->in_function_body && s->cur_func->parent && | 20663 | !s->cur_func->in_function_body && s->cur_func->parent && |
| 20458 | (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) { | 20664 | (s->cur_func->parent->func_kind & JS_FUNC_ASYNC))))))) { |
| @@ -20505,9 +20711,8 @@ static __exception int next_token(JSParseState *s) · 46 unmodified lines |
| 20505 | } | 20711 | } |
| 20506 | break; | 20712 | break; |
| 20507 | case '0': | 20713 | case '0': |
| 20508 | /* in strict or JSON parsing mode, octal literals are not accepted */ | 20714 | /* in strict mode, octal literals are not accepted */ |
| 20509 | if (is_digit(p[1]) && (!s->cur_func || | 20715 | if (is_digit(p[1]) && (s->cur_func->js_mode & JS_MODE_STRICT)) { |
| 20510 | (s->cur_func->js_mode & JS_MODE_STRICT))) { | | |
| 20511 | js_parse_error(s, "octal literals are deprecated in strict mode"); | 20716 | js_parse_error(s, "octal literals are deprecated in strict mode"); |
| 20512 | goto fail; | 20717 | goto fail; |
| 20513 | } | 20718 | } |
| @@ -20519,22 +20724,17 @@ static __exception int next_token(JSParseState *s) · 5 unmodified lines |
| 20519 | JSValue ret; | 20724 | JSValue ret; |
| 20520 | const uint8_t *p1; | 20725 | const uint8_t *p1; |
| 20521 | int flags, radix; | 20726 | int flags, radix; |
| 20522 | if (!s->cur_func) { | 20727 | flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL | |
| 20523 | flags = 0; | 20728 | ATOD_ACCEPT_UNDERSCORES; |
| 20524 | radix = 10; | | |
| 20525 | } else { | | |
| 20526 | flags = ATOD_ACCEPT_BIN_OCT | ATOD_ACCEPT_LEGACY_OCTAL | | | |
| 20527 | ATOD_ACCEPT_UNDERSCORES; | | |
| 20528 | #ifdef CONFIG_BIGNUM | 20729 | #ifdef CONFIG_BIGNUM |
| 20529 | flags |= ATOD_ACCEPT_SUFFIX; | 20730 | flags |= ATOD_ACCEPT_SUFFIX; |
| 20530 | if (s->cur_func->js_mode & JS_MODE_MATH) { | 20731 | if (s->cur_func->js_mode & JS_MODE_MATH) { |
| 20531 | flags |= ATOD_MODE_BIGINT; | 20732 | flags |= ATOD_MODE_BIGINT; |
| 20532 | if (s->cur_func->js_mode & JS_MODE_MATH) | 20733 | if (s->cur_func->js_mode & JS_MODE_MATH) |
| 20533 | flags |= ATOD_TYPE_BIG_FLOAT; | 20734 | flags |= ATOD_TYPE_BIG_FLOAT; |
| 20534 | } | | |
| 20535 | #endif | | |
| 20536 | radix = 0; | | |
| 20537 | } | 20735 | } |
| | 20736 | #endif |
| | 20737 | radix = 0; |
| 20538 | #ifdef CONFIG_BIGNUM | 20738 | #ifdef CONFIG_BIGNUM |
| 20539 | s->token.u.num.exponent = 0; | 20739 | s->token.u.num.exponent = 0; |
| 20540 | ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix, | 20740 | ret = js_atof2(s->ctx, (const char *)p, (const char **)&p, radix, |
| @@ -20699,7 +20899,7 @@ static __exception int next_token(JSParseState *s) · 158 unmodified lines |
| 20699 | case '^': | 20899 | case '^': |
| 20700 | if (p[1] == '=') { | 20900 | if (p[1] == '=') { |
| 20701 | p += 2; | 20901 | p += 2; |
| 20702 | if (s->cur_func && (s->cur_func->js_mode & JS_MODE_MATH)) | 20902 | if (s->cur_func->js_mode & JS_MODE_MATH) |
| 20703 | s->token.val = TOK_MATH_POW_ASSIGN; | 20903 | s->token.val = TOK_MATH_POW_ASSIGN; |
| 20704 | else | 20904 | else |
| 20705 | s->token.val = TOK_XOR_ASSIGN; | 20905 | s->token.val = TOK_XOR_ASSIGN; |
| @@ -20713,7 +20913,7 @@ static __exception int next_token(JSParseState *s) · 7 unmodified lines |
| 20713 | } | 20913 | } |
| 20714 | } else { | 20914 | } else { |
| 20715 | p++; | 20915 | p++; |
| 20716 | if (s->cur_func && (s->cur_func->js_mode & JS_MODE_MATH)) | 20916 | if (s->cur_func->js_mode & JS_MODE_MATH) |
| 20717 | s->token.val = TOK_MATH_POW; | 20917 | s->token.val = TOK_MATH_POW; |
| 20718 | else | 20918 | else |
| 20719 | s->token.val = '^'; | 20919 | s->token.val = '^'; |
| @@ -20758,22 +20958,12 @@ static __exception int next_token(JSParseState *s) · 38 unmodified lines |
| 20758 | switch(c) { | 20958 | switch(c) { |
| 20759 | case CP_PS: | 20959 | case CP_PS: |
| 20760 | case CP_LS: | 20960 | case CP_LS: |
| 20761 | if (!s->cur_func) { | 20961 | /* XXX: should avoid incrementing line_number, but |
| 20762 | /* <PS> and <LS> are not JSONWhitespace */ | 20962 | needed to handle HTML comments */ |
| 20763 | goto def_token; | 20963 | goto line_terminator; |
| 20764 | } else { | | |
| 20765 | /* XXX: should avoid incrementing line_number, but | | |
| 20766 | needed to handle HTML comments */ | | |
| 20767 | goto line_terminator; | | |
| 20768 | } | | |
| 20769 | default: | 20964 | default: |
| 20770 | if (lre_is_space(c)) { | 20965 | if (lre_is_space(c)) { |
| 20771 | if (!s->cur_func) { | 20966 | goto redo; |
| 20772 | /* category z spaces are not JSONWhitespace */ | | |
| 20773 | goto def_token; | | |
| 20774 | } else { | | |
| 20775 | goto redo; | | |
| 20776 | } | | |
| 20777 | } else if (lre_js_is_ident_first(c)) { | 20967 | } else if (lre_js_is_ident_first(c)) { |
| 20778 | ident_has_escape = FALSE; | 20968 | ident_has_escape = FALSE; |
| 20779 | goto has_ident; | 20969 | goto has_ident; |
| @@ -20798,6 +20988,220 @@ static __exception int next_token(JSParseState *s) · 18 unmodified lines |
| 20798 | return -1; | 20988 | return -1; |
| 20799 | } | 20989 | } |
| 20800 | | 20990 | |
| | 20991 | /* 'c' is the first character. Return JS_ATOM_NULL in case of error */ |
| | 20992 | static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c) |
| | 20993 | { |
| | 20994 | const uint8_t *p; |
| | 20995 | char ident_buf[128], *buf; |
| | 20996 | size_t ident_size, ident_pos; |
| | 20997 | JSAtom atom; |
| | 20998 | |
| | 20999 | p = *pp; |
| | 21000 | buf = ident_buf; |
| | 21001 | ident_size = sizeof(ident_buf); |
| | 21002 | ident_pos = 0; |
| | 21003 | for(;;) { |
| | 21004 | buf[ident_pos++] = c; |
| | 21005 | c = *p; |
| | 21006 | if (c >= 128 || |
| | 21007 | !((lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1)) |
| | 21008 | break; |
| | 21009 | p++; |
| | 21010 | if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) { |
| | 21011 | if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) { |
| | 21012 | atom = JS_ATOM_NULL; |
| | 21013 | goto done; |
| | 21014 | } |
| | 21015 | } |
| | 21016 | } |
| | 21017 | atom = JS_NewAtomLen(s->ctx, buf, ident_pos); |
| | 21018 | done: |
| | 21019 | if (unlikely(buf != ident_buf)) |
| | 21020 | js_free(s->ctx, buf); |
| | 21021 | *pp = p; |
| | 21022 | return atom; |
| | 21023 | } |
| | 21024 | |
| | 21025 | static __exception int json_next_token(JSParseState *s) |
| | 21026 | { |
| | 21027 | const uint8_t *p; |
| | 21028 | int c; |
| | 21029 | JSAtom atom; |
| | 21030 | |
| | 21031 | if (js_check_stack_overflow(s->ctx->rt, 0)) { |
| | 21032 | return js_parse_error(s, "stack overflow"); |
| | 21033 | } |
| | 21034 | |
| | 21035 | free_token(s, &s->token); |
| | 21036 | |
| | 21037 | p = s->last_ptr = s->buf_ptr; |
| | 21038 | s->last_line_num = s->token.line_num; |
| | 21039 | redo: |
| | 21040 | s->token.line_num = s->line_num; |
| | 21041 | s->token.ptr = p; |
| | 21042 | c = *p; |
| | 21043 | switch(c) { |
| | 21044 | case 0: |
| | 21045 | if (p >= s->buf_end) { |
| | 21046 | s->token.val = TOK_EOF; |
| | 21047 | } else { |
| | 21048 | goto def_token; |
| | 21049 | } |
| | 21050 | break; |
| | 21051 | case '\'': |
| | 21052 | if (!s->ext_json) { |
| | 21053 | /* JSON does not accept single quoted strings */ |
| | 21054 | goto def_token; |
| | 21055 | } |
| | 21056 | /* fall through */ |
| | 21057 | case '\"': |
| | 21058 | if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p)) |
| | 21059 | goto fail; |
| | 21060 | break; |
| | 21061 | case '\r': /* accept DOS and MAC newline sequences */ |
| | 21062 | if (p[1] == '\n') { |
| | 21063 | p++; |
| | 21064 | } |
| | 21065 | /* fall thru */ |
| | 21066 | case '\n': |
| | 21067 | p++; |
| | 21068 | s->line_num++; |
| | 21069 | goto redo; |
| | 21070 | case '\f': |
| | 21071 | case '\v': |
| | 21072 | if (!s->ext_json) { |
| | 21073 | /* JSONWhitespace does not match <VT>, nor <FF> */ |
| | 21074 | goto def_token; |
| | 21075 | } |
| | 21076 | /* fall through */ |
| | 21077 | case ' ': |
| | 21078 | case '\t': |
| | 21079 | p++; |
| | 21080 | goto redo; |
| | 21081 | case '/': |
| | 21082 | if (!s->ext_json) { |
| | 21083 | /* JSON does not accept comments */ |
| | 21084 | goto def_token; |
| | 21085 | } |
| | 21086 | if (p[1] == '*') { |
| | 21087 | /* comment */ |
| | 21088 | p += 2; |
| | 21089 | for(;;) { |
| | 21090 | if (*p == '\0' && p >= s->buf_end) { |
| | 21091 | js_parse_error(s, "unexpected end of comment"); |
| | 21092 | goto fail; |
| | 21093 | } |
| | 21094 | if (p[0] == '*' && p[1] == '/') { |
| | 21095 | p += 2; |
| | 21096 | break; |
| | 21097 | } |
| | 21098 | if (*p == '\n') { |
| | 21099 | s->line_num++; |
| | 21100 | p++; |
| | 21101 | } else if (*p == '\r') { |
| | 21102 | p++; |
| | 21103 | } else if (*p >= 0x80) { |
| | 21104 | c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); |
| | 21105 | if (c == -1) { |
| | 21106 | p++; /* skip invalid UTF-8 */ |
| | 21107 | } |
| | 21108 | } else { |
| | 21109 | p++; |
| | 21110 | } |
| | 21111 | } |
| | 21112 | goto redo; |
| | 21113 | } else if (p[1] == '/') { |
| | 21114 | /* line comment */ |
| | 21115 | p += 2; |
| | 21116 | for(;;) { |
| | 21117 | if (*p == '\0' && p >= s->buf_end) |
| | 21118 | break; |
| | 21119 | if (*p == '\r' || *p == '\n') |
| | 21120 | break; |
| | 21121 | if (*p >= 0x80) { |
| | 21122 | c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p); |
| | 21123 | /* LS or PS are considered as line terminator */ |
| | 21124 | if (c == CP_LS || c == CP_PS) { |
| | 21125 | break; |
| | 21126 | } else if (c == -1) { |
| | 21127 | p++; /* skip invalid UTF-8 */ |
| | 21128 | } |
| | 21129 | } else { |
| | 21130 | p++; |
| | 21131 | } |
| | 21132 | } |
| | 21133 | goto redo; |
| | 21134 | } else { |
| | 21135 | goto def_token; |
| | 21136 | } |
| | 21137 | break; |
| | 21138 | case 'a' ... 'z': |
| | 21139 | case 'A' ... 'Z': |
| | 21140 | case '_': |
| | 21141 | case '$': |
| | 21142 | /* identifier : only pure ascii characters are accepted */ |
| | 21143 | p++; |
| | 21144 | atom = json_parse_ident(s, &p, c); |
| | 21145 | if (atom == JS_ATOM_NULL) |
| | 21146 | goto fail; |
| | 21147 | s->token.u.ident.atom = atom; |
| | 21148 | s->token.u.ident.has_escape = FALSE; |
| | 21149 | s->token.u.ident.is_reserved = FALSE; |
| | 21150 | s->token.val = TOK_IDENT; |
| | 21151 | break; |
| | 21152 | case '+': |
| | 21153 | if (!s->ext_json || !is_digit(p[1])) |
| | 21154 | goto def_token; |
| | 21155 | goto parse_number; |
| | 21156 | case '0': |
| | 21157 | if (is_digit(p[1])) |
| | 21158 | goto def_token; |
| | 21159 | goto parse_number; |
| | 21160 | case '-': |
| | 21161 | if (!is_digit(p[1])) |
| | 21162 | goto def_token; |
| | 21163 | goto parse_number; |
| | 21164 | case '1' ... '9': |
| | 21165 | /* number */ |
| | 21166 | parse_number: |
| | 21167 | { |
| | 21168 | JSValue ret; |
| | 21169 | int flags, radix; |
| | 21170 | if (!s->ext_json) { |
| | 21171 | flags = 0; |
| | 21172 | radix = 10; |
| | 21173 | } else { |
| | 21174 | flags = ATOD_ACCEPT_BIN_OCT; |
| | 21175 | radix = 0; |
| | 21176 | } |
| | 21177 | ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix, |
| | 21178 | flags); |
| | 21179 | if (JS_IsException(ret)) |
| | 21180 | goto fail; |
| | 21181 | s->token.val = TOK_NUMBER; |
| | 21182 | s->token.u.num.val = ret; |
| | 21183 | } |
| | 21184 | break; |
| | 21185 | default: |
| | 21186 | if (c >= 128) { |
| | 21187 | js_parse_error(s, "unexpected character"); |
| | 21188 | goto fail; |
| | 21189 | } |
| | 21190 | def_token: |
| | 21191 | s->token.val = c; |
| | 21192 | p++; |
| | 21193 | break; |
| | 21194 | } |
| | 21195 | s->buf_ptr = p; |
| | 21196 | |
| | 21197 | // dump_token(s, &s->token); |
| | 21198 | return 0; |
| | 21199 | |
| | 21200 | fail: |
| | 21201 | s->token.val = TOK_ERROR; |
| | 21202 | return -1; |
| | 21203 | } |
| | 21204 | |
| 20801 | /* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is | 21205 | /* only used for ':' and '=>', 'let' or 'function' look-ahead. *pp is |
| 20802 | only set if TOK_IMPORT is returned */ | 21206 | only set if TOK_IMPORT is returned */ |
| 20803 | /* XXX: handle all unicode cases */ | 21207 | /* XXX: handle all unicode cases */ |
| @@ -20858,6 +21262,12 @@ static int simple_next_token(const uint8_t **pp, BOOL no_line_terminator) · 54 unmodified lines |
| 20858 | } | 21262 | } |
| 20859 | } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) { | 21263 | } else if (c == 'o' && *p == 'f' && !lre_js_is_ident_next(p[1])) { |
| 20860 | return TOK_OF; | 21264 | return TOK_OF; |
| | 21265 | } else if (c == 'e' && |
| | 21266 | p[0] == 'x' && p[1] == 'p' && p[2] == 'o' && |
| | 21267 | p[3] == 'r' && p[4] == 't' && |
| | 21268 | !lre_js_is_ident_next(p[5])) { |
| | 21269 | *pp = p + 5; |
| | 21270 | return TOK_EXPORT; |
| 20861 | } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && | 21271 | } else if (c == 'f' && p[0] == 'u' && p[1] == 'n' && |
| 20862 | p[2] == 'c' && p[3] == 't' && p[4] == 'i' && | 21272 | p[2] == 'c' && p[3] == 't' && p[4] == 'i' && |
| 20863 | p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) { | 21273 | p[5] == 'o' && p[6] == 'n' && !lre_js_is_ident_next(p[7])) { |
| @@ -20881,16 +21291,21 @@ static int peek_token(JSParseState *s, BOOL no_line_terminator) · 17 unmodified lines |
| 20881 | (heuristic). 'input' must be a zero terminated. | 21291 | (heuristic). 'input' must be a zero terminated. |
| 20882 | | 21292 | |
| 20883 | Heuristic: skip comments and expect 'import' keyword not followed | 21293 | Heuristic: skip comments and expect 'import' keyword not followed |
| 20884 | by '(' or '.' | 21294 | by '(' or '.' or export keyword. |
| 20885 | */ | 21295 | */ |
| 20886 | BOOL JS_DetectModule(const char *input, size_t input_len) | 21296 | BOOL JS_DetectModule(const char *input, size_t input_len) |
| 20887 | { | 21297 | { |
| 20888 | const uint8_t *p = (const uint8_t *)input; | 21298 | const uint8_t *p = (const uint8_t *)input; |
| 20889 | int tok; | 21299 | int tok; |
| 20890 | if (simple_next_token(&p, FALSE) != TOK_IMPORT) | 21300 | switch(simple_next_token(&p, FALSE)) { |
| | 21301 | case TOK_IMPORT: |
| | 21302 | tok = simple_next_token(&p, FALSE); |
| | 21303 | return (tok != '.' && tok != '('); |
| | 21304 | case TOK_EXPORT: |
| | 21305 | return TRUE; |
| | 21306 | default: |
| 20891 | return FALSE; | 21307 | return FALSE; |
| 20892 | tok = simple_next_token(&p, FALSE); | 21308 | } |
| 20893 | return (tok != '.' && tok != '('); | | |
| 20894 | } | 21309 | } |
| 20895 | | 21310 | |
| 20896 | static inline int get_prev_opcode(JSFunctionDef *fd) { | 21311 | static inline int get_prev_opcode(JSFunctionDef *fd) { |
| @@ -20974,20 +21389,10 @@ static int new_label_fd(JSFunctionDef *fd, int label) · 77 unmodified lines |
| 20974 | LabelSlot *ls; | 21389 | LabelSlot *ls; |
| 20975 | | 21390 | |
| 20976 | if (label < 0) { | 21391 | if (label < 0) { |
| 20977 | if (fd->label_count >= fd->label_size) { | 21392 | if (js_resize_array(fd->ctx, (void *)&fd->label_slots, |
| 20978 | int new_size; | 21393 | sizeof(fd->label_slots[0]), |
| 20979 | size_t slack; | 21394 | &fd->label_size, fd->label_count + 1)) |
| 20980 | LabelSlot *new_tab; | 21395 | return -1; |
| 20981 | | | |
| 20982 | /* XXX: potential arithmetic overflow */ | | |
| 20983 | new_size = fd->label_size * 3 / 2 + 4; | | |
| 20984 | new_tab = js_realloc2(fd->ctx, fd->label_slots, new_size * sizeof(*new_tab), &slack); | | |
| 20985 | if (!new_tab) | | |
| 20986 | return -1; | | |
| 20987 | new_size += slack / sizeof(*new_tab); | | |
| 20988 | fd->label_slots = new_tab; | | |
| 20989 | fd->label_size = new_size; | | |
| 20990 | } | | |
| 20991 | label = fd->label_count++; | 21396 | label = fd->label_count++; |
| 20992 | ls = &fd->label_slots[label]; | 21397 | ls = &fd->label_slots[label]; |
| 20993 | ls->ref_count = 0; | 21398 | ls->ref_count = 0; |
| @@ -21035,19 +21440,10 @@ static int emit_goto(JSParseState *s, int opcode, int label) · 41 unmodified lines |
| 21035 | static int cpool_add(JSParseState *s, JSValue val) | 21440 | static int cpool_add(JSParseState *s, JSValue val) |
| 21036 | { | 21441 | { |
| 21037 | JSFunctionDef *fd = s->cur_func; | 21442 | JSFunctionDef *fd = s->cur_func; |
| 21038 | if (fd->cpool_count >= fd->cpool_size) { | 21443 | |
| 21039 | int new_size; | 21444 | if (js_resize_array(s->ctx, (void *)&fd->cpool, sizeof(fd->cpool[0]), |
| 21040 | size_t slack; | 21445 | &fd->cpool_size, fd->cpool_count + 1)) |
| 21041 | JSValue *new_tab; | 21446 | return -1; |
| 21042 | /* XXX: potential arithmetic overflow */ | | |
| 21043 | new_size = max_int(fd->cpool_count + 1, fd->cpool_size * 3 / 2); | | |
| 21044 | new_tab = js_realloc2(s->ctx, fd->cpool, new_size * sizeof(JSValue), &slack); | | |
| 21045 | if (!new_tab) | | |
| 21046 | return -1; | | |
| 21047 | new_size += slack / sizeof(*new_tab); | | |
| 21048 | fd->cpool = new_tab; | | |
| 21049 | fd->cpool_size = new_size; | | |
| 21050 | } | | |
| 21051 | fd->cpool[fd->cpool_count++] = val; | 21447 | fd->cpool[fd->cpool_count++] = val; |
| 21052 | return fd->cpool_count - 1; | 21448 | return fd->cpool_count - 1; |
| 21053 | } | 21449 | } |
| @@ -21246,18 +21642,9 @@ static int add_var(JSContext *ctx, JSFunctionDef *fd, JSAtom name) · 192 unmodified lines |
| 21246 | JS_ThrowInternalError(ctx, "too many local variables"); | 21642 | JS_ThrowInternalError(ctx, "too many local variables"); |
| 21247 | return -1; | 21643 | return -1; |
| 21248 | } | 21644 | } |
| 21249 | if ((fd->var_count + 1) > fd->var_size) { | 21645 | if (js_resize_array(ctx, (void **)&fd->vars, sizeof(fd->vars[0]), |
| 21250 | int new_size; | 21646 | &fd->var_size, fd->var_count + 1)) |
| 21251 | size_t slack; | 21647 | return -1; |
| 21252 | JSVarDef *new_buf; | | |
| 21253 | new_size = max_int(fd->var_count + 1, fd->var_size * 3 / 2); | | |
| 21254 | new_buf = js_realloc2(ctx, fd->vars, new_size * sizeof(*fd->vars), &slack); | | |
| 21255 | if (!new_buf) | | |
| 21256 | return -1; | | |
| 21257 | new_size += slack / sizeof(*new_buf); | | |
| 21258 | fd->vars = new_buf; | | |
| 21259 | fd->var_size = new_size; | | |
| 21260 | } | | |
| 21261 | vd = &fd->vars[fd->var_count++]; | 21648 | vd = &fd->vars[fd->var_count++]; |
| 21262 | memset(vd, 0, sizeof(*vd)); | 21649 | memset(vd, 0, sizeof(*vd)); |
| 21263 | vd->var_name = JS_DupAtom(ctx, name); | 21650 | vd->var_name = JS_DupAtom(ctx, name); |
| @@ -21309,18 +21696,9 @@ static int add_arg(JSContext *ctx, JSFunctionDef *fd, JSAtom name) · 45 unmodified lines |
| 21309 | JS_ThrowInternalError(ctx, "too many arguments"); | 21696 | JS_ThrowInternalError(ctx, "too many arguments"); |
| 21310 | return -1; | 21697 | return -1; |
| 21311 | } | 21698 | } |
| 21312 | if ((fd->arg_count + 1) > fd->arg_size) { | 21699 | if (js_resize_array(ctx, (void **)&fd->args, sizeof(fd->args[0]), |
| 21313 | int new_size; | 21700 | &fd->arg_size, fd->arg_count + 1)) |
| 21314 | size_t slack; | 21701 | return -1; |
| 21315 | JSVarDef *new_buf; | | |
| 21316 | new_size = max_int(fd->arg_count + 1, fd->arg_size * 3 / 2); | | |
| 21317 | new_buf = js_realloc2(ctx, fd->args, new_size * sizeof(*fd->args), &slack); | | |
| 21318 | if (!new_buf) | | |
| 21319 | return -1; | | |
| 21320 | new_size += slack / sizeof(*new_buf); | | |
| 21321 | fd->args = new_buf; | | |
| 21322 | fd->arg_size = new_size; | | |
| 21323 | } | | |
| 21324 | vd = &fd->args[fd->arg_count++]; | 21702 | vd = &fd->args[fd->arg_count++]; |
| 21325 | memset(vd, 0, sizeof(*vd)); | 21703 | memset(vd, 0, sizeof(*vd)); |
| 21326 | vd->var_name = JS_DupAtom(ctx, name); | 21704 | vd->var_name = JS_DupAtom(ctx, name); |
| @@ -21335,19 +21713,10 @@ static JSHoistedDef *add_hoisted_def(JSContext *ctx, · 8 unmodified lines |
| 21335 | { | 21713 | { |
| 21336 | JSHoistedDef *hf; | 21714 | JSHoistedDef *hf; |
| 21337 | | 21715 | |
| 21338 | if (s->hoisted_def_count >= s->hoisted_def_size) { | 21716 | if (js_resize_array(ctx, (void **)&s->hoisted_def, |
| 21339 | int new_size; | 21717 | sizeof(s->hoisted_def[0]), |
| 21340 | size_t slack; | 21718 | &s->hoisted_def_size, s->hoisted_def_count + 1)) |
| 21341 | JSHoistedDef *new_tab; | 21719 | return NULL; |
| 21342 | new_size = max_int(s->hoisted_def_count + 1, | | |
| 21343 | s->hoisted_def_size * 3 / 2); | | |
| 21344 | new_tab = js_realloc2(ctx, s->hoisted_def, new_size * sizeof(s->hoisted_def[0]), &slack); | | |
| 21345 | if (!new_tab) | | |
| 21346 | return NULL; | | |
| 21347 | new_size += slack / sizeof(*new_tab); | | |
| 21348 | s->hoisted_def = new_tab; | | |
| 21349 | s->hoisted_def_size = new_size; | | |
| 21350 | } | | |
| 21351 | hf = &s->hoisted_def[s->hoisted_def_count++]; | 21720 | hf = &s->hoisted_def[s->hoisted_def_count++]; |
| 21352 | hf->cpool_idx = cpool_idx; | 21721 | hf->cpool_idx = cpool_idx; |
| 21353 | hf->force_init = 0; | 21722 | hf->force_init = 0; |
| @@ -21639,7 +22008,7 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) · 285 unmodified lines |
| 21639 | goto done; | 22008 | goto done; |
| 21640 | if (next_token(s)) | 22009 | if (next_token(s)) |
| 21641 | return -1; | 22010 | return -1; |
| 21642 | if (js_parse_assign_expr(s, TRUE)) | 22011 | if (js_parse_expr(s)) |
| 21643 | return -1; | 22012 | return -1; |
| 21644 | depth++; | 22013 | depth++; |
| 21645 | if (s->token.val != '}') { | 22014 | if (s->token.val != '}') { |
| @@ -21647,7 +22016,8 @@ static __exception int js_parse_template(JSParseState *s, int call, int *argc) · 1 unmodified line |
| 21647 | } | 22016 | } |
| 21648 | /* XXX: should convert to string at this stage? */ | 22017 | /* XXX: should convert to string at this stage? */ |
| 21649 | free_token(s, &s->token); | 22018 | free_token(s, &s->token); |
| 21650 | /* Resume TOK_TEMPLATE parsing (s->token.line_num and s->token.ptr are OK) */ | 22019 | /* Resume TOK_TEMPLATE parsing (s->token.line_num and |
| | 22020 | * s->token.ptr are OK) */ |
| 21651 | s->got_lf = FALSE; | 22021 | s->got_lf = FALSE; |
| 21652 | s->last_line_num = s->token.line_num; | 22022 | s->last_line_num = s->token.line_num; |
| 21653 | if (js_parse_template_part(s, s->buf_ptr)) | 22023 | if (js_parse_template_part(s, s->buf_ptr)) |
| @@ -21875,7 +22245,7 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ · 221 unmodified lines |
| 21875 | size_t level = 0; | 22245 | size_t level = 0; |
| 21876 | JSParsePos pos; | 22246 | JSParsePos pos; |
| 21877 | int last_tok, tok = TOK_EOF; | 22247 | int last_tok, tok = TOK_EOF; |
| 21878 | int tok_len, bits = 0; | 22248 | int c, tok_len, bits = 0; |
| 21879 | | 22249 | |
| 21880 | /* protect from underflow */ | 22250 | /* protect from underflow */ |
| 21881 | state[level++] = 0; | 22251 | state[level++] = 0; |
| @@ -21900,8 +22270,30 @@ static int js_parse_skip_parens_token(JSParseState *s, int *pbits, BOOL no_line_ · 18 unmodified lines |
| 21900 | goto done; | 22270 | goto done; |
| 21901 | break; | 22271 | break; |
| 21902 | case '}': | 22272 | case '}': |
| 21903 | if (state[--level] != '{') | 22273 | c = state[--level]; |
| | 22274 | if (c == '`') { |
| | 22275 | /* continue the parsing of the template */ |
| | 22276 | free_token(s, &s->token); |
| | 22277 | /* Resume TOK_TEMPLATE parsing (s->token.line_num and |
| | 22278 | * s->token.ptr are OK) */ |
| | 22279 | s->got_lf = FALSE; |
| | 22280 | s->last_line_num = s->token.line_num; |
| | 22281 | if (js_parse_template_part(s, s->buf_ptr)) |
| | 22282 | goto done; |
| | 22283 | goto handle_template; |
| | 22284 | } else if (c != '{') { |
| 21904 | goto done; | 22285 | goto done; |
| | 22286 | } |
| | 22287 | break; |
| | 22288 | case TOK_TEMPLATE: |
| | 22289 | handle_template: |
| | 22290 | if (s->token.u.str.sep != '`') { |
| | 22291 | /* '${' inside the template : closing '}' and continue |
| | 22292 | parsing the template */ |
| | 22293 | if (level >= sizeof(state)) |
| | 22294 | goto done; |
| | 22295 | state[level++] = '`'; |
| | 22296 | } |
| 21905 | break; | 22297 | break; |
| 21906 | case TOK_EOF: | 22298 | case TOK_EOF: |
| 21907 | goto done; | 22299 | goto done; |
| @@ -24005,7 +24397,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen · 2097 unmodified lines |
| 24005 | int scope; | 24397 | int scope; |
| 24006 | name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); | 24398 | name = get_u32(fd->byte_code.buf + fd->last_opcode_pos + 1); |
| 24007 | scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); | 24399 | scope = get_u16(fd->byte_code.buf + fd->last_opcode_pos + 5); |
| 24008 | if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL) { | 24400 | if (name == JS_ATOM_eval && call_type == FUNC_CALL_NORMAL && !has_optional_chain) { |
| 24009 | /* direct 'eval' */ | 24401 | /* direct 'eval' */ |
| 24010 | opcode = OP_eval; | 24402 | opcode = OP_eval; |
| 24011 | } else { | 24403 | } else { |
| @@ -26318,26 +26710,6 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) · 2306 unmodified lines |
| 26318 | js_free(ctx, m); | 26710 | js_free(ctx, m); |
| 26319 | } | 26711 | } |
| 26320 | | 26712 | |
| 26321 | static int js_resize_array(JSContext *ctx, void **parray, int elem_size, | | |
| 26322 | int *psize, int *pcount, int new_count) | | |
| 26323 | { | | |
| 26324 | if (unlikely(new_count > *psize)) { | | |
| 26325 | int new_size; | | |
| 26326 | size_t slack; | | |
| 26327 | void *new_array; | | |
| 26328 | /* XXX: potential arithmetic overflow */ | | |
| 26329 | new_size = max_int(new_count, *psize * 3 / 2); | | |
| 26330 | new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack); | | |
| 26331 | if (!new_array) | | |
| 26332 | return -1; | | |
| 26333 | new_size += slack / elem_size; | | |
| 26334 | *psize = new_size; | | |
| 26335 | *parray = new_array; | | |
| 26336 | } | | |
| 26337 | *pcount = new_count; | | |
| 26338 | return 0; | | |
| 26339 | } | | |
| 26340 | | | |
| 26341 | static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, | 26713 | static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, |
| 26342 | JSAtom module_name) | 26714 | JSAtom module_name) |
| 26343 | { | 26715 | { |
| @@ -26353,11 +26725,10 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, · 9 unmodified lines |
| 26353 | | 26725 | |
| 26354 | if (js_resize_array(ctx, (void **)&m->req_module_entries, | 26726 | if (js_resize_array(ctx, (void **)&m->req_module_entries, |
| 26355 | sizeof(JSReqModuleEntry), | 26727 | sizeof(JSReqModuleEntry), |
| 26356 | &m->req_module_entries_size, &m->req_module_entries_count, | 26728 | &m->req_module_entries_size, |
| 26357 | m->req_module_entries_count + 1)) | 26729 | m->req_module_entries_count + 1)) |
| 26358 | return -1; | 26730 | return -1; |
| 26359 | i = m->req_module_entries_count - 1; | 26731 | rme = &m->req_module_entries[m->req_module_entries_count++]; |
| 26360 | rme = &m->req_module_entries[i]; | | |
| 26361 | rme->module_name = JS_DupAtom(ctx, module_name); | 26732 | rme->module_name = JS_DupAtom(ctx, module_name); |
| 26362 | rme->module = NULL; | 26733 | rme->module = NULL; |
| 26363 | return i; | 26734 | return i; |
| @@ -26389,18 +26760,17 @@ static JSExportEntry *add_export_entry2(JSContext *ctx, · 25 unmodified lines |
| 26389 | js_parse_error(s, "duplicate exported name '%s'", | 26760 | js_parse_error(s, "duplicate exported name '%s'", |
| 26390 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name)); | 26761 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name)); |
| 26391 | } else { | 26762 | } else { |
| 26392 | JS_ThrowSyntaxError(ctx, "duplicate exported name '%s'", | 26763 | JS_ThrowSyntaxErrorAtom(ctx, "duplicate exported name '%s'", export_name); |
| 26393 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name)); | | |
| 26394 | } | 26764 | } |
| 26395 | return NULL; | 26765 | return NULL; |
| 26396 | } | 26766 | } |
| 26397 | | 26767 | |
| 26398 | if (js_resize_array(ctx, (void **)&m->export_entries, | 26768 | if (js_resize_array(ctx, (void **)&m->export_entries, |
| 26399 | sizeof(JSExportEntry), | 26769 | sizeof(JSExportEntry), |
| 26400 | &m->export_entries_size, &m->export_entries_count, | 26770 | &m->export_entries_size, |
| 26401 | m->export_entries_count + 1)) | 26771 | m->export_entries_count + 1)) |
| 26402 | return NULL; | 26772 | return NULL; |
| 26403 | me = &m->export_entries[m->export_entries_count - 1]; | 26773 | me = &m->export_entries[m->export_entries_count++]; |
| 26404 | memset(me, 0, sizeof(*me)); | 26774 | memset(me, 0, sizeof(*me)); |
| 26405 | me->local_name = JS_DupAtom(ctx, local_name); | 26775 | me->local_name = JS_DupAtom(ctx, local_name); |
| 26406 | me->export_name = JS_DupAtom(ctx, export_name); | 26776 | me->export_name = JS_DupAtom(ctx, export_name); |
| @@ -26423,10 +26793,10 @@ static int add_star_export_entry(JSContext *ctx, JSModuleDef *m, · 16 unmodified lines |
| 26423 | | 26793 | |
| 26424 | if (js_resize_array(ctx, (void **)&m->star_export_entries, | 26794 | if (js_resize_array(ctx, (void **)&m->star_export_entries, |
| 26425 | sizeof(JSStarExportEntry), | 26795 | sizeof(JSStarExportEntry), |
| 26426 | &m->star_export_entries_size, &m->star_export_entries_count, | 26796 | &m->star_export_entries_size, |
| 26427 | m->star_export_entries_count + 1)) | 26797 | m->star_export_entries_count + 1)) |
| 26428 | return -1; | 26798 | return -1; |
| 26429 | se = &m->star_export_entries[m->star_export_entries_count - 1]; | 26799 | se = &m->star_export_entries[m->star_export_entries_count++]; |
| 26430 | se->req_module_idx = req_module_idx; | 26800 | se->req_module_idx = req_module_idx; |
| 26431 | return 0; | 26801 | return 0; |
| 26432 | } | 26802 | } |
| @@ -26652,10 +27022,9 @@ static int add_resolve_entry(JSContext *ctx, JSResolveState *s, · 219 unmodified lines |
| 26652 | | 27022 | |
| 26653 | if (js_resize_array(ctx, (void **)&s->array, | 27023 | if (js_resize_array(ctx, (void **)&s->array, |
| 26654 | sizeof(JSResolveEntry), | 27024 | sizeof(JSResolveEntry), |
| 26655 | &s->size, &s->count, | 27025 | &s->size, s->count + 1)) |
| 26656 | s->count + 1)) | | |
| 26657 | return -1; | 27026 | return -1; |
| 26658 | re = &s->array[s->count - 1]; | 27027 | re = &s->array[s->count++]; |
| 26659 | re->module = m; | 27028 | re->module = m; |
| 26660 | re->name = JS_DupAtom(ctx, name); | 27029 | re->name = JS_DupAtom(ctx, name); |
| 26661 | return 0; | 27030 | return 0; |
| @@ -26780,17 +27149,17 @@ static void js_resolve_export_throw_error(JSContext *ctx, · 118 unmodified lines |
| 26780 | break; | 27149 | break; |
| 26781 | default: | 27150 | default: |
| 26782 | case JS_RESOLVE_RES_NOT_FOUND: | 27151 | case JS_RESOLVE_RES_NOT_FOUND: |
| 26783 | JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous", | 27152 | JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'", |
| 26784 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), | 27153 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), |
| 26785 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); | 27154 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); |
| 26786 | break; | 27155 | break; |
| 26787 | case JS_RESOLVE_RES_CIRCULAR: | 27156 | case JS_RESOLVE_RES_CIRCULAR: |
| 26788 | JS_ThrowSyntaxError(ctx, "Could not find export '%s' in module '%s'", | 27157 | JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'", |
| 26789 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), | 27158 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), |
| 26790 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); | 27159 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); |
| 26791 | break; | 27160 | break; |
| 26792 | case JS_RESOLVE_RES_AMBIGUOUS: | 27161 | case JS_RESOLVE_RES_AMBIGUOUS: |
| 26793 | JS_ThrowSyntaxError(ctx, "circular reference when looking for export '%s' in module '%s'", | 27162 | JS_ThrowSyntaxError(ctx, "export '%s' in module '%s' is ambiguous", |
| 26794 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), | 27163 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), export_name), |
| 26795 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); | 27164 | JS_AtomGetStr(ctx, buf2, sizeof(buf2), m->module_name)); |
| 26796 | break; | 27165 | break; |
| @@ -26847,9 +27216,9 @@ static __exception int get_exported_names(JSContext *ctx, · 50 unmodified lines |
| 26847 | return 0; | 27216 | return 0; |
| 26848 | } | 27217 | } |
| 26849 | if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]), | 27218 | if (js_resize_array(ctx, (void **)&s->modules, sizeof(s->modules[0]), |
| 26850 | &s->modules_size, &s->modules_count, s->modules_count + 1)) | 27219 | &s->modules_size, s->modules_count + 1)) |
| 26851 | return -1; | 27220 | return -1; |
| 26852 | s->modules[s->modules_count - 1] = m; | 27221 | s->modules[s->modules_count++] = m; |
| 26853 | | 27222 | |
| 26854 | for(i = 0; i < m->export_entries_count; i++) { | 27223 | for(i = 0; i < m->export_entries_count; i++) { |
| 26855 | JSExportEntry *me = &m->export_entries[i]; | 27224 | JSExportEntry *me = &m->export_entries[i]; |
| @@ -26858,9 +27227,10 @@ static __exception int get_exported_names(JSContext *ctx, · 2 unmodified lines |
| 26858 | j = find_exported_name(s, me->export_name); | 27227 | j = find_exported_name(s, me->export_name); |
| 26859 | if (j < 0) { | 27228 | if (j < 0) { |
| 26860 | if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]), | 27229 | if (js_resize_array(ctx, (void **)&s->exported_names, sizeof(s->exported_names[0]), |
| 26861 | &s->exported_names_size, &s->exported_names_count, s->exported_names_count + 1)) | 27230 | &s->exported_names_size, |
| | 27231 | s->exported_names_count + 1)) |
| 26862 | return -1; | 27232 | return -1; |
| 26863 | en = &s->exported_names[s->exported_names_count - 1]; | 27233 | en = &s->exported_names[s->exported_names_count++]; |
| 26864 | en->export_name = me->export_name; | 27234 | en->export_name = me->export_name; |
| 26865 | /* avoid a second lookup for simple module exports */ | 27235 | /* avoid a second lookup for simple module exports */ |
| 26866 | if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL) | 27236 | if (from_star || me->export_type != JS_EXPORT_TYPE_LOCAL) |
| @@ -27096,7 +27466,7 @@ static JSVarRef *js_create_module_var(JSContext *ctx, BOOL is_lexical) · 229 unmodified lines |
| 27096 | } | 27466 | } |
| 27097 | | 27467 | |
| 27098 | /* Create the <eval> function associated with the module */ | 27468 | /* Create the <eval> function associated with the module */ |
| 27099 | static int js_create_module_function(JSContext *ctx, JSModuleDef *m) | 27469 | static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m) |
| 27100 | { | 27470 | { |
| 27101 | JSFunctionBytecode *b; | 27471 | JSFunctionBytecode *b; |
| 27102 | int i; | 27472 | int i; |
| @@ -27147,20 +27517,15 @@ static int js_create_module_function(JSContext *ctx, JSModuleDef *m) · 44 unmodified lines |
| 27147 | return -1; | 27517 | return -1; |
| 27148 | } | 27518 | } |
| 27149 | | 27519 | |
| 27150 | /* Prepare a module to be executed by resolving all the imported | 27520 | /* must be done before js_instantiate_module() because of cyclic references */ |
| 27151 | variables. */ | 27521 | static int js_create_module_function(JSContext *ctx, JSModuleDef *m) |
| 27152 | static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) | | |
| 27153 | { | 27522 | { |
| 27154 | int i; | | |
| 27155 | JSImportEntry *mi; | | |
| 27156 | JSModuleDef *m1; | | |
| 27157 | JSVarRef **var_refs, *var_ref; | | |
| 27158 | JSObject *p; | | |
| 27159 | BOOL is_c_module; | 27523 | BOOL is_c_module; |
| 27160 | | 27524 | int i; |
| 27161 | if (m->instantiated) | 27525 | JSVarRef *var_ref; |
| | 27526 | |
| | 27527 | if (m->func_created) |
| 27162 | return 0; | 27528 | return 0; |
| 27163 | m->instantiated = TRUE; | | |
| 27164 | | 27529 | |
| 27165 | is_c_module = (m->init_func != NULL); | 27530 | is_c_module = (m->init_func != NULL); |
| 27166 | | 27531 | |
| @@ -27171,14 +27536,49 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 4 unmodified lines |
| 27171 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { | 27536 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { |
| 27172 | var_ref = js_create_module_var(ctx, FALSE); | 27537 | var_ref = js_create_module_var(ctx, FALSE); |
| 27173 | if (!var_ref) | 27538 | if (!var_ref) |
| 27174 | goto fail; | 27539 | return -1; |
| 27175 | me->u.local.var_ref = var_ref; | 27540 | me->u.local.var_ref = var_ref; |
| 27176 | } | 27541 | } |
| 27177 | } | 27542 | } |
| 27178 | } else { | 27543 | } else { |
| 27179 | if (js_create_module_function(ctx, m) < 0) | 27544 | if (js_create_module_bytecode_function(ctx, m)) |
| 27180 | goto fail; | 27545 | return -1; |
| 27181 | } | 27546 | } |
| | 27547 | m->func_created = TRUE; |
| | 27548 | |
| | 27549 | /* do it on the dependencies */ |
| | 27550 | |
| | 27551 | for(i = 0; i < m->req_module_entries_count; i++) { |
| | 27552 | JSReqModuleEntry *rme = &m->req_module_entries[i]; |
| | 27553 | if (js_create_module_function(ctx, rme->module) < 0) |
| | 27554 | return -1; |
| | 27555 | } |
| | 27556 | |
| | 27557 | return 0; |
| | 27558 | } |
| | 27559 | |
| | 27560 | |
| | 27561 | /* Prepare a module to be executed by resolving all the imported |
| | 27562 | variables. */ |
| | 27563 | static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) |
| | 27564 | { |
| | 27565 | int i; |
| | 27566 | JSImportEntry *mi; |
| | 27567 | JSModuleDef *m1; |
| | 27568 | JSVarRef **var_refs, *var_ref; |
| | 27569 | JSObject *p; |
| | 27570 | BOOL is_c_module; |
| | 27571 | |
| | 27572 | if (m->instantiated) |
| | 27573 | return 0; |
| | 27574 | m->instantiated = TRUE; |
| | 27575 | |
| | 27576 | #ifdef DUMP_MODULE_RESOLVE |
| | 27577 | { |
| | 27578 | char buf1[ATOM_GET_STR_BUF_SIZE]; |
| | 27579 | printf("start instantiating module '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name)); |
| | 27580 | } |
| | 27581 | #endif |
| 27182 | | 27582 | |
| 27183 | for(i = 0; i < m->req_module_entries_count; i++) { | 27583 | for(i = 0; i < m->req_module_entries_count; i++) { |
| 27184 | JSReqModuleEntry *rme = &m->req_module_entries[i]; | 27584 | JSReqModuleEntry *rme = &m->req_module_entries[i]; |
| @@ -27221,6 +27621,8 @@ static int js_instantiate_module(JSContext *ctx, JSModuleDef *m) · 36 unmodified lines |
| 27221 | } | 27621 | } |
| 27222 | #endif | 27622 | #endif |
| 27223 | | 27623 | |
| | 27624 | is_c_module = (m->init_func != NULL); |
| | 27625 | |
| 27224 | if (!is_c_module) { | 27626 | if (!is_c_module) { |
| 27225 | p = JS_VALUE_GET_OBJ(m->func_obj); | 27627 | p = JS_VALUE_GET_OBJ(m->func_obj); |
| 27226 | var_refs = p->u.func.var_refs; | 27628 | var_refs = p->u.func.var_refs; |
| @@ -27740,10 +28142,10 @@ static int add_import(JSParseState *s, JSModuleDef *m, · 513 unmodified lines |
| 27740 | return -1; | 28142 | return -1; |
| 27741 | if (js_resize_array(ctx, (void **)&m->import_entries, | 28143 | if (js_resize_array(ctx, (void **)&m->import_entries, |
| 27742 | sizeof(JSImportEntry), | 28144 | sizeof(JSImportEntry), |
| 27743 | &m->import_entries_size, &m->import_entries_count, | 28145 | &m->import_entries_size, |
| 27744 | m->import_entries_count + 1)) | 28146 | m->import_entries_count + 1)) |
| 27745 | return -1; | 28147 | return -1; |
| 27746 | mi = &m->import_entries[m->import_entries_count - 1]; | 28148 | mi = &m->import_entries[m->import_entries_count++]; |
| 27747 | mi->import_name = JS_DupAtom(ctx, import_name); | 28149 | mi->import_name = JS_DupAtom(ctx, import_name); |
| 27748 | mi->var_idx = var_idx; | 28150 | mi->var_idx = var_idx; |
| 27749 | return 0; | 28151 | return 0; |
| @@ -28474,20 +28876,10 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s, · 724 unmodified lines |
| 28474 | return -1; | 28876 | return -1; |
| 28475 | } | 28877 | } |
| 28476 | | 28878 | |
| 28477 | if (s->closure_var_count >= s->closure_var_size) { | 28879 | if (js_resize_array(ctx, (void **)&s->closure_var, |
| 28478 | JSClosureVar *new_tab; | 28880 | sizeof(s->closure_var[0]), |
| 28479 | int new_size; | 28881 | &s->closure_var_size, s->closure_var_count + 1)) |
| 28480 | size_t slack; | 28882 | return -1; |
| 28481 | new_size = max_int(s->closure_var_count + 1, | | |
| 28482 | s->closure_var_size * 3 / 2); | | |
| 28483 | new_tab = js_realloc2(ctx, s->closure_var, | | |
| 28484 | new_size * sizeof(JSClosureVar), &slack); | | |
| 28485 | if (!new_tab) | | |
| 28486 | return -1; | | |
| 28487 | new_size += slack / sizeof(*new_tab); | | |
| 28488 | s->closure_var = new_tab; | | |
| 28489 | s->closure_var_size = new_size; | | |
| 28490 | } | | |
| 28491 | cv = &s->closure_var[s->closure_var_count++]; | 28883 | cv = &s->closure_var[s->closure_var_count++]; |
| 28492 | cv->is_local = is_local; | 28884 | cv->is_local = is_local; |
| 28493 | cv->is_arg = is_arg; | 28885 | cv->is_arg = is_arg; |
| @@ -29243,8 +29635,6 @@ static int resolve_scope_private_field1(JSContext *ctx, · 749 unmodified lines |
| 29243 | } | 29635 | } |
| 29244 | scope_level = fd->parent_scope_level; | 29636 | scope_level = fd->parent_scope_level; |
| 29245 | if (!fd->parent) { | 29637 | if (!fd->parent) { |
| 29246 | char buf[ATOM_GET_STR_BUF_SIZE]; | | |
| 29247 | | | |
| 29248 | if (fd->is_eval) { | 29638 | if (fd->is_eval) { |
| 29249 | /* closure of the eval function (top level) */ | 29639 | /* closure of the eval function (top level) */ |
| 29250 | for (idx = 0; idx < fd->closure_var_count; idx++) { | 29640 | for (idx = 0; idx < fd->closure_var_count; idx++) { |
| @@ -29267,8 +29657,8 @@ static int resolve_scope_private_field1(JSContext *ctx, · 16 unmodified lines |
| 29267 | } | 29657 | } |
| 29268 | } | 29658 | } |
| 29269 | /* XXX: no line number info */ | 29659 | /* XXX: no line number info */ |
| 29270 | JS_ThrowSyntaxError(ctx, "undefined private field %s", | 29660 | JS_ThrowSyntaxErrorAtom(ctx, "undefined private field '%s'", |
| 29271 | JS_AtomGetStr(ctx, buf, sizeof(buf), var_name)); | 29661 | var_name); |
| 29272 | return -1; | 29662 | return -1; |
| 29273 | } else { | 29663 | } else { |
| 29274 | fd = fd->parent; | 29664 | fd = fd->parent; |
| @@ -31535,9 +31925,8 @@ static int add_module_variables(JSContext *ctx, JSFunctionDef *fd) · 2260 unmodified lines |
| 31535 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { | 31925 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { |
| 31536 | idx = find_closure_var(ctx, fd, me->local_name); | 31926 | idx = find_closure_var(ctx, fd, me->local_name); |
| 31537 | if (idx < 0) { | 31927 | if (idx < 0) { |
| 31538 | char buf1[ATOM_GET_STR_BUF_SIZE]; | 31928 | JS_ThrowSyntaxErrorAtom(ctx, "exported variable '%s' does not exist", |
| 31539 | JS_ThrowSyntaxError(ctx, "exported variable '%s' does not exist", | 31929 | me->local_name); |
| 31540 | JS_AtomGetStr(ctx, buf1, sizeof(buf1), me->local_name)); | | |
| 31541 | return -1; | 31930 | return -1; |
| 31542 | } | 31931 | } |
| 31543 | me->u.local.var_idx = idx; | 31932 | me->u.local.var_idx = idx; |
| @@ -32559,6 +32948,8 @@ static JSValue JS_EvalFunctionInternal(JSContext *ctx, JSValue fun_obj, · 1015 unmodified lines |
| 32559 | m = JS_VALUE_GET_PTR(fun_obj); | 32948 | m = JS_VALUE_GET_PTR(fun_obj); |
| 32560 | /* the module refcount should be >= 2 */ | 32949 | /* the module refcount should be >= 2 */ |
| 32561 | JS_FreeValue(ctx, fun_obj); | 32950 | JS_FreeValue(ctx, fun_obj); |
| | 32951 | if (js_create_module_function(ctx, m) < 0) |
| | 32952 | goto fail; |
| 32562 | if (js_instantiate_module(ctx, m) < 0) | 32953 | if (js_instantiate_module(ctx, m) < 0) |
| 32563 | goto fail; | 32954 | goto fail; |
| 32564 | ret_val = js_evaluate_module(ctx, m); | 32955 | ret_val = js_evaluate_module(ctx, m); |
| @@ -32769,6 +33160,110 @@ int JS_ResolveModule(JSContext *ctx, JSValueConst obj) · 204 unmodified lines |
| 32769 | return 0; | 33160 | return 0; |
| 32770 | } | 33161 | } |
| 32771 | | 33162 | |
| | 33163 | /*******************************************************************/ |
| | 33164 | /* object list */ |
| | 33165 | |
| | 33166 | typedef struct { |
| | 33167 | JSObject *obj; |
| | 33168 | uint32_t hash_next; /* -1 if no next entry */ |
| | 33169 | } JSObjectListEntry; |
| | 33170 | |
| | 33171 | /* XXX: reuse it to optimize weak references */ |
| | 33172 | typedef struct { |
| | 33173 | JSObjectListEntry *object_tab; |
| | 33174 | int object_count; |
| | 33175 | int object_size; |
| | 33176 | uint32_t *hash_table; |
| | 33177 | uint32_t hash_size; |
| | 33178 | } JSObjectList; |
| | 33179 | |
| | 33180 | static void js_object_list_init(JSObjectList *s) |
| | 33181 | { |
| | 33182 | memset(s, 0, sizeof(*s)); |
| | 33183 | } |
| | 33184 | |
| | 33185 | static uint32_t js_object_list_get_hash(JSObject *p, uint32_t hash_size) |
| | 33186 | { |
| | 33187 | return ((uintptr_t)p * 3163) & (hash_size - 1); |
| | 33188 | } |
| | 33189 | |
| | 33190 | static int js_object_list_resize_hash(JSContext *ctx, JSObjectList *s, |
| | 33191 | uint32_t new_hash_size) |
| | 33192 | { |
| | 33193 | JSObjectListEntry *e; |
| | 33194 | uint32_t i, h, *new_hash_table; |
| | 33195 | |
| | 33196 | new_hash_table = js_malloc(ctx, sizeof(new_hash_table[0]) * new_hash_size); |
| | 33197 | if (!new_hash_table) |
| | 33198 | return -1; |
| | 33199 | js_free(ctx, s->hash_table); |
| | 33200 | s->hash_table = new_hash_table; |
| | 33201 | s->hash_size = new_hash_size; |
| | 33202 | |
| | 33203 | for(i = 0; i < s->hash_size; i++) { |
| | 33204 | s->hash_table[i] = -1; |
| | 33205 | } |
| | 33206 | for(i = 0; i < s->object_count; i++) { |
| | 33207 | e = &s->object_tab[i]; |
| | 33208 | h = js_object_list_get_hash(e->obj, s->hash_size); |
| | 33209 | e->hash_next = s->hash_table[h]; |
| | 33210 | s->hash_table[h] = i; |
| | 33211 | } |
| | 33212 | return 0; |
| | 33213 | } |
| | 33214 | |
| | 33215 | /* the reference count of 'obj' is not modified. Return 0 if OK, -1 if |
| | 33216 | memory error */ |
| | 33217 | static int js_object_list_add(JSContext *ctx, JSObjectList *s, JSObject *obj) |
| | 33218 | { |
| | 33219 | JSObjectListEntry *e; |
| | 33220 | uint32_t h, new_hash_size; |
| | 33221 | |
| | 33222 | if (js_resize_array(ctx, (void *)&s->object_tab, |
| | 33223 | sizeof(s->object_tab[0]), |
| | 33224 | &s->object_size, s->object_count + 1)) |
| | 33225 | return -1; |
| | 33226 | if (unlikely((s->object_count + 1) >= s->hash_size)) { |
| | 33227 | new_hash_size = max_uint32(s->hash_size, 4); |
| | 33228 | while (new_hash_size <= s->object_count) |
| | 33229 | new_hash_size *= 2; |
| | 33230 | if (js_object_list_resize_hash(ctx, s, new_hash_size)) |
| | 33231 | return -1; |
| | 33232 | } |
| | 33233 | e = &s->object_tab[s->object_count++]; |
| | 33234 | h = js_object_list_get_hash(obj, s->hash_size); |
| | 33235 | e->obj = obj; |
| | 33236 | e->hash_next = s->hash_table[h]; |
| | 33237 | s->hash_table[h] = s->object_count - 1; |
| | 33238 | return 0; |
| | 33239 | } |
| | 33240 | |
| | 33241 | /* return -1 if not present or the object index */ |
| | 33242 | static int js_object_list_find(JSContext *ctx, JSObjectList *s, JSObject *obj) |
| | 33243 | { |
| | 33244 | JSObjectListEntry *e; |
| | 33245 | uint32_t h, p; |
| | 33246 | |
| | 33247 | /* must test empty size because there is no hash table */ |
| | 33248 | if (s->object_count == 0) |
| | 33249 | return -1; |
| | 33250 | h = js_object_list_get_hash(obj, s->hash_size); |
| | 33251 | p = s->hash_table[h]; |
| | 33252 | while (p != -1) { |
| | 33253 | e = &s->object_tab[p]; |
| | 33254 | if (e->obj == obj) |
| | 33255 | return p; |
| | 33256 | p = e->hash_next; |
| | 33257 | } |
| | 33258 | return -1; |
| | 33259 | } |
| | 33260 | |
| | 33261 | static void js_object_list_end(JSContext *ctx, JSObjectList *s) |
| | 33262 | { |
| | 33263 | js_free(ctx, s->object_tab); |
| | 33264 | js_free(ctx, s->hash_table); |
| | 33265 | } |
| | 33266 | |
| 32772 | /*******************************************************************/ | 33267 | /*******************************************************************/ |
| 32773 | /* binary object writer & reader */ | 33268 | /* binary object writer & reader */ |
| 32774 | | 33269 | |
| @@ -32788,6 +33283,12 @@ typedef enum BCTagEnum { · 13 unmodified lines |
| 32788 | BC_TAG_TEMPLATE_OBJECT, | 33283 | BC_TAG_TEMPLATE_OBJECT, |
| 32789 | BC_TAG_FUNCTION_BYTECODE, | 33284 | BC_TAG_FUNCTION_BYTECODE, |
| 32790 | BC_TAG_MODULE, | 33285 | BC_TAG_MODULE, |
| | 33286 | BC_TAG_TYPED_ARRAY, |
| | 33287 | BC_TAG_ARRAY_BUFFER, |
| | 33288 | BC_TAG_SHARED_ARRAY_BUFFER, |
| | 33289 | BC_TAG_DATE, |
| | 33290 | BC_TAG_OBJECT_VALUE, |
| | 33291 | BC_TAG_OBJECT_REFERENCE, |
| 32791 | } BCTagEnum; | 33292 | } BCTagEnum; |
| 32792 | | 33293 | |
| 32793 | #ifdef CONFIG_BIGNUM | 33294 | #ifdef CONFIG_BIGNUM |
| @@ -32805,14 +33306,21 @@ typedef enum BCTagEnum { · 11 unmodified lines |
| 32805 | typedef struct BCWriterState { | 33306 | typedef struct BCWriterState { |
| 32806 | JSContext *ctx; | 33307 | JSContext *ctx; |
| 32807 | DynBuf dbuf; | 33308 | DynBuf dbuf; |
| 32808 | BOOL byte_swap; | 33309 | BOOL byte_swap : 8; |
| 32809 | BOOL allow_bytecode; | 33310 | BOOL allow_bytecode : 8; |
| | 33311 | BOOL allow_sab : 8; |
| | 33312 | BOOL allow_reference : 8; |
| 32810 | uint32_t first_atom; | 33313 | uint32_t first_atom; |
| 32811 | uint32_t *atom_to_idx; | 33314 | uint32_t *atom_to_idx; |
| 32812 | int atom_to_idx_size; | 33315 | int atom_to_idx_size; |
| 32813 | JSAtom *idx_to_atom; | 33316 | JSAtom *idx_to_atom; |
| 32814 | int idx_to_atom_count; | 33317 | int idx_to_atom_count; |
| 32815 | int idx_to_atom_size; | 33318 | int idx_to_atom_size; |
| | 33319 | uint8_t **sab_tab; |
| | 33320 | int sab_tab_len; |
| | 33321 | int sab_tab_size; |
| | 33322 | /* list of referenced objects (used if allow_reference = TRUE) */ |
| | 33323 | JSObjectList object_list; |
| 32816 | } BCWriterState; | 33324 | } BCWriterState; |
| 32817 | | 33325 | |
| 32818 | #ifdef DUMP_READ_OBJECT | 33326 | #ifdef DUMP_READ_OBJECT |
| @@ -32833,6 +33341,12 @@ static const char * const bc_tag_str[] = { · 14 unmodified lines |
| 32833 | "template", | 33341 | "template", |
| 32834 | "function", | 33342 | "function", |
| 32835 | "module", | 33343 | "module", |
| | 33344 | "TypedArray", |
| | 33345 | "ArrayBuffer", |
| | 33346 | "SharedArrayBuffer", |
| | 33347 | "Date", |
| | 33348 | "ObjectValue", |
| | 33349 | "ObjectReference", |
| 32836 | }; | 33350 | }; |
| 32837 | #endif | 33351 | #endif |
| 32838 | | 33352 | |
| @@ -32892,36 +33406,20 @@ static int bc_atom_to_idx(BCWriterState *s, uint32_t *pres, JSAtom atom) · 53 unmodified lines |
| 32892 | return 0; | 33406 | return 0; |
| 32893 | } | 33407 | } |
| 32894 | if (atom >= s->atom_to_idx_size) { | 33408 | if (atom >= s->atom_to_idx_size) { |
| 32895 | size_t new_size, i, slack; | 33409 | int old_size, i; |
| 32896 | uint32_t *new_tab; | 33410 | old_size = s->atom_to_idx_size; |
| 32897 | /* XXX: potential arithmetic overflow */ | 33411 | if (js_resize_array(s->ctx, (void **)&s->atom_to_idx, |
| 32898 | new_size = s->atom_to_idx_size * 3 / 2; | 33412 | sizeof(s->atom_to_idx[0]), &s->atom_to_idx_size, |
| 32899 | if ((atom + 1) > new_size) | 33413 | atom + 1)) |
| 32900 | new_size = atom + 1; | 33414 | return -1; |
| 32901 | new_tab = js_realloc2(s->ctx, s->atom_to_idx, | 33415 | /* XXX: could add a specific js_resize_array() function to do it */ |
| 32902 | new_size * sizeof(s->atom_to_idx[0]), &slack); | 33416 | for(i = old_size; i < s->atom_to_idx_size; i++) |
| 32903 | if (!new_tab) | 33417 | s->atom_to_idx[i] = 0; |
| 32904 | goto fail; | | |
| 32905 | new_size += slack / sizeof(*new_tab); | | |
| 32906 | for(i = s->atom_to_idx_size; i < new_size; i++) | | |
| 32907 | new_tab[i] = 0; | | |
| 32908 | s->atom_to_idx = new_tab; | | |
| 32909 | s->atom_to_idx_size = new_size; | | |
| 32910 | } | | |
| 32911 | if ((s->idx_to_atom_count + 1) > s->idx_to_atom_size) { | | |
| 32912 | size_t new_size, slack; | | |
| 32913 | JSAtom *new_tab; | | |
| 32914 | new_size = s->idx_to_atom_size * 3 / 2; | | |
| 32915 | if ((s->idx_to_atom_count + 1) > new_size) | | |
| 32916 | new_size = s->idx_to_atom_count + 1; | | |
| 32917 | new_tab = js_realloc2(s->ctx, s->idx_to_atom, | | |
| 32918 | new_size * sizeof(s->idx_to_atom[0]), &slack); | | |
| 32919 | if (!new_tab) | | |
| 32920 | goto fail; | | |
| 32921 | new_size += slack / sizeof(*new_tab); | | |
| 32922 | s->idx_to_atom = new_tab; | | |
| 32923 | s->idx_to_atom_size = new_size; | | |
| 32924 | } | 33418 | } |
| | 33419 | if (js_resize_array(s->ctx, (void **)&s->idx_to_atom, |
| | 33420 | sizeof(s->idx_to_atom[0]), |
| | 33421 | &s->idx_to_atom_size, s->idx_to_atom_count + 1)) |
| | 33422 | goto fail; |
| 32925 | | 33423 | |
| 32926 | v = s->idx_to_atom_count++; | 33424 | v = s->idx_to_atom_count++; |
| 32927 | s->idx_to_atom[v] = atom + s->first_atom; | 33425 | s->idx_to_atom[v] = atom + s->first_atom; |
| @@ -33204,10 +33702,276 @@ static int JS_WriteBigNum(BCWriterState *s, JSValueConst obj) · 276 unmodified lines |
| 33204 | } | 33702 | } |
| 33205 | #endif /* CONFIG_BIGNUM */ | 33703 | #endif /* CONFIG_BIGNUM */ |
| 33206 | | 33704 | |
| | 33705 | static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj); |
| | 33706 | |
| | 33707 | static int JS_WriteFunctionTag(BCWriterState *s, JSValueConst obj) |
| | 33708 | { |
| | 33709 | JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj); |
| | 33710 | uint32_t flags; |
| | 33711 | int idx, i; |
| | 33712 | |
| | 33713 | bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE); |
| | 33714 | flags = idx = 0; |
| | 33715 | bc_set_flags(&flags, &idx, b->has_prototype, 1); |
| | 33716 | bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1); |
| | 33717 | bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1); |
| | 33718 | bc_set_flags(&flags, &idx, b->need_home_object, 1); |
| | 33719 | bc_set_flags(&flags, &idx, b->func_kind, 2); |
| | 33720 | bc_set_flags(&flags, &idx, b->new_target_allowed, 1); |
| | 33721 | bc_set_flags(&flags, &idx, b->super_call_allowed, 1); |
| | 33722 | bc_set_flags(&flags, &idx, b->super_allowed, 1); |
| | 33723 | bc_set_flags(&flags, &idx, b->arguments_allowed, 1); |
| | 33724 | bc_set_flags(&flags, &idx, b->has_debug, 1); |
| | 33725 | bc_set_flags(&flags, &idx, b->backtrace_barrier, 1); |
| | 33726 | assert(idx <= 16); |
| | 33727 | bc_put_u16(s, flags); |
| | 33728 | bc_put_u8(s, b->js_mode); |
| | 33729 | bc_put_atom(s, b->func_name); |
| | 33730 | |
| | 33731 | bc_put_leb128(s, b->arg_count); |
| | 33732 | bc_put_leb128(s, b->var_count); |
| | 33733 | bc_put_leb128(s, b->defined_arg_count); |
| | 33734 | bc_put_leb128(s, b->stack_size); |
| | 33735 | bc_put_leb128(s, b->closure_var_count); |
| | 33736 | bc_put_leb128(s, b->cpool_count); |
| | 33737 | bc_put_leb128(s, b->byte_code_len); |
| | 33738 | if (b->vardefs) { |
| | 33739 | bc_put_leb128(s, b->arg_count + b->var_count); |
| | 33740 | for(i = 0; i < b->arg_count + b->var_count; i++) { |
| | 33741 | JSVarDef *vd = &b->vardefs[i]; |
| | 33742 | bc_put_atom(s, vd->var_name); |
| | 33743 | bc_put_leb128(s, vd->scope_level); |
| | 33744 | bc_put_leb128(s, vd->scope_next + 1); |
| | 33745 | flags = idx = 0; |
| | 33746 | bc_set_flags(&flags, &idx, vd->var_kind, 4); |
| | 33747 | bc_set_flags(&flags, &idx, vd->is_func_var, 1); |
| | 33748 | bc_set_flags(&flags, &idx, vd->is_const, 1); |
| | 33749 | bc_set_flags(&flags, &idx, vd->is_lexical, 1); |
| | 33750 | bc_set_flags(&flags, &idx, vd->is_captured, 1); |
| | 33751 | assert(idx <= 8); |
| | 33752 | bc_put_u8(s, flags); |
| | 33753 | } |
| | 33754 | } else { |
| | 33755 | bc_put_leb128(s, 0); |
| | 33756 | } |
| | 33757 | |
| | 33758 | for(i = 0; i < b->closure_var_count; i++) { |
| | 33759 | JSClosureVar *cv = &b->closure_var[i]; |
| | 33760 | bc_put_atom(s, cv->var_name); |
| | 33761 | bc_put_leb128(s, cv->var_idx); |
| | 33762 | flags = idx = 0; |
| | 33763 | bc_set_flags(&flags, &idx, cv->is_local, 1); |
| | 33764 | bc_set_flags(&flags, &idx, cv->is_arg, 1); |
| | 33765 | bc_set_flags(&flags, &idx, cv->is_const, 1); |
| | 33766 | bc_set_flags(&flags, &idx, cv->is_lexical, 1); |
| | 33767 | bc_set_flags(&flags, &idx, cv->var_kind, 4); |
| | 33768 | assert(idx <= 8); |
| | 33769 | bc_put_u8(s, flags); |
| | 33770 | } |
| | 33771 | |
| | 33772 | if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len)) |
| | 33773 | goto fail; |
| | 33774 | |
| | 33775 | if (b->has_debug) { |
| | 33776 | bc_put_atom(s, b->debug.filename); |
| | 33777 | bc_put_leb128(s, b->debug.line_num); |
| | 33778 | bc_put_leb128(s, b->debug.pc2line_len); |
| | 33779 | dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len); |
| | 33780 | } |
| | 33781 | |
| | 33782 | for(i = 0; i < b->cpool_count; i++) { |
| | 33783 | if (JS_WriteObjectRec(s, b->cpool[i])) |
| | 33784 | goto fail; |
| | 33785 | } |
| | 33786 | return 0; |
| | 33787 | fail: |
| | 33788 | return -1; |
| | 33789 | } |
| | 33790 | |
| | 33791 | static int JS_WriteModule(BCWriterState *s, JSValueConst obj) |
| | 33792 | { |
| | 33793 | JSModuleDef *m = JS_VALUE_GET_PTR(obj); |
| | 33794 | int i; |
| | 33795 | |
| | 33796 | bc_put_u8(s, BC_TAG_MODULE); |
| | 33797 | bc_put_atom(s, m->module_name); |
| | 33798 | |
| | 33799 | bc_put_leb128(s, m->req_module_entries_count); |
| | 33800 | for(i = 0; i < m->req_module_entries_count; i++) { |
| | 33801 | JSReqModuleEntry *rme = &m->req_module_entries[i]; |
| | 33802 | bc_put_atom(s, rme->module_name); |
| | 33803 | } |
| | 33804 | |
| | 33805 | bc_put_leb128(s, m->export_entries_count); |
| | 33806 | for(i = 0; i < m->export_entries_count; i++) { |
| | 33807 | JSExportEntry *me = &m->export_entries[i]; |
| | 33808 | bc_put_u8(s, me->export_type); |
| | 33809 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { |
| | 33810 | bc_put_leb128(s, me->u.local.var_idx); |
| | 33811 | } else { |
| | 33812 | bc_put_leb128(s, me->u.req_module_idx); |
| | 33813 | bc_put_atom(s, me->local_name); |
| | 33814 | } |
| | 33815 | bc_put_atom(s, me->export_name); |
| | 33816 | } |
| | 33817 | |
| | 33818 | bc_put_leb128(s, m->star_export_entries_count); |
| | 33819 | for(i = 0; i < m->star_export_entries_count; i++) { |
| | 33820 | JSStarExportEntry *se = &m->star_export_entries[i]; |
| | 33821 | bc_put_leb128(s, se->req_module_idx); |
| | 33822 | } |
| | 33823 | |
| | 33824 | bc_put_leb128(s, m->import_entries_count); |
| | 33825 | for(i = 0; i < m->import_entries_count; i++) { |
| | 33826 | JSImportEntry *mi = &m->import_entries[i]; |
| | 33827 | bc_put_leb128(s, mi->var_idx); |
| | 33828 | bc_put_atom(s, mi->import_name); |
| | 33829 | bc_put_leb128(s, mi->req_module_idx); |
| | 33830 | } |
| | 33831 | |
| | 33832 | if (JS_WriteObjectRec(s, m->func_obj)) |
| | 33833 | goto fail; |
| | 33834 | return 0; |
| | 33835 | fail: |
| | 33836 | return -1; |
| | 33837 | } |
| | 33838 | |
| | 33839 | static int JS_WriteArray(BCWriterState *s, JSValueConst obj) |
| | 33840 | { |
| | 33841 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| | 33842 | uint32_t i, len; |
| | 33843 | JSValue val; |
| | 33844 | int ret; |
| | 33845 | BOOL is_template; |
| | 33846 | |
| | 33847 | if (s->allow_bytecode && !p->extensible) { |
| | 33848 | /* not extensible array: we consider it is a |
| | 33849 | template when we are saving bytecode */ |
| | 33850 | bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT); |
| | 33851 | is_template = TRUE; |
| | 33852 | } else { |
| | 33853 | bc_put_u8(s, BC_TAG_ARRAY); |
| | 33854 | is_template = FALSE; |
| | 33855 | } |
| | 33856 | if (js_get_length32(s->ctx, &len, obj)) |
| | 33857 | goto fail1; |
| | 33858 | bc_put_leb128(s, len); |
| | 33859 | for(i = 0; i < len; i++) { |
| | 33860 | val = JS_GetPropertyUint32(s->ctx, obj, i); |
| | 33861 | if (JS_IsException(val)) |
| | 33862 | goto fail1; |
| | 33863 | ret = JS_WriteObjectRec(s, val); |
| | 33864 | JS_FreeValue(s->ctx, val); |
| | 33865 | if (ret) |
| | 33866 | goto fail1; |
| | 33867 | } |
| | 33868 | if (is_template) { |
| | 33869 | val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw); |
| | 33870 | if (JS_IsException(val)) |
| | 33871 | goto fail1; |
| | 33872 | ret = JS_WriteObjectRec(s, val); |
| | 33873 | JS_FreeValue(s->ctx, val); |
| | 33874 | if (ret) |
| | 33875 | goto fail1; |
| | 33876 | } |
| | 33877 | return 0; |
| | 33878 | fail1: |
| | 33879 | return -1; |
| | 33880 | } |
| | 33881 | |
| | 33882 | static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) |
| | 33883 | { |
| | 33884 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| | 33885 | uint32_t i, prop_count; |
| | 33886 | JSShape *sh; |
| | 33887 | JSShapeProperty *pr; |
| | 33888 | int pass; |
| | 33889 | JSAtom atom; |
| | 33890 | |
| | 33891 | bc_put_u8(s, BC_TAG_OBJECT); |
| | 33892 | prop_count = 0; |
| | 33893 | sh = p->shape; |
| | 33894 | for(pass = 0; pass < 2; pass++) { |
| | 33895 | if (pass == 1) |
| | 33896 | bc_put_leb128(s, prop_count); |
| | 33897 | for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { |
| | 33898 | atom = pr->atom; |
| | 33899 | if (atom != JS_ATOM_NULL && |
| | 33900 | JS_AtomIsString(s->ctx, atom) && |
| | 33901 | (pr->flags & JS_PROP_ENUMERABLE)) { |
| | 33902 | if (pr->flags & JS_PROP_TMASK) { |
| | 33903 | JS_ThrowTypeError(s->ctx, "only value properties are supported"); |
| | 33904 | goto fail; |
| | 33905 | } |
| | 33906 | if (pass == 0) { |
| | 33907 | prop_count++; |
| | 33908 | } else { |
| | 33909 | bc_put_atom(s, atom); |
| | 33910 | if (JS_WriteObjectRec(s, p->prop[i].u.value)) |
| | 33911 | goto fail; |
| | 33912 | } |
| | 33913 | } |
| | 33914 | } |
| | 33915 | } |
| | 33916 | return 0; |
| | 33917 | fail: |
| | 33918 | return -1; |
| | 33919 | } |
| | 33920 | |
| | 33921 | static int JS_WriteTypedArray(BCWriterState *s, JSValueConst obj) |
| | 33922 | { |
| | 33923 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| | 33924 | JSTypedArray *ta = p->u.typed_array; |
| | 33925 | |
| | 33926 | bc_put_u8(s, BC_TAG_TYPED_ARRAY); |
| | 33927 | bc_put_u8(s, p->class_id - JS_CLASS_UINT8C_ARRAY); |
| | 33928 | bc_put_leb128(s, p->u.array.count); |
| | 33929 | bc_put_leb128(s, ta->offset); |
| | 33930 | if (JS_WriteObjectRec(s, JS_MKPTR(JS_TAG_OBJECT, ta->buffer))) |
| | 33931 | return -1; |
| | 33932 | return 0; |
| | 33933 | } |
| | 33934 | |
| | 33935 | static int JS_WriteArrayBuffer(BCWriterState *s, JSValueConst obj) |
| | 33936 | { |
| | 33937 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| | 33938 | JSArrayBuffer *abuf = p->u.array_buffer; |
| | 33939 | if (abuf->detached) { |
| | 33940 | JS_ThrowTypeErrorDetachedArrayBuffer(s->ctx); |
| | 33941 | return -1; |
| | 33942 | } |
| | 33943 | bc_put_u8(s, BC_TAG_ARRAY_BUFFER); |
| | 33944 | bc_put_leb128(s, abuf->byte_length); |
| | 33945 | dbuf_put(&s->dbuf, abuf->data, abuf->byte_length); |
| | 33946 | return 0; |
| | 33947 | } |
| | 33948 | |
| | 33949 | static int JS_WriteSharedArrayBuffer(BCWriterState *s, JSValueConst obj) |
| | 33950 | { |
| | 33951 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| | 33952 | JSArrayBuffer *abuf = p->u.array_buffer; |
| | 33953 | assert(!abuf->detached); /* SharedArrayBuffer are never detached */ |
| | 33954 | bc_put_u8(s, BC_TAG_SHARED_ARRAY_BUFFER); |
| | 33955 | bc_put_leb128(s, abuf->byte_length); |
| | 33956 | bc_put_u64(s, (uintptr_t)abuf->data); |
| | 33957 | if (js_resize_array(s->ctx, (void **)&s->sab_tab, sizeof(s->sab_tab[0]), |
| | 33958 | &s->sab_tab_size, s->sab_tab_len + 1)) |
| | 33959 | return -1; |
| | 33960 | /* keep the SAB pointer so that the user can clone it or free it */ |
| | 33961 | s->sab_tab[s->sab_tab_len++] = abuf->data; |
| | 33962 | return 0; |
| | 33963 | } |
| | 33964 | |
| 33207 | static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) | 33965 | static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) |
| 33208 | { | 33966 | { |
| 33209 | uint32_t tag = JS_VALUE_GET_NORM_TAG(obj); | 33967 | uint32_t tag; |
| | 33968 | |
| | 33969 | if (js_check_stack_overflow(s->ctx->rt, 0)) { |
| | 33970 | JS_ThrowStackOverflow(s->ctx); |
| | 33971 | return -1; |
| | 33972 | } |
| 33210 | | 33973 | |
| | 33974 | tag = JS_VALUE_GET_NORM_TAG(obj); |
| 33211 | switch(tag) { | 33975 | switch(tag) { |
| 33212 | case JS_TAG_NULL: | 33976 | case JS_TAG_NULL: |
| 33213 | bc_put_u8(s, BC_TAG_NULL); | 33977 | bc_put_u8(s, BC_TAG_NULL); |
| @@ -33238,218 +34002,82 @@ static int JS_WriteObjectRec(BCWriterState *s, JSValueConst obj) · 24 unmodified lines |
| 33238 | } | 34002 | } |
| 33239 | break; | 34003 | break; |
| 33240 | case JS_TAG_FUNCTION_BYTECODE: | 34004 | case JS_TAG_FUNCTION_BYTECODE: |
| 33241 | { | 34005 | if (!s->allow_bytecode) |
| 33242 | JSFunctionBytecode *b = JS_VALUE_GET_PTR(obj); | 34006 | goto invalid_tag; |
| 33243 | uint32_t flags; | 34007 | if (JS_WriteFunctionTag(s, obj)) |
| 33244 | int idx, i; | 34008 | goto fail; |
| 33245 | | | |
| 33246 | if (!s->allow_bytecode) | | |
| 33247 | goto invalid_tag; | | |
| 33248 | bc_put_u8(s, BC_TAG_FUNCTION_BYTECODE); | | |
| 33249 | flags = idx = 0; | | |
| 33250 | bc_set_flags(&flags, &idx, b->has_prototype, 1); | | |
| 33251 | bc_set_flags(&flags, &idx, b->has_simple_parameter_list, 1); | | |
| 33252 | bc_set_flags(&flags, &idx, b->is_derived_class_constructor, 1); | | |
| 33253 | bc_set_flags(&flags, &idx, b->need_home_object, 1); | | |
| 33254 | bc_set_flags(&flags, &idx, b->func_kind, 2); | | |
| 33255 | bc_set_flags(&flags, &idx, b->new_target_allowed, 1); | | |
| 33256 | bc_set_flags(&flags, &idx, b->super_call_allowed, 1); | | |
| 33257 | bc_set_flags(&flags, &idx, b->super_allowed, 1); | | |
| 33258 | bc_set_flags(&flags, &idx, b->arguments_allowed, 1); | | |
| 33259 | bc_set_flags(&flags, &idx, b->has_debug, 1); | | |
| 33260 | bc_set_flags(&flags, &idx, b->backtrace_barrier, 1); | | |
| 33261 | assert(idx <= 16); | | |
| 33262 | bc_put_u16(s, flags); | | |
| 33263 | bc_put_u8(s, b->js_mode); | | |
| 33264 | bc_put_atom(s, b->func_name); | | |
| 33265 | | | |
| 33266 | bc_put_leb128(s, b->arg_count); | | |
| 33267 | bc_put_leb128(s, b->var_count); | | |
| 33268 | bc_put_leb128(s, b->defined_arg_count); | | |
| 33269 | bc_put_leb128(s, b->stack_size); | | |
| 33270 | bc_put_leb128(s, b->closure_var_count); | | |
| 33271 | bc_put_leb128(s, b->cpool_count); | | |
| 33272 | bc_put_leb128(s, b->byte_code_len); | | |
| 33273 | if (b->vardefs) { | | |
| 33274 | bc_put_leb128(s, b->arg_count + b->var_count); | | |
| 33275 | for(i = 0; i < b->arg_count + b->var_count; i++) { | | |
| 33276 | JSVarDef *vd = &b->vardefs[i]; | | |
| 33277 | bc_put_atom(s, vd->var_name); | | |
| 33278 | bc_put_leb128(s, vd->scope_level); | | |
| 33279 | bc_put_leb128(s, vd->scope_next + 1); | | |
| 33280 | flags = idx = 0; | | |
| 33281 | bc_set_flags(&flags, &idx, vd->var_kind, 4); | | |
| 33282 | bc_set_flags(&flags, &idx, vd->is_func_var, 1); | | |
| 33283 | bc_set_flags(&flags, &idx, vd->is_const, 1); | | |
| 33284 | bc_set_flags(&flags, &idx, vd->is_lexical, 1); | | |
| 33285 | bc_set_flags(&flags, &idx, vd->is_captured, 1); | | |
| 33286 | assert(idx <= 8); | | |
| 33287 | bc_put_u8(s, flags); | | |
| 33288 | } | | |
| 33289 | } else { | | |
| 33290 | bc_put_leb128(s, 0); | | |
| 33291 | } | | |
| 33292 | | | |
| 33293 | for(i = 0; i < b->closure_var_count; i++) { | | |
| 33294 | JSClosureVar *cv = &b->closure_var[i]; | | |
| 33295 | bc_put_atom(s, cv->var_name); | | |
| 33296 | bc_put_leb128(s, cv->var_idx); | | |
| 33297 | flags = idx = 0; | | |
| 33298 | bc_set_flags(&flags, &idx, cv->is_local, 1); | | |
| 33299 | bc_set_flags(&flags, &idx, cv->is_arg, 1); | | |
| 33300 | bc_set_flags(&flags, &idx, cv->is_const, 1); | | |
| 33301 | bc_set_flags(&flags, &idx, cv->is_lexical, 1); | | |
| 33302 | bc_set_flags(&flags, &idx, cv->var_kind, 4); | | |
| 33303 | assert(idx <= 8); | | |
| 33304 | bc_put_u8(s, flags); | | |
| 33305 | } | | |
| 33306 | | | |
| 33307 | if (JS_WriteFunctionBytecode(s, b->byte_code_buf, b->byte_code_len)) | | |
| 33308 | goto fail; | | |
| 33309 | | | |
| 33310 | if (b->has_debug) { | | |
| 33311 | bc_put_atom(s, b->debug.filename); | | |
| 33312 | bc_put_leb128(s, b->debug.line_num); | | |
| 33313 | bc_put_leb128(s, b->debug.pc2line_len); | | |
| 33314 | dbuf_put(&s->dbuf, b->debug.pc2line_buf, b->debug.pc2line_len); | | |
| 33315 | } | | |
| 33316 | | | |
| 33317 | for(i = 0; i < b->cpool_count; i++) { | | |
| 33318 | if (JS_WriteObjectRec(s, b->cpool[i])) | | |
| 33319 | goto fail; | | |
| 33320 | } | | |
| 33321 | } | | |
| 33322 | break; | 34009 | break; |
| 33323 | case JS_TAG_MODULE: | 34010 | case JS_TAG_MODULE: |
| 33324 | { | 34011 | if (!s->allow_bytecode) |
| 33325 | JSModuleDef *m = JS_VALUE_GET_PTR(obj); | 34012 | goto invalid_tag; |
| 33326 | int i; | 34013 | if (JS_WriteModule(s, obj)) |
| 33327 | | 34014 | goto fail; |
| 33328 | if (!s->allow_bytecode) | | |
| 33329 | goto invalid_tag; | | |
| 33330 | bc_put_u8(s, BC_TAG_MODULE); | | |
| 33331 | bc_put_atom(s, m->module_name); | | |
| 33332 | | | |
| 33333 | bc_put_leb128(s, m->req_module_entries_count); | | |
| 33334 | for(i = 0; i < m->req_module_entries_count; i++) { | | |
| 33335 | JSReqModuleEntry *rme = &m->req_module_entries[i]; | | |
| 33336 | bc_put_atom(s, rme->module_name); | | |
| 33337 | } | | |
| 33338 | | | |
| 33339 | bc_put_leb128(s, m->export_entries_count); | | |
| 33340 | for(i = 0; i < m->export_entries_count; i++) { | | |
| 33341 | JSExportEntry *me = &m->export_entries[i]; | | |
| 33342 | bc_put_u8(s, me->export_type); | | |
| 33343 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { | | |
| 33344 | bc_put_leb128(s, me->u.local.var_idx); | | |
| 33345 | } else { | | |
| 33346 | bc_put_leb128(s, me->u.req_module_idx); | | |
| 33347 | bc_put_atom(s, me->local_name); | | |
| 33348 | } | | |
| 33349 | bc_put_atom(s, me->export_name); | | |
| 33350 | } | | |
| 33351 | | | |
| 33352 | bc_put_leb128(s, m->star_export_entries_count); | | |
| 33353 | for(i = 0; i < m->star_export_entries_count; i++) { | | |
| 33354 | JSStarExportEntry *se = &m->star_export_entries[i]; | | |
| 33355 | bc_put_leb128(s, se->req_module_idx); | | |
| 33356 | } | | |
| 33357 | | | |
| 33358 | bc_put_leb128(s, m->import_entries_count); | | |
| 33359 | for(i = 0; i < m->import_entries_count; i++) { | | |
| 33360 | JSImportEntry *mi = &m->import_entries[i]; | | |
| 33361 | bc_put_leb128(s, mi->var_idx); | | |
| 33362 | bc_put_atom(s, mi->import_name); | | |
| 33363 | bc_put_leb128(s, mi->req_module_idx); | | |
| 33364 | } | | |
| 33365 | | | |
| 33366 | if (JS_WriteObjectRec(s, m->func_obj)) | | |
| 33367 | goto fail; | | |
| 33368 | } | | |
| 33369 | break; | 34015 | break; |
| 33370 | case JS_TAG_OBJECT: | 34016 | case JS_TAG_OBJECT: |
| 33371 | { | 34017 | { |
| 33372 | JSObject *p = JS_VALUE_GET_OBJ(obj); | 34018 | JSObject *p = JS_VALUE_GET_OBJ(obj); |
| 33373 | uint32_t i, prop_count, len; | 34019 | int ret, idx; |
| 33374 | JSShape *sh; | 34020 | |
| 33375 | JSShapeProperty *pr; | 34021 | if (s->allow_reference) { |
| 33376 | JSValue val; | 34022 | idx = js_object_list_find(s->ctx, &s->object_list, p); |
| 33377 | int ret, pass; | 34023 | if (idx >= 0) { |
| 33378 | BOOL is_template; | 34024 | bc_put_u8(s, BC_TAG_OBJECT_REFERENCE); |
| 33379 | JSAtom atom; | 34025 | bc_put_leb128(s, idx); |
| 33380 | | 34026 | break; |
| 33381 | if (p->class_id != JS_CLASS_ARRAY && | | |
| 33382 | p->class_id != JS_CLASS_OBJECT) { | | |
| 33383 | JS_ThrowTypeError(s->ctx, "unsupported object class"); | | |
| 33384 | goto fail; | | |
| 33385 | } | | |
| 33386 | if (p->tmp_mark) { | | |
| 33387 | JS_ThrowTypeError(s->ctx, "circular reference"); | | |
| 33388 | goto fail; | | |
| 33389 | } | | |
| 33390 | p->tmp_mark = 1; | | |
| 33391 | if (p->class_id == JS_CLASS_ARRAY) { | | |
| 33392 | if (s->allow_bytecode && !p->extensible) { | | |
| 33393 | /* not extensible array: we consider it is a | | |
| 33394 | template when we are saving bytecode */ | | |
| 33395 | bc_put_u8(s, BC_TAG_TEMPLATE_OBJECT); | | |
| 33396 | is_template = TRUE; | | |
| 33397 | } else { | 34027 | } else { |
| 33398 | bc_put_u8(s, BC_TAG_ARRAY); | 34028 | if (js_object_list_add(s->ctx, &s->object_list, p)) |
| 33399 | is_template = FALSE; | 34029 | goto fail; |
| 33400 | } | | |
| 33401 | if (js_get_length32(s->ctx, &len, obj)) | | |
| 33402 | goto fail1; | | |
| 33403 | bc_put_leb128(s, len); | | |
| 33404 | for(i = 0; i < len; i++) { | | |
| 33405 | val = JS_GetPropertyUint32(s->ctx, obj, i); | | |
| 33406 | if (JS_IsException(val)) | | |
| 33407 | goto fail1; | | |
| 33408 | ret = JS_WriteObjectRec(s, val); | | |
| 33409 | JS_FreeValue(s->ctx, val); | | |
| 33410 | if (ret) | | |
| 33411 | goto fail1; | | |
| 33412 | } | | |
| 33413 | if (is_template) { | | |
| 33414 | val = JS_GetProperty(s->ctx, obj, JS_ATOM_raw); | | |
| 33415 | if (JS_IsException(val)) | | |
| 33416 | goto fail1; | | |
| 33417 | ret = JS_WriteObjectRec(s, val); | | |
| 33418 | JS_FreeValue(s->ctx, val); | | |
| 33419 | if (ret) | | |
| 33420 | goto fail1; | | |
| 33421 | } | 34030 | } |
| 33422 | } else { | 34031 | } else { |
| 33423 | bc_put_u8(s, BC_TAG_OBJECT); | 34032 | if (p->tmp_mark) { |
| 33424 | prop_count = 0; | 34033 | JS_ThrowTypeError(s->ctx, "circular reference"); |
| 33425 | sh = p->shape; | 34034 | goto fail; |
| 33426 | for(pass = 0; pass < 2; pass++) { | 34035 | } |
| 33427 | if (pass == 1) | 34036 | p->tmp_mark = 1; |
| 33428 | bc_put_leb128(s, prop_count); | 34037 | } |
| 33429 | for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { | 34038 | switch(p->class_id) { |
| 33430 | atom = pr->atom; | 34039 | case JS_CLASS_ARRAY: |
| 33431 | if (atom != JS_ATOM_NULL && | 34040 | ret = JS_WriteArray(s, obj); |
| 33432 | JS_AtomIsString(s->ctx, atom) && | 34041 | break; |
| 33433 | (pr->flags & JS_PROP_ENUMERABLE)) { | 34042 | case JS_CLASS_OBJECT: |
| 33434 | if (pr->flags & JS_PROP_TMASK) { | 34043 | ret = JS_WriteObjectTag(s, obj); |
| 33435 | JS_ThrowTypeError(s->ctx, "only value properties are supported"); | 34044 | break; |
| 33436 | goto fail; | 34045 | case JS_CLASS_ARRAY_BUFFER: |
| 33437 | } | 34046 | ret = JS_WriteArrayBuffer(s, obj); |
| 33438 | if (pass == 0) { | 34047 | break; |
| 33439 | prop_count++; | 34048 | case JS_CLASS_SHARED_ARRAY_BUFFER: |
| 33440 | } else { | 34049 | if (!s->allow_sab) |
| 33441 | bc_put_atom(s, atom); | 34050 | goto invalid_tag; |
| 33442 | if (JS_WriteObjectRec(s, p->prop[i].u.value)) { | 34051 | ret = JS_WriteSharedArrayBuffer(s, obj); |
| 33443 | fail1: | 34052 | break; |
| 33444 | p->tmp_mark = 0; | 34053 | case JS_CLASS_DATE: |
| 33445 | goto fail; | 34054 | bc_put_u8(s, BC_TAG_DATE); |
| 33446 | } | 34055 | ret = JS_WriteObjectRec(s, p->u.object_data); |
| 33447 | } | 34056 | break; |
| 33448 | } | 34057 | case JS_CLASS_NUMBER: |
| 33449 | } | 34058 | case JS_CLASS_STRING: |
| | 34059 | case JS_CLASS_BOOLEAN: |
| | 34060 | #ifdef CONFIG_BIGNUM |
| | 34061 | case JS_CLASS_BIG_INT: |
| | 34062 | case JS_CLASS_BIG_FLOAT: |
| | 34063 | case JS_CLASS_BIG_DECIMAL: |
| | 34064 | #endif |
| | 34065 | bc_put_u8(s, BC_TAG_OBJECT_VALUE); |
| | 34066 | ret = JS_WriteObjectRec(s, p->u.object_data); |
| | 34067 | break; |
| | 34068 | default: |
| | 34069 | if (p->class_id >= JS_CLASS_UINT8C_ARRAY && |
| | 34070 | p->class_id <= JS_CLASS_FLOAT64_ARRAY) { |
| | 34071 | ret = JS_WriteTypedArray(s, obj); |
| | 34072 | } else { |
| | 34073 | JS_ThrowTypeError(s->ctx, "unsupported object class"); |
| | 34074 | ret = -1; |
| 33450 | } | 34075 | } |
| | 34076 | break; |
| 33451 | } | 34077 | } |
| 33452 | p->tmp_mark = 0; | 34078 | p->tmp_mark = 0; |
| | 34079 | if (ret) |
| | 34080 | goto fail; |
| 33453 | } | 34081 | } |
| 33454 | break; | 34082 | break; |
| 33455 | #ifdef CONFIG_BIGNUM | 34083 | #ifdef CONFIG_BIGNUM |
| @@ -33511,8 +34139,8 @@ static int JS_WriteObjectAtoms(BCWriterState *s) · 55 unmodified lines |
| 33511 | return -1; | 34139 | return -1; |
| 33512 | } | 34140 | } |
| 33513 | | 34141 | |
| 33514 | uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, | 34142 | uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj, |
| 33515 | int flags) | 34143 | int flags, uint8_t ***psab_tab, size_t *psab_tab_len) |
| 33516 | { | 34144 | { |
| 33517 | BCWriterState ss, *s = &ss; | 34145 | BCWriterState ss, *s = &ss; |
| 33518 | | 34146 | |
| @@ -33521,29 +34149,48 @@ uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, · 2 unmodified lines |
| 33521 | /* XXX: byte swapped output is untested */ | 34149 | /* XXX: byte swapped output is untested */ |
| 33522 | s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0); | 34150 | s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0); |
| 33523 | s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0); | 34151 | s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0); |
| | 34152 | s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0); |
| | 34153 | s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0); |
| 33524 | /* XXX: could use a different version when bytecode is included */ | 34154 | /* XXX: could use a different version when bytecode is included */ |
| 33525 | if (s->allow_bytecode) | 34155 | if (s->allow_bytecode) |
| 33526 | s->first_atom = JS_ATOM_END; | 34156 | s->first_atom = JS_ATOM_END; |
| 33527 | else | 34157 | else |
| 33528 | s->first_atom = 1; | 34158 | s->first_atom = 1; |
| 33529 | js_dbuf_init(ctx, &s->dbuf); | 34159 | js_dbuf_init(ctx, &s->dbuf); |
| 33530 | | 34160 | js_object_list_init(&s->object_list); |
| | 34161 | |
| 33531 | if (JS_WriteObjectRec(s, obj)) | 34162 | if (JS_WriteObjectRec(s, obj)) |
| 33532 | goto fail; | 34163 | goto fail; |
| 33533 | if (JS_WriteObjectAtoms(s)) | 34164 | if (JS_WriteObjectAtoms(s)) |
| 33534 | goto fail; | 34165 | goto fail; |
| | 34166 | js_object_list_end(ctx, &s->object_list); |
| 33535 | js_free(ctx, s->atom_to_idx); | 34167 | js_free(ctx, s->atom_to_idx); |
| 33536 | js_free(ctx, s->idx_to_atom); | 34168 | js_free(ctx, s->idx_to_atom); |
| 33537 | *psize = s->dbuf.size; | 34169 | *psize = s->dbuf.size; |
| | 34170 | if (psab_tab) |
| | 34171 | *psab_tab = s->sab_tab; |
| | 34172 | if (psab_tab_len) |
| | 34173 | *psab_tab_len = s->sab_tab_len; |
| 33538 | return s->dbuf.buf; | 34174 | return s->dbuf.buf; |
| 33539 | fail: | 34175 | fail: |
| | 34176 | js_object_list_end(ctx, &s->object_list); |
| 33540 | js_free(ctx, s->atom_to_idx); | 34177 | js_free(ctx, s->atom_to_idx); |
| 33541 | js_free(ctx, s->idx_to_atom); | 34178 | js_free(ctx, s->idx_to_atom); |
| 33542 | dbuf_free(&s->dbuf); | 34179 | dbuf_free(&s->dbuf); |
| 33543 | *psize = 0; | 34180 | *psize = 0; |
| | 34181 | if (psab_tab) |
| | 34182 | *psab_tab = NULL; |
| | 34183 | if (psab_tab_len) |
| | 34184 | *psab_tab_len = 0; |
| 33544 | return NULL; | 34185 | return NULL; |
| 33545 | } | 34186 | } |
| 33546 | | 34187 | |
| | 34188 | uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj, |
| | 34189 | int flags) |
| | 34190 | { |
| | 34191 | return JS_WriteObject2(ctx, psize, obj, flags, NULL, NULL); |
| | 34192 | } |
| | 34193 | |
| 33547 | typedef struct BCReaderState { | 34194 | typedef struct BCReaderState { |
| 33548 | JSContext *ctx; | 34195 | JSContext *ctx; |
| 33549 | const uint8_t *buf_start, *ptr, *buf_end; | 34196 | const uint8_t *buf_start, *ptr, *buf_end; |
| @@ -33551,8 +34198,15 @@ typedef struct BCReaderState { · 1 unmodified line |
| 33551 | uint32_t idx_to_atom_count; | 34198 | uint32_t idx_to_atom_count; |
| 33552 | JSAtom *idx_to_atom; | 34199 | JSAtom *idx_to_atom; |
| 33553 | int error_state; | 34200 | int error_state; |
| 33554 | BOOL allow_bytecode; | 34201 | BOOL allow_sab : 8; |
| 33555 | BOOL is_rom_data; | 34202 | BOOL allow_bytecode : 8; |
| | 34203 | BOOL is_rom_data : 8; |
| | 34204 | BOOL allow_reference : 8; |
| | 34205 | /* object references */ |
| | 34206 | JSObject **objects; |
| | 34207 | int objects_count; |
| | 34208 | int objects_size; |
| | 34209 | |
| 33556 | #ifdef DUMP_READ_OBJECT | 34210 | #ifdef DUMP_READ_OBJECT |
| 33557 | const uint8_t *ptr_last; | 34211 | const uint8_t *ptr_last; |
| 33558 | int level; | 34212 | int level; |
| @@ -33756,7 +34410,7 @@ static JSString *JS_ReadString(BCReaderState *s) · 197 unmodified lines |
| 33756 | p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */ | 34410 | p->u.str8[size] = '\0'; /* add the trailing zero for 8 bit strings */ |
| 33757 | } | 34411 | } |
| 33758 | #ifdef DUMP_READ_OBJECT | 34412 | #ifdef DUMP_READ_OBJECT |
| 33759 | bc_read_trace(s, "string: "); JS_DumpString(s->ctx->rt, p); printf("\n"); | 34413 | JS_DumpString(s->ctx->rt, p); printf("\n"); |
| 33760 | #endif | 34414 | #endif |
| 33761 | return p; | 34415 | return p; |
| 33762 | } | 34416 | } |
| @@ -33838,8 +34492,6 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) · 75 unmodified lines |
| 33838 | bf_t *a; | 34492 | bf_t *a; |
| 33839 | int bpos, d; | 34493 | int bpos, d; |
| 33840 | | 34494 | |
| 33841 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); | | |
| 33842 | | | |
| 33843 | p = js_new_bf(s->ctx); | 34495 | p = js_new_bf(s->ctx); |
| 33844 | if (!p) | 34496 | if (!p) |
| 33845 | goto fail; | 34497 | goto fail; |
| @@ -33961,28 +34613,560 @@ static JSValue JS_ReadBigNum(BCReaderState *s, int tag) · 115 unmodified lines |
| 33961 | } | 34613 | } |
| 33962 | #endif /* CONFIG_BIGNUM */ | 34614 | #endif /* CONFIG_BIGNUM */ |
| 33963 | | 34615 | |
| | 34616 | static JSValue JS_ReadObjectRec(BCReaderState *s); |
| | 34617 | |
| | 34618 | static int BC_add_object_ref1(BCReaderState *s, JSObject *p) |
| | 34619 | { |
| | 34620 | if (s->allow_reference) { |
| | 34621 | if (js_resize_array(s->ctx, (void *)&s->objects, |
| | 34622 | sizeof(s->objects[0]), |
| | 34623 | &s->objects_size, s->objects_count + 1)) |
| | 34624 | return -1; |
| | 34625 | s->objects[s->objects_count++] = p; |
| | 34626 | } |
| | 34627 | return 0; |
| | 34628 | } |
| | 34629 | |
| | 34630 | static int BC_add_object_ref(BCReaderState *s, JSValueConst obj) |
| | 34631 | { |
| | 34632 | return BC_add_object_ref1(s, JS_VALUE_GET_OBJ(obj)); |
| | 34633 | } |
| | 34634 | |
| | 34635 | static JSValue JS_ReadFunctionTag(BCReaderState *s) |
| | 34636 | { |
| | 34637 | JSContext *ctx = s->ctx; |
| | 34638 | JSFunctionBytecode bc, *b; |
| | 34639 | JSValue obj = JS_UNDEFINED; |
| | 34640 | uint16_t v16; |
| | 34641 | uint8_t v8; |
| | 34642 | int idx, i, local_count; |
| | 34643 | int function_size, cpool_offset, byte_code_offset; |
| | 34644 | int closure_var_offset, vardefs_offset; |
| | 34645 | |
| | 34646 | memset(&bc, 0, sizeof(bc)); |
| | 34647 | bc.header.ref_count = 1; |
| | 34648 | //bc.gc_header.mark = 0; |
| | 34649 | |
| | 34650 | if (bc_get_u16(s, &v16)) |
| | 34651 | goto fail; |
| | 34652 | idx = 0; |
| | 34653 | bc.has_prototype = bc_get_flags(v16, &idx, 1); |
| | 34654 | bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1); |
| | 34655 | bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1); |
| | 34656 | bc.need_home_object = bc_get_flags(v16, &idx, 1); |
| | 34657 | bc.func_kind = bc_get_flags(v16, &idx, 2); |
| | 34658 | bc.new_target_allowed = bc_get_flags(v16, &idx, 1); |
| | 34659 | bc.super_call_allowed = bc_get_flags(v16, &idx, 1); |
| | 34660 | bc.super_allowed = bc_get_flags(v16, &idx, 1); |
| | 34661 | bc.arguments_allowed = bc_get_flags(v16, &idx, 1); |
| | 34662 | bc.has_debug = bc_get_flags(v16, &idx, 1); |
| | 34663 | bc.backtrace_barrier = bc_get_flags(v16, &idx, 1); |
| | 34664 | bc.read_only_bytecode = s->is_rom_data; |
| | 34665 | if (bc_get_u8(s, &v8)) |
| | 34666 | goto fail; |
| | 34667 | bc.js_mode = v8; |
| | 34668 | if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure |
| | 34669 | goto fail; |
| | 34670 | if (bc_get_leb128_u16(s, &bc.arg_count)) |
| | 34671 | goto fail; |
| | 34672 | if (bc_get_leb128_u16(s, &bc.var_count)) |
| | 34673 | goto fail; |
| | 34674 | if (bc_get_leb128_u16(s, &bc.defined_arg_count)) |
| | 34675 | goto fail; |
| | 34676 | if (bc_get_leb128_u16(s, &bc.stack_size)) |
| | 34677 | goto fail; |
| | 34678 | if (bc_get_leb128_int(s, &bc.closure_var_count)) |
| | 34679 | goto fail; |
| | 34680 | if (bc_get_leb128_int(s, &bc.cpool_count)) |
| | 34681 | goto fail; |
| | 34682 | if (bc_get_leb128_int(s, &bc.byte_code_len)) |
| | 34683 | goto fail; |
| | 34684 | if (bc_get_leb128_int(s, &local_count)) |
| | 34685 | goto fail; |
| | 34686 | |
| | 34687 | if (bc.has_debug) { |
| | 34688 | function_size = sizeof(*b); |
| | 34689 | } else { |
| | 34690 | function_size = offsetof(JSFunctionBytecode, debug); |
| | 34691 | } |
| | 34692 | cpool_offset = function_size; |
| | 34693 | function_size += bc.cpool_count * sizeof(*bc.cpool); |
| | 34694 | vardefs_offset = function_size; |
| | 34695 | function_size += local_count * sizeof(*bc.vardefs); |
| | 34696 | closure_var_offset = function_size; |
| | 34697 | function_size += bc.closure_var_count * sizeof(*bc.closure_var); |
| | 34698 | byte_code_offset = function_size; |
| | 34699 | if (!bc.read_only_bytecode) { |
| | 34700 | function_size += bc.byte_code_len; |
| | 34701 | } |
| | 34702 | |
| | 34703 | b = js_mallocz(ctx, function_size); |
| | 34704 | if (!b) |
| | 34705 | return JS_EXCEPTION; |
| | 34706 | |
| | 34707 | memcpy(b, &bc, offsetof(JSFunctionBytecode, debug)); |
| | 34708 | b->header.ref_count = 1; |
| | 34709 | add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); |
| | 34710 | |
| | 34711 | obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b); |
| | 34712 | |
| | 34713 | #ifdef DUMP_READ_OBJECT |
| | 34714 | bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n"); |
| | 34715 | #endif |
| | 34716 | bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n", |
| | 34717 | b->arg_count, b->var_count, b->defined_arg_count, |
| | 34718 | b->closure_var_count, b->cpool_count); |
| | 34719 | bc_read_trace(s, "stack=%d bclen=%d locals=%d\n", |
| | 34720 | b->stack_size, b->byte_code_len, local_count); |
| | 34721 | |
| | 34722 | if (local_count != 0) { |
| | 34723 | bc_read_trace(s, "vars {\n"); |
| | 34724 | b->vardefs = (void *)((uint8_t*)b + vardefs_offset); |
| | 34725 | for(i = 0; i < local_count; i++) { |
| | 34726 | JSVarDef *vd = &b->vardefs[i]; |
| | 34727 | if (bc_get_atom(s, &vd->var_name)) |
| | 34728 | goto fail; |
| | 34729 | if (bc_get_leb128_int(s, &vd->scope_level)) |
| | 34730 | goto fail; |
| | 34731 | if (bc_get_leb128_int(s, &vd->scope_next)) |
| | 34732 | goto fail; |
| | 34733 | vd->scope_next--; |
| | 34734 | if (bc_get_u8(s, &v8)) |
| | 34735 | goto fail; |
| | 34736 | idx = 0; |
| | 34737 | vd->var_kind = bc_get_flags(v8, &idx, 4); |
| | 34738 | vd->is_func_var = bc_get_flags(v8, &idx, 1); |
| | 34739 | vd->is_const = bc_get_flags(v8, &idx, 1); |
| | 34740 | vd->is_lexical = bc_get_flags(v8, &idx, 1); |
| | 34741 | vd->is_captured = bc_get_flags(v8, &idx, 1); |
| | 34742 | #ifdef DUMP_READ_OBJECT |
| | 34743 | bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n"); |
| | 34744 | #endif |
| | 34745 | } |
| | 34746 | bc_read_trace(s, "}\n"); |
| | 34747 | } |
| | 34748 | if (b->closure_var_count != 0) { |
| | 34749 | bc_read_trace(s, "closure vars {\n"); |
| | 34750 | b->closure_var = (void *)((uint8_t*)b + closure_var_offset); |
| | 34751 | for(i = 0; i < b->closure_var_count; i++) { |
| | 34752 | JSClosureVar *cv = &b->closure_var[i]; |
| | 34753 | int var_idx; |
| | 34754 | if (bc_get_atom(s, &cv->var_name)) |
| | 34755 | goto fail; |
| | 34756 | if (bc_get_leb128_int(s, &var_idx)) |
| | 34757 | goto fail; |
| | 34758 | cv->var_idx = var_idx; |
| | 34759 | if (bc_get_u8(s, &v8)) |
| | 34760 | goto fail; |
| | 34761 | idx = 0; |
| | 34762 | cv->is_local = bc_get_flags(v8, &idx, 1); |
| | 34763 | cv->is_arg = bc_get_flags(v8, &idx, 1); |
| | 34764 | cv->is_const = bc_get_flags(v8, &idx, 1); |
| | 34765 | cv->is_lexical = bc_get_flags(v8, &idx, 1); |
| | 34766 | cv->var_kind = bc_get_flags(v8, &idx, 4); |
| | 34767 | #ifdef DUMP_READ_OBJECT |
| | 34768 | bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); |
| | 34769 | #endif |
| | 34770 | } |
| | 34771 | bc_read_trace(s, "}\n"); |
| | 34772 | } |
| | 34773 | { |
| | 34774 | bc_read_trace(s, "bytecode {\n"); |
| | 34775 | if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len)) |
| | 34776 | goto fail; |
| | 34777 | bc_read_trace(s, "}\n"); |
| | 34778 | } |
| | 34779 | if (b->has_debug) { |
| | 34780 | /* read optional debug information */ |
| | 34781 | bc_read_trace(s, "debug {\n"); |
| | 34782 | if (bc_get_atom(s, &b->debug.filename)) |
| | 34783 | goto fail; |
| | 34784 | if (bc_get_leb128_int(s, &b->debug.line_num)) |
| | 34785 | goto fail; |
| | 34786 | if (bc_get_leb128_int(s, &b->debug.pc2line_len)) |
| | 34787 | goto fail; |
| | 34788 | if (b->debug.pc2line_len) { |
| | 34789 | b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len); |
| | 34790 | if (!b->debug.pc2line_buf) |
| | 34791 | goto fail; |
| | 34792 | if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len)) |
| | 34793 | goto fail; |
| | 34794 | } |
| | 34795 | #ifdef DUMP_READ_OBJECT |
| | 34796 | bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n"); |
| | 34797 | #endif |
| | 34798 | bc_read_trace(s, "}\n"); |
| | 34799 | } |
| | 34800 | if (b->cpool_count != 0) { |
| | 34801 | bc_read_trace(s, "cpool {\n"); |
| | 34802 | b->cpool = (void *)((uint8_t*)b + cpool_offset); |
| | 34803 | for(i = 0; i < b->cpool_count; i++) { |
| | 34804 | JSValue val; |
| | 34805 | val = JS_ReadObjectRec(s); |
| | 34806 | if (JS_IsException(val)) |
| | 34807 | goto fail; |
| | 34808 | b->cpool[i] = val; |
| | 34809 | } |
| | 34810 | bc_read_trace(s, "}\n"); |
| | 34811 | } |
| | 34812 | b->realm = JS_DupContext(ctx); |
| | 34813 | return obj; |
| | 34814 | fail: |
| | 34815 | JS_FreeValue(ctx, obj); |
| | 34816 | return JS_EXCEPTION; |
| | 34817 | } |
| | 34818 | |
| | 34819 | static JSValue JS_ReadModule(BCReaderState *s) |
| | 34820 | { |
| | 34821 | JSContext *ctx = s->ctx; |
| | 34822 | JSValue obj; |
| | 34823 | JSModuleDef *m = NULL; |
| | 34824 | JSAtom module_name; |
| | 34825 | int i; |
| | 34826 | uint8_t v8; |
| | 34827 | |
| | 34828 | if (bc_get_atom(s, &module_name)) |
| | 34829 | goto fail; |
| | 34830 | #ifdef DUMP_READ_OBJECT |
| | 34831 | bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n"); |
| | 34832 | #endif |
| | 34833 | m = js_new_module_def(ctx, module_name); |
| | 34834 | if (!m) |
| | 34835 | goto fail; |
| | 34836 | obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); |
| | 34837 | if (bc_get_leb128_int(s, &m->req_module_entries_count)) |
| | 34838 | goto fail; |
| | 34839 | if (m->req_module_entries_count != 0) { |
| | 34840 | m->req_module_entries_size = m->req_module_entries_count; |
| | 34841 | m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size); |
| | 34842 | if (!m->req_module_entries) |
| | 34843 | goto fail; |
| | 34844 | for(i = 0; i < m->req_module_entries_count; i++) { |
| | 34845 | JSReqModuleEntry *rme = &m->req_module_entries[i]; |
| | 34846 | if (bc_get_atom(s, &rme->module_name)) |
| | 34847 | goto fail; |
| | 34848 | } |
| | 34849 | } |
| | 34850 | |
| | 34851 | if (bc_get_leb128_int(s, &m->export_entries_count)) |
| | 34852 | goto fail; |
| | 34853 | if (m->export_entries_count != 0) { |
| | 34854 | m->export_entries_size = m->export_entries_count; |
| | 34855 | m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size); |
| | 34856 | if (!m->export_entries) |
| | 34857 | goto fail; |
| | 34858 | for(i = 0; i < m->export_entries_count; i++) { |
| | 34859 | JSExportEntry *me = &m->export_entries[i]; |
| | 34860 | if (bc_get_u8(s, &v8)) |
| | 34861 | goto fail; |
| | 34862 | me->export_type = v8; |
| | 34863 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { |
| | 34864 | if (bc_get_leb128_int(s, &me->u.local.var_idx)) |
| | 34865 | goto fail; |
| | 34866 | } else { |
| | 34867 | if (bc_get_leb128_int(s, &me->u.req_module_idx)) |
| | 34868 | goto fail; |
| | 34869 | if (bc_get_atom(s, &me->local_name)) |
| | 34870 | goto fail; |
| | 34871 | } |
| | 34872 | if (bc_get_atom(s, &me->export_name)) |
| | 34873 | goto fail; |
| | 34874 | } |
| | 34875 | } |
| | 34876 | |
| | 34877 | if (bc_get_leb128_int(s, &m->star_export_entries_count)) |
| | 34878 | goto fail; |
| | 34879 | if (m->star_export_entries_count != 0) { |
| | 34880 | m->star_export_entries_size = m->star_export_entries_count; |
| | 34881 | m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size); |
| | 34882 | if (!m->star_export_entries) |
| | 34883 | goto fail; |
| | 34884 | for(i = 0; i < m->star_export_entries_count; i++) { |
| | 34885 | JSStarExportEntry *se = &m->star_export_entries[i]; |
| | 34886 | if (bc_get_leb128_int(s, &se->req_module_idx)) |
| | 34887 | goto fail; |
| | 34888 | } |
| | 34889 | } |
| | 34890 | |
| | 34891 | if (bc_get_leb128_int(s, &m->import_entries_count)) |
| | 34892 | goto fail; |
| | 34893 | if (m->import_entries_count != 0) { |
| | 34894 | m->import_entries_size = m->import_entries_count; |
| | 34895 | m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size); |
| | 34896 | if (!m->import_entries) |
| | 34897 | goto fail; |
| | 34898 | for(i = 0; i < m->import_entries_count; i++) { |
| | 34899 | JSImportEntry *mi = &m->import_entries[i]; |
| | 34900 | if (bc_get_leb128_int(s, &mi->var_idx)) |
| | 34901 | goto fail; |
| | 34902 | if (bc_get_atom(s, &mi->import_name)) |
| | 34903 | goto fail; |
| | 34904 | if (bc_get_leb128_int(s, &mi->req_module_idx)) |
| | 34905 | goto fail; |
| | 34906 | } |
| | 34907 | } |
| | 34908 | |
| | 34909 | m->func_obj = JS_ReadObjectRec(s); |
| | 34910 | if (JS_IsException(m->func_obj)) |
| | 34911 | goto fail; |
| | 34912 | return obj; |
| | 34913 | fail: |
| | 34914 | if (m) { |
| | 34915 | js_free_module_def(ctx, m); |
| | 34916 | } |
| | 34917 | return JS_EXCEPTION; |
| | 34918 | } |
| | 34919 | |
| | 34920 | static JSValue JS_ReadObjectTag(BCReaderState *s) |
| | 34921 | { |
| | 34922 | JSContext *ctx = s->ctx; |
| | 34923 | JSValue obj; |
| | 34924 | uint32_t prop_count, i; |
| | 34925 | JSAtom atom; |
| | 34926 | JSValue val; |
| | 34927 | int ret; |
| | 34928 | |
| | 34929 | obj = JS_NewObject(ctx); |
| | 34930 | if (BC_add_object_ref(s, obj)) |
| | 34931 | goto fail; |
| | 34932 | if (bc_get_leb128(s, &prop_count)) |
| | 34933 | goto fail; |
| | 34934 | for(i = 0; i < prop_count; i++) { |
| | 34935 | if (bc_get_atom(s, &atom)) |
| | 34936 | goto fail; |
| | 34937 | #ifdef DUMP_READ_OBJECT |
| | 34938 | bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n"); |
| | 34939 | #endif |
| | 34940 | val = JS_ReadObjectRec(s); |
| | 34941 | if (JS_IsException(val)) { |
| | 34942 | JS_FreeAtom(ctx, atom); |
| | 34943 | goto fail; |
| | 34944 | } |
| | 34945 | ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E); |
| | 34946 | JS_FreeAtom(ctx, atom); |
| | 34947 | if (ret < 0) |
| | 34948 | goto fail; |
| | 34949 | } |
| | 34950 | return obj; |
| | 34951 | fail: |
| | 34952 | JS_FreeValue(ctx, obj); |
| | 34953 | return JS_EXCEPTION; |
| | 34954 | } |
| | 34955 | |
| | 34956 | static JSValue JS_ReadArray(BCReaderState *s, int tag) |
| | 34957 | { |
| | 34958 | JSContext *ctx = s->ctx; |
| | 34959 | JSValue obj; |
| | 34960 | uint32_t len, i; |
| | 34961 | JSValue val; |
| | 34962 | int ret, prop_flags; |
| | 34963 | BOOL is_template; |
| | 34964 | |
| | 34965 | obj = JS_NewArray(ctx); |
| | 34966 | if (BC_add_object_ref(s, obj)) |
| | 34967 | goto fail; |
| | 34968 | is_template = (tag == BC_TAG_TEMPLATE_OBJECT); |
| | 34969 | if (bc_get_leb128(s, &len)) |
| | 34970 | goto fail; |
| | 34971 | for(i = 0; i < len; i++) { |
| | 34972 | val = JS_ReadObjectRec(s); |
| | 34973 | if (JS_IsException(val)) |
| | 34974 | goto fail; |
| | 34975 | if (is_template) |
| | 34976 | prop_flags = JS_PROP_ENUMERABLE; |
| | 34977 | else |
| | 34978 | prop_flags = JS_PROP_C_W_E; |
| | 34979 | ret = JS_DefinePropertyValueUint32(ctx, obj, i, val, |
| | 34980 | prop_flags); |
| | 34981 | if (ret < 0) |
| | 34982 | goto fail; |
| | 34983 | } |
| | 34984 | if (is_template) { |
| | 34985 | val = JS_ReadObjectRec(s); |
| | 34986 | if (JS_IsException(val)) |
| | 34987 | goto fail; |
| | 34988 | if (!JS_IsUndefined(val)) { |
| | 34989 | ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0); |
| | 34990 | if (ret < 0) |
| | 34991 | goto fail; |
| | 34992 | } |
| | 34993 | JS_PreventExtensions(ctx, obj); |
| | 34994 | } |
| | 34995 | return obj; |
| | 34996 | fail: |
| | 34997 | JS_FreeValue(ctx, obj); |
| | 34998 | return JS_EXCEPTION; |
| | 34999 | } |
| | 35000 | |
| | 35001 | static JSValue JS_ReadTypedArray(BCReaderState *s) |
| | 35002 | { |
| | 35003 | JSContext *ctx = s->ctx; |
| | 35004 | JSValue obj = JS_UNDEFINED, array_buffer = JS_UNDEFINED; |
| | 35005 | uint8_t array_tag; |
| | 35006 | JSValueConst args[3]; |
| | 35007 | uint32_t offset, len, idx; |
| | 35008 | |
| | 35009 | if (bc_get_u8(s, &array_tag)) |
| | 35010 | return JS_EXCEPTION; |
| | 35011 | if (array_tag >= JS_TYPED_ARRAY_COUNT) |
| | 35012 | return JS_ThrowTypeError(ctx, "invalid typed array"); |
| | 35013 | if (bc_get_leb128(s, &len)) |
| | 35014 | return JS_EXCEPTION; |
| | 35015 | if (bc_get_leb128(s, &offset)) |
| | 35016 | return JS_EXCEPTION; |
| | 35017 | /* XXX: this hack could be avoided if the typed array could be |
| | 35018 | created before the array buffer */ |
| | 35019 | idx = s->objects_count; |
| | 35020 | if (BC_add_object_ref1(s, NULL)) |
| | 35021 | goto fail; |
| | 35022 | array_buffer = JS_ReadObjectRec(s); |
| | 35023 | if (JS_IsException(array_buffer)) |
| | 35024 | return JS_EXCEPTION; |
| | 35025 | if (!js_get_array_buffer(ctx, array_buffer)) { |
| | 35026 | JS_FreeValue(ctx, array_buffer); |
| | 35027 | return JS_EXCEPTION; |
| | 35028 | } |
| | 35029 | args[0] = array_buffer; |
| | 35030 | args[1] = JS_NewInt64(ctx, offset); |
| | 35031 | args[2] = JS_NewInt64(ctx, len); |
| | 35032 | obj = js_typed_array_constructor(ctx, JS_UNDEFINED, |
| | 35033 | 3, args, |
| | 35034 | JS_CLASS_UINT8C_ARRAY + array_tag); |
| | 35035 | if (JS_IsException(obj)) |
| | 35036 | goto fail; |
| | 35037 | if (s->allow_reference) { |
| | 35038 | s->objects[idx] = JS_VALUE_GET_OBJ(obj); |
| | 35039 | } |
| | 35040 | JS_FreeValue(ctx, array_buffer); |
| | 35041 | return obj; |
| | 35042 | fail: |
| | 35043 | JS_FreeValue(ctx, array_buffer); |
| | 35044 | JS_FreeValue(ctx, obj); |
| | 35045 | return JS_EXCEPTION; |
| | 35046 | } |
| | 35047 | |
| | 35048 | static JSValue JS_ReadArrayBuffer(BCReaderState *s) |
| | 35049 | { |
| | 35050 | JSContext *ctx = s->ctx; |
| | 35051 | uint32_t byte_length; |
| | 35052 | JSValue obj; |
| | 35053 | |
| | 35054 | if (bc_get_leb128(s, &byte_length)) |
| | 35055 | return JS_EXCEPTION; |
| | 35056 | if (unlikely(s->buf_end - s->ptr < byte_length)) { |
| | 35057 | bc_read_error_end(s); |
| | 35058 | return JS_EXCEPTION; |
| | 35059 | } |
| | 35060 | obj = JS_NewArrayBufferCopy(ctx, s->ptr, byte_length); |
| | 35061 | if (JS_IsException(obj)) |
| | 35062 | goto fail; |
| | 35063 | if (BC_add_object_ref(s, obj)) |
| | 35064 | goto fail; |
| | 35065 | s->ptr += byte_length; |
| | 35066 | return obj; |
| | 35067 | fail: |
| | 35068 | JS_FreeValue(ctx, obj); |
| | 35069 | return JS_EXCEPTION; |
| | 35070 | } |
| | 35071 | |
| | 35072 | static JSValue JS_ReadSharedArrayBuffer(BCReaderState *s) |
| | 35073 | { |
| | 35074 | JSContext *ctx = s->ctx; |
| | 35075 | uint32_t byte_length; |
| | 35076 | uint8_t *data_ptr; |
| | 35077 | JSValue obj; |
| | 35078 | uint64_t u64; |
| | 35079 | |
| | 35080 | if (bc_get_leb128(s, &byte_length)) |
| | 35081 | return JS_EXCEPTION; |
| | 35082 | if (bc_get_u64(s, &u64)) |
| | 35083 | return JS_EXCEPTION; |
| | 35084 | data_ptr = (uint8_t *)(uintptr_t)u64; |
| | 35085 | /* the SharedArrayBuffer is cloned */ |
| | 35086 | obj = js_array_buffer_constructor3(ctx, JS_UNDEFINED, byte_length, |
| | 35087 | JS_CLASS_SHARED_ARRAY_BUFFER, |
| | 35088 | data_ptr, |
| | 35089 | NULL, NULL, FALSE); |
| | 35090 | if (JS_IsException(obj)) |
| | 35091 | goto fail; |
| | 35092 | if (BC_add_object_ref(s, obj)) |
| | 35093 | goto fail; |
| | 35094 | return obj; |
| | 35095 | fail: |
| | 35096 | JS_FreeValue(ctx, obj); |
| | 35097 | return JS_EXCEPTION; |
| | 35098 | } |
| | 35099 | |
| | 35100 | static JSValue JS_ReadDate(BCReaderState *s) |
| | 35101 | { |
| | 35102 | JSContext *ctx = s->ctx; |
| | 35103 | JSValue val, obj = JS_UNDEFINED; |
| | 35104 | |
| | 35105 | val = JS_ReadObjectRec(s); |
| | 35106 | if (JS_IsException(val)) |
| | 35107 | goto fail; |
| | 35108 | if (!JS_IsNumber(val)) { |
| | 35109 | JS_ThrowTypeError(ctx, "Number tag expected for date"); |
| | 35110 | goto fail; |
| | 35111 | } |
| | 35112 | obj = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_DATE], |
| | 35113 | JS_CLASS_DATE); |
| | 35114 | if (JS_IsException(obj)) |
| | 35115 | goto fail; |
| | 35116 | if (BC_add_object_ref(s, obj)) |
| | 35117 | goto fail; |
| | 35118 | JS_SetObjectData(ctx, obj, val); |
| | 35119 | return obj; |
| | 35120 | fail: |
| | 35121 | JS_FreeValue(ctx, val); |
| | 35122 | JS_FreeValue(ctx, obj); |
| | 35123 | return JS_EXCEPTION; |
| | 35124 | } |
| | 35125 | |
| | 35126 | static JSValue JS_ReadObjectValue(BCReaderState *s) |
| | 35127 | { |
| | 35128 | JSContext *ctx = s->ctx; |
| | 35129 | JSValue val, obj = JS_UNDEFINED; |
| | 35130 | |
| | 35131 | val = JS_ReadObjectRec(s); |
| | 35132 | if (JS_IsException(val)) |
| | 35133 | goto fail; |
| | 35134 | obj = JS_ToObject(ctx, val); |
| | 35135 | if (JS_IsException(obj)) |
| | 35136 | goto fail; |
| | 35137 | if (BC_add_object_ref(s, obj)) |
| | 35138 | goto fail; |
| | 35139 | JS_FreeValue(ctx, val); |
| | 35140 | return obj; |
| | 35141 | fail: |
| | 35142 | JS_FreeValue(ctx, val); |
| | 35143 | JS_FreeValue(ctx, obj); |
| | 35144 | return JS_EXCEPTION; |
| | 35145 | } |
| | 35146 | |
| 33964 | static JSValue JS_ReadObjectRec(BCReaderState *s) | 35147 | static JSValue JS_ReadObjectRec(BCReaderState *s) |
| 33965 | { | 35148 | { |
| 33966 | JSContext *ctx = s->ctx; | 35149 | JSContext *ctx = s->ctx; |
| 33967 | uint8_t tag; | 35150 | uint8_t tag; |
| 33968 | JSValue obj = JS_UNDEFINED; | 35151 | JSValue obj = JS_UNDEFINED; |
| 33969 | JSModuleDef *m = NULL; | 35152 | |
| | 35153 | if (js_check_stack_overflow(ctx->rt, 0)) |
| | 35154 | return JS_ThrowStackOverflow(ctx); |
| 33970 | | 35155 | |
| 33971 | if (bc_get_u8(s, &tag)) | 35156 | if (bc_get_u8(s, &tag)) |
| 33972 | return JS_EXCEPTION; | 35157 | return JS_EXCEPTION; |
| 33973 | | 35158 | |
| | 35159 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); |
| | 35160 | |
| 33974 | switch(tag) { | 35161 | switch(tag) { |
| 33975 | case BC_TAG_NULL: | 35162 | case BC_TAG_NULL: |
| 33976 | bc_read_trace(s, "null\n"); | | |
| 33977 | obj = JS_NULL; | 35163 | obj = JS_NULL; |
| 33978 | break; | 35164 | break; |
| 33979 | case BC_TAG_UNDEFINED: | 35165 | case BC_TAG_UNDEFINED: |
| 33980 | bc_read_trace(s, "undefined\n"); | | |
| 33981 | obj = JS_UNDEFINED; | 35166 | obj = JS_UNDEFINED; |
| 33982 | break; | 35167 | break; |
| 33983 | case BC_TAG_BOOL_FALSE: | 35168 | case BC_TAG_BOOL_FALSE: |
| 33984 | case BC_TAG_BOOL_TRUE: | 35169 | case BC_TAG_BOOL_TRUE: |
| 33985 | bc_read_trace(s, "%s\n", bc_tag_str[tag]); | | |
| 33986 | obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE); | 35170 | obj = JS_NewBool(ctx, tag - BC_TAG_BOOL_FALSE); |
| 33987 | break; | 35171 | break; |
| 33988 | case BC_TAG_INT32: | 35172 | case BC_TAG_INT32: |
| @@ -33990,7 +35174,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 1 unmodified line |
| 33990 | int32_t val; | 35174 | int32_t val; |
| 33991 | if (bc_get_sleb128(s, &val)) | 35175 | if (bc_get_sleb128(s, &val)) |
| 33992 | return JS_EXCEPTION; | 35176 | return JS_EXCEPTION; |
| 33993 | bc_read_trace(s, "int32 %d\n", val); | 35177 | bc_read_trace(s, "%d\n", val); |
| 33994 | obj = JS_NewInt32(ctx, val); | 35178 | obj = JS_NewInt32(ctx, val); |
| 33995 | } | 35179 | } |
| 33996 | break; | 35180 | break; |
| @@ -33999,7 +35183,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 2 unmodified lines |
| 33999 | JSFloat64Union u; | 35183 | JSFloat64Union u; |
| 34000 | if (bc_get_u64(s, &u.u64)) | 35184 | if (bc_get_u64(s, &u.u64)) |
| 34001 | return JS_EXCEPTION; | 35185 | return JS_EXCEPTION; |
| 34002 | bc_read_trace(s, "float64 %g\n", u.d); | 35186 | bc_read_trace(s, "%g\n", u.d); |
| 34003 | obj = __JS_NewFloat64(ctx, u.d); | 35187 | obj = __JS_NewFloat64(ctx, u.d); |
| 34004 | } | 35188 | } |
| 34005 | break; | 35189 | break; |
| @@ -34013,378 +35197,68 @@ static JSValue JS_ReadObjectRec(BCReaderState *s) · 7 unmodified lines |
| 34013 | } | 35197 | } |
| 34014 | break; | 35198 | break; |
| 34015 | case BC_TAG_FUNCTION_BYTECODE: | 35199 | case BC_TAG_FUNCTION_BYTECODE: |
| 34016 | { | 35200 | if (!s->allow_bytecode) |
| 34017 | JSFunctionBytecode bc, *b; | 35201 | goto invalid_tag; |
| 34018 | uint16_t v16; | 35202 | obj = JS_ReadFunctionTag(s); |
| 34019 | uint8_t v8; | | |
| 34020 | int idx, i, local_count; | | |
| 34021 | int function_size, cpool_offset, byte_code_offset; | | |
| 34022 | int closure_var_offset, vardefs_offset; | | |
| 34023 | | | |
| 34024 | if (!s->allow_bytecode) | | |
| 34025 | goto invalid_tag; | | |
| 34026 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); | | |
| 34027 | | | |
| 34028 | memset(&bc, 0, sizeof(bc)); | | |
| 34029 | bc.header.ref_count = 1; | | |
| 34030 | //bc.gc_header.mark = 0; | | |
| 34031 | | | |
| 34032 | if (bc_get_u16(s, &v16)) | | |
| 34033 | goto fail; | | |
| 34034 | idx = 0; | | |
| 34035 | bc.has_prototype = bc_get_flags(v16, &idx, 1); | | |
| 34036 | bc.has_simple_parameter_list = bc_get_flags(v16, &idx, 1); | | |
| 34037 | bc.is_derived_class_constructor = bc_get_flags(v16, &idx, 1); | | |
| 34038 | bc.need_home_object = bc_get_flags(v16, &idx, 1); | | |
| 34039 | bc.func_kind = bc_get_flags(v16, &idx, 2); | | |
| 34040 | bc.new_target_allowed = bc_get_flags(v16, &idx, 1); | | |
| 34041 | bc.super_call_allowed = bc_get_flags(v16, &idx, 1); | | |
| 34042 | bc.super_allowed = bc_get_flags(v16, &idx, 1); | | |
| 34043 | bc.arguments_allowed = bc_get_flags(v16, &idx, 1); | | |
| 34044 | bc.has_debug = bc_get_flags(v16, &idx, 1); | | |
| 34045 | bc.backtrace_barrier = bc_get_flags(v16, &idx, 1); | | |
| 34046 | bc.read_only_bytecode = s->is_rom_data; | | |
| 34047 | if (bc_get_u8(s, &v8)) | | |
| 34048 | goto fail; | | |
| 34049 | bc.js_mode = v8; | | |
| 34050 | if (bc_get_atom(s, &bc.func_name)) //@ atom leak if failure | | |
| 34051 | goto fail; | | |
| 34052 | if (bc_get_leb128_u16(s, &bc.arg_count)) | | |
| 34053 | goto fail; | | |
| 34054 | if (bc_get_leb128_u16(s, &bc.var_count)) | | |
| 34055 | goto fail; | | |
| 34056 | if (bc_get_leb128_u16(s, &bc.defined_arg_count)) | | |
| 34057 | goto fail; | | |
| 34058 | if (bc_get_leb128_u16(s, &bc.stack_size)) | | |
| 34059 | goto fail; | | |
| 34060 | if (bc_get_leb128_int(s, &bc.closure_var_count)) | | |
| 34061 | goto fail; | | |
| 34062 | if (bc_get_leb128_int(s, &bc.cpool_count)) | | |
| 34063 | goto fail; | | |
| 34064 | if (bc_get_leb128_int(s, &bc.byte_code_len)) | | |
| 34065 | goto fail; | | |
| 34066 | if (bc_get_leb128_int(s, &local_count)) | | |
| 34067 | goto fail; | | |
| 34068 | | | |
| 34069 | if (bc.has_debug) { | | |
| 34070 | function_size = sizeof(*b); | | |
| 34071 | } else { | | |
| 34072 | function_size = offsetof(JSFunctionBytecode, debug); | | |
| 34073 | } | | |
| 34074 | cpool_offset = function_size; | | |
| 34075 | function_size += bc.cpool_count * sizeof(*bc.cpool); | | |
| 34076 | vardefs_offset = function_size; | | |
| 34077 | function_size += local_count * sizeof(*bc.vardefs); | | |
| 34078 | closure_var_offset = function_size; | | |
| 34079 | function_size += bc.closure_var_count * sizeof(*bc.closure_var); | | |
| 34080 | byte_code_offset = function_size; | | |
| 34081 | if (!bc.read_only_bytecode) { | | |
| 34082 | function_size += bc.byte_code_len; | | |
| 34083 | } | | |
| 34084 | | | |
| 34085 | b = js_mallocz(ctx, function_size); | | |
| 34086 | if (!b) | | |
| 34087 | return JS_EXCEPTION; | | |
| 34088 | | | |
| 34089 | memcpy(b, &bc, offsetof(JSFunctionBytecode, debug)); | | |
| 34090 | b->header.ref_count = 1; | | |
| 34091 | add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); | | |
| 34092 | | | |
| 34093 | obj = JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b); | | |
| 34094 | | | |
| 34095 | #ifdef DUMP_READ_OBJECT | | |
| 34096 | bc_read_trace(s, "name: "); print_atom(s->ctx, b->func_name); printf("\n"); | | |
| 34097 | #endif | | |
| 34098 | bc_read_trace(s, "args=%d vars=%d defargs=%d closures=%d cpool=%d\n", | | |
| 34099 | b->arg_count, b->var_count, b->defined_arg_count, | | |
| 34100 | b->closure_var_count, b->cpool_count); | | |
| 34101 | bc_read_trace(s, "stack=%d bclen=%d locals=%d\n", | | |
| 34102 | b->stack_size, b->byte_code_len, local_count); | | |
| 34103 | | | |
| 34104 | if (local_count != 0) { | | |
| 34105 | bc_read_trace(s, "vars {\n"); | | |
| 34106 | b->vardefs = (void *)((uint8_t*)b + vardefs_offset); | | |
| 34107 | for(i = 0; i < local_count; i++) { | | |
| 34108 | JSVarDef *vd = &b->vardefs[i]; | | |
| 34109 | if (bc_get_atom(s, &vd->var_name)) | | |
| 34110 | goto fail; | | |
| 34111 | if (bc_get_leb128_int(s, &vd->scope_level)) | | |
| 34112 | goto fail; | | |
| 34113 | if (bc_get_leb128_int(s, &vd->scope_next)) | | |
| 34114 | goto fail; | | |
| 34115 | vd->scope_next--; | | |
| 34116 | if (bc_get_u8(s, &v8)) | | |
| 34117 | goto fail; | | |
| 34118 | idx = 0; | | |
| 34119 | vd->var_kind = bc_get_flags(v8, &idx, 4); | | |
| 34120 | vd->is_func_var = bc_get_flags(v8, &idx, 1); | | |
| 34121 | vd->is_const = bc_get_flags(v8, &idx, 1); | | |
| 34122 | vd->is_lexical = bc_get_flags(v8, &idx, 1); | | |
| 34123 | vd->is_captured = bc_get_flags(v8, &idx, 1); | | |
| 34124 | #ifdef DUMP_READ_OBJECT | | |
| 34125 | bc_read_trace(s, "name: "); print_atom(s->ctx, vd->var_name); printf("\n"); | | |
| 34126 | #endif | | |
| 34127 | } | | |
| 34128 | bc_read_trace(s, "}\n"); | | |
| 34129 | } | | |
| 34130 | if (b->closure_var_count != 0) { | | |
| 34131 | bc_read_trace(s, "closure vars {\n"); | | |
| 34132 | b->closure_var = (void *)((uint8_t*)b + closure_var_offset); | | |
| 34133 | for(i = 0; i < b->closure_var_count; i++) { | | |
| 34134 | JSClosureVar *cv = &b->closure_var[i]; | | |
| 34135 | int var_idx; | | |
| 34136 | if (bc_get_atom(s, &cv->var_name)) | | |
| 34137 | goto fail; | | |
| 34138 | if (bc_get_leb128_int(s, &var_idx)) | | |
| 34139 | goto fail; | | |
| 34140 | cv->var_idx = var_idx; | | |
| 34141 | if (bc_get_u8(s, &v8)) | | |
| 34142 | goto fail; | | |
| 34143 | idx = 0; | | |
| 34144 | cv->is_local = bc_get_flags(v8, &idx, 1); | | |
| 34145 | cv->is_arg = bc_get_flags(v8, &idx, 1); | | |
| 34146 | cv->is_const = bc_get_flags(v8, &idx, 1); | | |
| 34147 | cv->is_lexical = bc_get_flags(v8, &idx, 1); | | |
| 34148 | cv->var_kind = bc_get_flags(v8, &idx, 4); | | |
| 34149 | #ifdef DUMP_READ_OBJECT | | |
| 34150 | bc_read_trace(s, "name: "); print_atom(s->ctx, cv->var_name); printf("\n"); | | |
| 34151 | #endif | | |
| 34152 | } | | |
| 34153 | bc_read_trace(s, "}\n"); | | |
| 34154 | } | | |
| 34155 | { | | |
| 34156 | bc_read_trace(s, "bytecode {\n"); | | |
| 34157 | if (JS_ReadFunctionBytecode(s, b, byte_code_offset, b->byte_code_len)) | | |
| 34158 | goto fail; | | |
| 34159 | bc_read_trace(s, "}\n"); | | |
| 34160 | } | | |
| 34161 | if (b->has_debug) { | | |
| 34162 | /* read optional debug information */ | | |
| 34163 | bc_read_trace(s, "debug {\n"); | | |
| 34164 | if (bc_get_atom(s, &b->debug.filename)) | | |
| 34165 | goto fail; | | |
| 34166 | if (bc_get_leb128_int(s, &b->debug.line_num)) | | |
| 34167 | goto fail; | | |
| 34168 | if (bc_get_leb128_int(s, &b->debug.pc2line_len)) | | |
| 34169 | goto fail; | | |
| 34170 | if (b->debug.pc2line_len) { | | |
| 34171 | b->debug.pc2line_buf = js_mallocz(ctx, b->debug.pc2line_len); | | |
| 34172 | if (!b->debug.pc2line_buf) | | |
| 34173 | goto fail; | | |
| 34174 | if (bc_get_buf(s, b->debug.pc2line_buf, b->debug.pc2line_len)) | | |
| 34175 | goto fail; | | |
| 34176 | } | | |
| 34177 | #ifdef DUMP_READ_OBJECT | | |
| 34178 | bc_read_trace(s, "filename: "); print_atom(s->ctx, b->debug.filename); printf("\n"); | | |
| 34179 | #endif | | |
| 34180 | bc_read_trace(s, "}\n"); | | |
| 34181 | } | | |
| 34182 | if (b->cpool_count != 0) { | | |
| 34183 | bc_read_trace(s, "cpool {\n"); | | |
| 34184 | b->cpool = (void *)((uint8_t*)b + cpool_offset); | | |
| 34185 | for(i = 0; i < b->cpool_count; i++) { | | |
| 34186 | JSValue val; | | |
| 34187 | val = JS_ReadObjectRec(s); | | |
| 34188 | if (JS_IsException(val)) | | |
| 34189 | goto fail; | | |
| 34190 | b->cpool[i] = val; | | |
| 34191 | } | | |
| 34192 | bc_read_trace(s, "}\n"); | | |
| 34193 | } | | |
| 34194 | bc_read_trace(s, "}\n"); | | |
| 34195 | b->realm = JS_DupContext(ctx); | | |
| 34196 | } | | |
| 34197 | break; | 35203 | break; |
| 34198 | case BC_TAG_MODULE: | 35204 | case BC_TAG_MODULE: |
| 34199 | { | 35205 | if (!s->allow_bytecode) |
| 34200 | JSAtom module_name; | 35206 | goto invalid_tag; |
| 34201 | int i; | 35207 | obj = JS_ReadModule(s); |
| 34202 | uint8_t v8; | | |
| 34203 | | | |
| 34204 | if (!s->allow_bytecode) | | |
| 34205 | goto invalid_tag; | | |
| 34206 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); | | |
| 34207 | if (bc_get_atom(s, &module_name)) | | |
| 34208 | goto fail; | | |
| 34209 | #ifdef DUMP_READ_OBJECT | | |
| 34210 | bc_read_trace(s, "name: "); print_atom(s->ctx, module_name); printf("\n"); | | |
| 34211 | #endif | | |
| 34212 | m = js_new_module_def(ctx, module_name); | | |
| 34213 | if (!m) | | |
| 34214 | goto fail; | | |
| 34215 | obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); | | |
| 34216 | if (bc_get_leb128_int(s, &m->req_module_entries_count)) | | |
| 34217 | goto fail; | | |
| 34218 | if (m->req_module_entries_count != 0) { | | |
| 34219 | m->req_module_entries_size = m->req_module_entries_count; | | |
| 34220 | m->req_module_entries = js_mallocz(ctx, sizeof(m->req_module_entries[0]) * m->req_module_entries_size); | | |
| 34221 | if (!m->req_module_entries) | | |
| 34222 | goto fail; | | |
| 34223 | for(i = 0; i < m->req_module_entries_count; i++) { | | |
| 34224 | JSReqModuleEntry *rme = &m->req_module_entries[i]; | | |
| 34225 | if (bc_get_atom(s, &rme->module_name)) | | |
| 34226 | goto fail; | | |
| 34227 | } | | |
| 34228 | } | | |
| 34229 | | | |
| 34230 | if (bc_get_leb128_int(s, &m->export_entries_count)) | | |
| 34231 | goto fail; | | |
| 34232 | if (m->export_entries_count != 0) { | | |
| 34233 | m->export_entries_size = m->export_entries_count; | | |
| 34234 | m->export_entries = js_mallocz(ctx, sizeof(m->export_entries[0]) * m->export_entries_size); | | |
| 34235 | if (!m->export_entries) | | |
| 34236 | goto fail; | | |
| 34237 | for(i = 0; i < m->export_entries_count; i++) { | | |
| 34238 | JSExportEntry *me = &m->export_entries[i]; | | |
| 34239 | if (bc_get_u8(s, &v8)) | | |
| 34240 | goto fail; | | |
| 34241 | me->export_type = v8; | | |
| 34242 | if (me->export_type == JS_EXPORT_TYPE_LOCAL) { | | |
| 34243 | if (bc_get_leb128_int(s, &me->u.local.var_idx)) | | |
| 34244 | goto fail; | | |
| 34245 | } else { | | |
| 34246 | if (bc_get_leb128_int(s, &me->u.req_module_idx)) | | |
| 34247 | goto fail; | | |
| 34248 | if (bc_get_atom(s, &me->local_name)) | | |
| 34249 | goto fail; | | |
| 34250 | } | | |
| 34251 | if (bc_get_atom(s, &me->export_name)) | | |
| 34252 | goto fail; | | |
| 34253 | } | | |
| 34254 | } | | |
| 34255 | | | |
| 34256 | if (bc_get_leb128_int(s, &m->star_export_entries_count)) | | |
| 34257 | goto fail; | | |
| 34258 | if (m->star_export_entries_count != 0) { | | |
| 34259 | m->star_export_entries_size = m->star_export_entries_count; | | |
| 34260 | m->star_export_entries = js_mallocz(ctx, sizeof(m->star_export_entries[0]) * m->star_export_entries_size); | | |
| 34261 | if (!m->star_export_entries) | | |
| 34262 | goto fail; | | |
| 34263 | for(i = 0; i < m->star_export_entries_count; i++) { | | |
| 34264 | JSStarExportEntry *se = &m->star_export_entries[i]; | | |
| 34265 | if (bc_get_leb128_int(s, &se->req_module_idx)) | | |
| 34266 | goto fail; | | |
| 34267 | } | | |
| 34268 | } | | |
| 34269 | | | |
| 34270 | if (bc_get_leb128_int(s, &m->import_entries_count)) | | |
| 34271 | goto fail; | | |
| 34272 | if (m->import_entries_count != 0) { | | |
| 34273 | m->import_entries_size = m->import_entries_count; | | |
| 34274 | m->import_entries = js_mallocz(ctx, sizeof(m->import_entries[0]) * m->import_entries_size); | | |
| 34275 | if (!m->import_entries) | | |
| 34276 | goto fail; | | |
| 34277 | for(i = 0; i < m->import_entries_count; i++) { | | |
| 34278 | JSImportEntry *mi = &m->import_entries[i]; | | |
| 34279 | if (bc_get_leb128_int(s, &mi->var_idx)) | | |
| 34280 | goto fail; | | |
| 34281 | if (bc_get_atom(s, &mi->import_name)) | | |
| 34282 | goto fail; | | |
| 34283 | if (bc_get_leb128_int(s, &mi->req_module_idx)) | | |
| 34284 | goto fail; | | |
| 34285 | } | | |
| 34286 | } | | |
| 34287 | | | |
| 34288 | m->func_obj = JS_ReadObjectRec(s); | | |
| 34289 | if (JS_IsException(m->func_obj)) | | |
| 34290 | goto fail; | | |
| 34291 | bc_read_trace(s, "}\n"); | | |
| 34292 | } | | |
| 34293 | break; | 35208 | break; |
| 34294 | case BC_TAG_OBJECT: | 35209 | case BC_TAG_OBJECT: |
| 34295 | { | 35210 | obj = JS_ReadObjectTag(s); |
| 34296 | uint32_t prop_count, i; | | |
| 34297 | JSAtom atom; | | |
| 34298 | JSValue val; | | |
| 34299 | int ret; | | |
| 34300 | | | |
| 34301 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); | | |
| 34302 | | | |
| 34303 | obj = JS_NewObject(ctx); | | |
| 34304 | if (bc_get_leb128(s, &prop_count)) | | |
| 34305 | goto fail; | | |
| 34306 | for(i = 0; i < prop_count; i++) { | | |
| 34307 | if (bc_get_atom(s, &atom)) | | |
| 34308 | goto fail; | | |
| 34309 | #ifdef DUMP_READ_OBJECT | | |
| 34310 | bc_read_trace(s, "propname: "); print_atom(s->ctx, atom); printf("\n"); | | |
| 34311 | #endif | | |
| 34312 | val = JS_ReadObjectRec(s); | | |
| 34313 | if (JS_IsException(val)) { | | |
| 34314 | JS_FreeAtom(ctx, atom); | | |
| 34315 | goto fail; | | |
| 34316 | } | | |
| 34317 | ret = JS_DefinePropertyValue(ctx, obj, atom, val, JS_PROP_C_W_E); | | |
| 34318 | JS_FreeAtom(ctx, atom); | | |
| 34319 | if (ret < 0) | | |
| 34320 | goto fail; | | |
| 34321 | } | | |
| 34322 | bc_read_trace(s, "}\n"); | | |
| 34323 | } | | |
| 34324 | break; | 35211 | break; |
| 34325 | case BC_TAG_ARRAY: | 35212 | case BC_TAG_ARRAY: |
| 34326 | case BC_TAG_TEMPLATE_OBJECT: | 35213 | case BC_TAG_TEMPLATE_OBJECT: |
| 34327 | { | 35214 | obj = JS_ReadArray(s, tag); |
| 34328 | uint32_t len, i; | 35215 | break; |
| 34329 | JSValue val; | 35216 | case BC_TAG_TYPED_ARRAY: |
| 34330 | int ret, prop_flags; | 35217 | obj = JS_ReadTypedArray(s); |
| 34331 | BOOL is_template; | 35218 | break; |
| 34332 | | 35219 | case BC_TAG_ARRAY_BUFFER: |
| 34333 | bc_read_trace(s, "%s {\n", bc_tag_str[tag]); | 35220 | obj = JS_ReadArrayBuffer(s); |
| 34334 | | 35221 | break; |
| 34335 | obj = JS_NewArray(ctx); | 35222 | case BC_TAG_SHARED_ARRAY_BUFFER: |
| 34336 | is_template = (tag == BC_TAG_TEMPLATE_OBJECT); | 35223 | if (!s->allow_sab || !ctx->rt->sab_funcs.sab_dup) |
| 34337 | if (bc_get_leb128(s, &len)) | 35224 | goto invalid_tag; |
| 34338 | goto fail; | 35225 | obj = JS_ReadSharedArrayBuffer(s); |
| 34339 | for(i = 0; i < len; i++) { | 35226 | break; |
| 34340 | val = JS_ReadObjectRec(s); | 35227 | case BC_TAG_DATE: |
| 34341 | if (JS_IsException(val)) | 35228 | obj = JS_ReadDate(s); |
| 34342 | goto fail; | 35229 | break; |
| 34343 | if (is_template) | 35230 | case BC_TAG_OBJECT_VALUE: |
| 34344 | prop_flags = JS_PROP_ENUMERABLE; | 35231 | obj = JS_ReadObjectValue(s); |
| 34345 | else | | |
| 34346 | prop_flags = JS_PROP_C_W_E; | | |
| 34347 | ret = JS_DefinePropertyValueUint32(ctx, obj, i, val, | | |
| 34348 | prop_flags); | | |
| 34349 | if (ret < 0) | | |
| 34350 | goto fail; | | |
| 34351 | } | | |
| 34352 | if (is_template) { | | |
| 34353 | val = JS_ReadObjectRec(s); | | |
| 34354 | if (JS_IsException(val)) | | |
| 34355 | goto fail; | | |
| 34356 | if (!JS_IsUndefined(val)) { | | |
| 34357 | ret = JS_DefinePropertyValue(ctx, obj, JS_ATOM_raw, val, 0); | | |
| 34358 | if (ret < 0) | | |
| 34359 | goto fail; | | |
| 34360 | } | | |
| 34361 | JS_PreventExtensions(ctx, obj); | | |
| 34362 | } | | |
| 34363 | bc_read_trace(s, "}\n"); | | |
| 34364 | } | | |
| 34365 | break; | 35232 | break; |
| 34366 | #ifdef CONFIG_BIGNUM | 35233 | #ifdef CONFIG_BIGNUM |
| 34367 | case BC_TAG_BIG_INT: | 35234 | case BC_TAG_BIG_INT: |
| 34368 | case BC_TAG_BIG_FLOAT: | 35235 | case BC_TAG_BIG_FLOAT: |
| 34369 | case BC_TAG_BIG_DECIMAL: | 35236 | case BC_TAG_BIG_DECIMAL: |
| 34370 | obj = JS_ReadBigNum(s, tag); | 35237 | obj = JS_ReadBigNum(s, tag); |
| 34371 | if (JS_IsException(obj)) | | |
| 34372 | goto fail; | | |
| 34373 | break; | 35238 | break; |
| 34374 | #endif | 35239 | #endif |
| | 35240 | case BC_TAG_OBJECT_REFERENCE: |
| | 35241 | { |
| | 35242 | uint32_t val; |
| | 35243 | if (!s->allow_reference) |
| | 35244 | return JS_ThrowSyntaxError(ctx, "object references are not allowed"); |
| | 35245 | if (bc_get_leb128(s, &val)) |
| | 35246 | return JS_EXCEPTION; |
| | 35247 | bc_read_trace(s, "%u\n", val); |
| | 35248 | if (val >= s->objects_count) { |
| | 35249 | return JS_ThrowSyntaxError(ctx, "invalid object reference (%u >= %u)", |
| | 35250 | val, s->objects_count); |
| | 35251 | } |
| | 35252 | obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, s->objects[val])); |
| | 35253 | } |
| | 35254 | break; |
| 34375 | default: | 35255 | default: |
| 34376 | invalid_tag: | 35256 | invalid_tag: |
| 34377 | return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)", | 35257 | return JS_ThrowSyntaxError(ctx, "invalid tag (tag=%d pos=%u)", |
| 34378 | tag, (unsigned int)(s->ptr - s->buf_start)); | 35258 | tag, (unsigned int)(s->ptr - s->buf_start)); |
| 34379 | } | 35259 | } |
| | 35260 | bc_read_trace(s, "}\n"); |
| 34380 | return obj; | 35261 | return obj; |
| 34381 | fail: | | |
| 34382 | if (m) { | | |
| 34383 | js_free_module_def(ctx, m); | | |
| 34384 | } else { | | |
| 34385 | JS_FreeValue(ctx, obj); | | |
| 34386 | } | | |
| 34387 | return JS_EXCEPTION; | | |
| 34388 | } | 35262 | } |
| 34389 | | 35263 | |
| 34390 | static int JS_ReadObjectAtoms(BCReaderState *s) | 35264 | static int JS_ReadObjectAtoms(BCReaderState *s) |
| @@ -34437,10 +35311,11 @@ static void bc_reader_free(BCReaderState *s) · 46 unmodified lines |
| 34437 | } | 35311 | } |
| 34438 | js_free(s->ctx, s->idx_to_atom); | 35312 | js_free(s->ctx, s->idx_to_atom); |
| 34439 | } | 35313 | } |
| | 35314 | js_free(s->ctx, s->objects); |
| 34440 | } | 35315 | } |
| 34441 | | 35316 | |
| 34442 | JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, | 35317 | JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, |
| 34443 | int flags) | 35318 | int flags) |
| 34444 | { | 35319 | { |
| 34445 | BCReaderState ss, *s = &ss; | 35320 | BCReaderState ss, *s = &ss; |
| 34446 | JSValue obj; | 35321 | JSValue obj; |
| @@ -34455,6 +35330,8 @@ JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len, · 8 unmodified lines |
| 34455 | s->ptr = buf; | 35330 | s->ptr = buf; |
| 34456 | s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0); | 35331 | s->allow_bytecode = ((flags & JS_READ_OBJ_BYTECODE) != 0); |
| 34457 | s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0); | 35332 | s->is_rom_data = ((flags & JS_READ_OBJ_ROM_DATA) != 0); |
| | 35333 | s->allow_sab = ((flags & JS_READ_OBJ_SAB) != 0); |
| | 35334 | s->allow_reference = ((flags & JS_READ_OBJ_REFERENCE) != 0); |
| 34458 | if (s->allow_bytecode) | 35335 | if (s->allow_bytecode) |
| 34459 | s->first_atom = JS_ATOM_END; | 35336 | s->first_atom = JS_ATOM_END; |
| 34460 | else | 35337 | else |
| @@ -34944,7 +35821,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx, · 483 unmodified lines |
| 34944 | if (JS_IsException(props)) | 35821 | if (JS_IsException(props)) |
| 34945 | return -1; | 35822 | return -1; |
| 34946 | p = JS_VALUE_GET_OBJ(props); | 35823 | p = JS_VALUE_GET_OBJ(props); |
| 34947 | if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK) < 0) | 35824 | if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &len, p, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK) < 0) |
| 34948 | goto exception; | 35825 | goto exception; |
| 34949 | for(i = 0; i < len; i++) { | 35826 | for(i = 0; i < len; i++) { |
| 34950 | JS_FreeValue(ctx, desc); | 35827 | JS_FreeValue(ctx, desc); |
| @@ -35021,7 +35898,7 @@ static JSValue js_object_getPrototypeOf(JSContext *ctx, JSValueConst this_val, · 70 unmodified lines |
| 35021 | JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED) | 35898 | JS_VALUE_GET_TAG(val) == JS_TAG_UNDEFINED) |
| 35022 | return JS_ThrowTypeErrorNotAnObject(ctx); | 35899 | return JS_ThrowTypeErrorNotAnObject(ctx); |
| 35023 | } | 35900 | } |
| 35024 | return JS_DupValue(ctx, JS_GetPrototype(ctx, val)); | 35901 | return JS_GetPrototype(ctx, val); |
| 35025 | } | 35902 | } |
| 35026 | | 35903 | |
| 35027 | static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val, | 35904 | static JSValue js_object_setPrototypeOf(JSContext *ctx, JSValueConst this_val, |
| @@ -35815,7 +36692,7 @@ static JSValue js_object_get___proto__(JSContext *ctx, JSValueConst this_val) · 787 unmodified lines |
| 35815 | val = JS_ToObject(ctx, this_val); | 36692 | val = JS_ToObject(ctx, this_val); |
| 35816 | if (JS_IsException(val)) | 36693 | if (JS_IsException(val)) |
| 35817 | return val; | 36694 | return val; |
| 35818 | ret = JS_DupValue(ctx, JS_GetPrototype(ctx, val)); | 36695 | ret = JS_GetPrototype(ctx, val); |
| 35819 | JS_FreeValue(ctx, val); | 36696 | JS_FreeValue(ctx, val); |
| 35820 | return ret; | 36697 | return ret; |
| 35821 | } | 36698 | } |
| @@ -35836,9 +36713,9 @@ static JSValue js_object_set___proto__(JSContext *ctx, JSValueConst this_val, · 14 unmodified lines |
| 35836 | static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, | 36713 | static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, |
| 35837 | int argc, JSValueConst *argv) | 36714 | int argc, JSValueConst *argv) |
| 35838 | { | 36715 | { |
| 35839 | JSValue obj; | 36716 | JSValue obj, v1; |
| 35840 | JSValueConst v; | 36717 | JSValueConst v; |
| 35841 | int max_depth = 1000, res = -1; | 36718 | int res; |
| 35842 | | 36719 | |
| 35843 | v = argv[0]; | 36720 | v = argv[0]; |
| 35844 | if (!JS_IsObject(v)) | 36721 | if (!JS_IsObject(v)) |
| @@ -35846,27 +36723,29 @@ static JSValue js_object_isPrototypeOf(JSContext *ctx, JSValueConst this_val, · 1 unmodified line |
| 35846 | obj = JS_ToObject(ctx, this_val); | 36723 | obj = JS_ToObject(ctx, this_val); |
| 35847 | if (JS_IsException(obj)) | 36724 | if (JS_IsException(obj)) |
| 35848 | return JS_EXCEPTION; | 36725 | return JS_EXCEPTION; |
| 35849 | while (--max_depth > 0) { | 36726 | v1 = JS_DupValue(ctx, v); |
| 35850 | v = JS_GetPrototype(ctx, v); | 36727 | for(;;) { |
| 35851 | if (JS_IsException(v)) | 36728 | v1 = JS_GetPrototypeFree(ctx, v1); |
| | 36729 | if (JS_IsException(v1)) |
| 35852 | goto exception; | 36730 | goto exception; |
| 35853 | if (JS_IsNull(v)) { | 36731 | if (JS_IsNull(v1)) { |
| 35854 | res = FALSE; | 36732 | res = FALSE; |
| 35855 | break; | 36733 | break; |
| 35856 | } | 36734 | } |
| 35857 | if (js_strict_eq2(ctx, JS_DupValue(ctx, obj), JS_DupValue(ctx, v), | 36735 | if (JS_VALUE_GET_OBJ(obj) == JS_VALUE_GET_OBJ(v1)) { |
| 35858 | JS_EQ_STRICT)) { | | |
| 35859 | res = TRUE; | 36736 | res = TRUE; |
| 35860 | break; | 36737 | break; |
| 35861 | } | 36738 | } |
| | 36739 | /* avoid infinite loop (possible with proxies) */ |
| | 36740 | if (js_poll_interrupts(ctx)) |
| | 36741 | goto exception; |
| 35862 | } | 36742 | } |
| | 36743 | JS_FreeValue(ctx, v1); |
| 35863 | JS_FreeValue(ctx, obj); | 36744 | JS_FreeValue(ctx, obj); |
| 35864 | if (res < 0) | 36745 | return JS_NewBool(ctx, res); |
| 35865 | return JS_ThrowInternalError(ctx, "prototype chain cycle"); | | |
| 35866 | else | | |
| 35867 | return JS_NewBool(ctx, res); | | |
| 35868 | | 36746 | |
| 35869 | exception: | 36747 | exception: |
| | 36748 | JS_FreeValue(ctx, v1); |
| 35870 | JS_FreeValue(ctx, obj); | 36749 | JS_FreeValue(ctx, obj); |
| 35871 | return JS_EXCEPTION; | 36750 | return JS_EXCEPTION; |
| 35872 | } | 36751 | } |
| @@ -35906,7 +36785,6 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 33 unmodified lines |
| 35906 | int argc, JSValueConst *argv, int setter) | 36785 | int argc, JSValueConst *argv, int setter) |
| 35907 | { | 36786 | { |
| 35908 | JSValue obj, res = JS_EXCEPTION; | 36787 | JSValue obj, res = JS_EXCEPTION; |
| 35909 | JSValueConst v; | | |
| 35910 | JSAtom prop = JS_ATOM_NULL; | 36788 | JSAtom prop = JS_ATOM_NULL; |
| 35911 | JSPropertyDescriptor desc; | 36789 | JSPropertyDescriptor desc; |
| 35912 | int has_prop; | 36790 | int has_prop; |
| @@ -35918,8 +36796,8 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 5 unmodified lines |
| 35918 | if (unlikely(prop == JS_ATOM_NULL)) | 36796 | if (unlikely(prop == JS_ATOM_NULL)) |
| 35919 | goto exception; | 36797 | goto exception; |
| 35920 | | 36798 | |
| 35921 | for (v = obj;;) { | 36799 | for (;;) { |
| 35922 | has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(v), prop); | 36800 | has_prop = JS_GetOwnPropertyInternal(ctx, &desc, JS_VALUE_GET_OBJ(obj), prop); |
| 35923 | if (has_prop < 0) | 36801 | if (has_prop < 0) |
| 35924 | goto exception; | 36802 | goto exception; |
| 35925 | if (has_prop) { | 36803 | if (has_prop) { |
| @@ -35930,13 +36808,16 @@ static JSValue js_object___lookupGetter__(JSContext *ctx, JSValueConst this_val, · 4 unmodified lines |
| 35930 | js_free_desc(ctx, &desc); | 36808 | js_free_desc(ctx, &desc); |
| 35931 | break; | 36809 | break; |
| 35932 | } | 36810 | } |
| 35933 | v = JS_GetPrototype(ctx, v); | 36811 | obj = JS_GetPrototypeFree(ctx, obj); |
| 35934 | if (JS_IsException(v)) | 36812 | if (JS_IsException(obj)) |
| 35935 | goto exception; | 36813 | goto exception; |
| 35936 | if (JS_IsNull(v)) { | 36814 | if (JS_IsNull(obj)) { |
| 35937 | res = JS_UNDEFINED; | 36815 | res = JS_UNDEFINED; |
| 35938 | break; | 36816 | break; |
| 35939 | } | 36817 | } |
| | 36818 | /* avoid infinite loop (possible with proxies) */ |
| | 36819 | if (js_poll_interrupts(ctx)) |
| | 36820 | goto exception; |
| 35940 | } | 36821 | } |
| 35941 | | 36822 | |
| 35942 | exception: | 36823 | exception: |
| @@ -36002,59 +36883,12 @@ static JSValue js_function_proto(JSContext *ctx, JSValueConst this_val, · 59 unmodified lines |
| 36002 | return JS_UNDEFINED; | 36883 | return JS_UNDEFINED; |
| 36003 | } | 36884 | } |
| 36004 | | 36885 | |
| 36005 | /* insert a '\n' at unicode character position 'pos' in the source of | | |
| 36006 | 'func_obj' */ | | |
| 36007 | static int patch_function_constructor_source(JSContext *ctx, | | |
| 36008 | JSValueConst func_obj, | | |
| 36009 | size_t pos) | | |
| 36010 | { | | |
| 36011 | JSObject *p; | | |
| 36012 | JSFunctionBytecode *b; | | |
| 36013 | char *r, *r_end, *new_source; | | |
| 36014 | int c; | | |
| 36015 | size_t idx, len; | | |
| 36016 | | | |
| 36017 | if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT) | | |
| 36018 | return 0; | | |
| 36019 | p = JS_VALUE_GET_OBJ(func_obj); | | |
| 36020 | if (!js_class_has_bytecode(p->class_id)) | | |
| 36021 | return 0; | | |
| 36022 | b = p->u.func.function_bytecode; | | |
| 36023 | if (!b->has_debug) | | |
| 36024 | return 0; | | |
| 36025 | r = b->debug.source; | | |
| 36026 | r_end = b->debug.source + b->debug.source_len; | | |
| 36027 | idx = 0; | | |
| 36028 | while (r < r_end) { | | |
| 36029 | if (idx == pos) { | | |
| 36030 | /* add the '\n' */ | | |
| 36031 | new_source = js_realloc(ctx, b->debug.source, | | |
| 36032 | b->debug.source_len + 2); | | |
| 36033 | if (!new_source) | | |
| 36034 | return -1; | | |
| 36035 | len = r - b->debug.source; | | |
| 36036 | memmove(new_source + len + 1, new_source + len, | | |
| 36037 | b->debug.source_len + 1 - len); | | |
| 36038 | new_source[len] = '\n'; | | |
| 36039 | b->debug.source = new_source; | | |
| 36040 | b->debug.source_len++; | | |
| 36041 | break; | | |
| 36042 | } | | |
| 36043 | c = unicode_from_utf8((const uint8_t *)r, UTF8_CHAR_LEN_MAX, | | |
| 36044 | (const uint8_t **)&r); | | |
| 36045 | if (c < 0) | | |
| 36046 | break; | | |
| 36047 | idx++; | | |
| 36048 | } | | |
| 36049 | return 0; | | |
| 36050 | } | | |
| 36051 | | | |
| 36052 | /* XXX: add a specific eval mode so that Function("}), ({") is rejected */ | 36886 | /* XXX: add a specific eval mode so that Function("}), ({") is rejected */ |
| 36053 | static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, | 36887 | static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, |
| 36054 | int argc, JSValueConst *argv, int magic) | 36888 | int argc, JSValueConst *argv, int magic) |
| 36055 | { | 36889 | { |
| 36056 | JSFunctionKindEnum func_kind = magic; | 36890 | JSFunctionKindEnum func_kind = magic; |
| 36057 | int i, n, ret, func_start_pos; | 36891 | int i, n, ret; |
| 36058 | JSValue s, proto, obj = JS_UNDEFINED; | 36892 | JSValue s, proto, obj = JS_UNDEFINED; |
| 36059 | StringBuffer b_s, *b = &b_s; | 36893 | StringBuffer b_s, *b = &b_s; |
| 36060 | | 36894 | |
| @@ -36079,13 +36913,7 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, · 18 unmodified lines |
| 36079 | if (string_buffer_concat_value(b, argv[i])) | 36913 | if (string_buffer_concat_value(b, argv[i])) |
| 36080 | goto fail; | 36914 | goto fail; |
| 36081 | } | 36915 | } |
| 36082 | string_buffer_puts8(b, "\n) {"); | 36916 | string_buffer_puts8(b, "\n) {\n"); |
| 36083 | /* Annex B HTML comments: We don't add a '\n' after "{" so that | | |
| 36084 | "-->" is not considered as an HTML comment. It is necessary | | |
| 36085 | because in the spec the function body is parsed separately. */ | | |
| 36086 | /* XXX: find a simpler way or be deliberately incompatible to | | |
| 36087 | simplify the code ? */ | | |
| 36088 | func_start_pos = b->len - 1; /* the leading '(' is not in the source */ | | |
| 36089 | if (n >= 0) { | 36917 | if (n >= 0) { |
| 36090 | if (string_buffer_concat_value(b, argv[n])) | 36918 | if (string_buffer_concat_value(b, argv[n])) |
| 36091 | goto fail; | 36919 | goto fail; |
| @@ -36099,8 +36927,6 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target, · 7 unmodified lines |
| 36099 | JS_FreeValue(ctx, s); | 36927 | JS_FreeValue(ctx, s); |
| 36100 | if (JS_IsException(obj)) | 36928 | if (JS_IsException(obj)) |
| 36101 | goto fail1; | 36929 | goto fail1; |
| 36102 | if (patch_function_constructor_source(ctx, obj, func_start_pos) < 0) | | |
| 36103 | goto fail1; | | |
| 36104 | if (!JS_IsUndefined(new_target)) { | 36930 | if (!JS_IsUndefined(new_target)) { |
| 36105 | /* set the prototype */ | 36931 | /* set the prototype */ |
| 36106 | proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype); | 36932 | proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype); |
| @@ -36315,27 +37141,22 @@ static JSValue js_function_toString(JSContext *ctx, JSValueConst this_val, · 208 unmodified lines |
| 36315 | JSValue name; | 37141 | JSValue name; |
| 36316 | const char *pref, *suff; | 37142 | const char *pref, *suff; |
| 36317 | | 37143 | |
| 36318 | if (p->is_class) { | 37144 | switch(func_kind) { |
| 36319 | pref = "class "; | 37145 | default: |
| 36320 | suff = " {\n [native code]\n}"; | 37146 | case JS_FUNC_NORMAL: |
| 36321 | } else { | 37147 | pref = "function "; |
| 36322 | switch(func_kind) { | 37148 | break; |
| 36323 | default: | 37149 | case JS_FUNC_GENERATOR: |
| 36324 | case JS_FUNC_NORMAL: | 37150 | pref = "function *"; |
| 36325 | pref = "function "; | 37151 | break; |
| 36326 | break; | 37152 | case JS_FUNC_ASYNC: |
| 36327 | case JS_FUNC_GENERATOR: | 37153 | pref = "async function "; |
| 36328 | pref = "function *"; | 37154 | break; |
| 36329 | break; | 37155 | case JS_FUNC_ASYNC_GENERATOR: |
| 36330 | case JS_FUNC_ASYNC: | 37156 | pref = "async function *"; |
| 36331 | pref = "async function "; | 37157 | break; |
| 36332 | break; | | |
| 36333 | case JS_FUNC_ASYNC_GENERATOR: | | |
| 36334 | pref = "async function *"; | | |
| 36335 | break; | | |
| 36336 | } | | |
| 36337 | suff = "() {\n [native code]\n}"; | | |
| 36338 | } | 37158 | } |
| | 37159 | suff = "() {\n [native code]\n}"; |
| 36339 | name = JS_GetProperty(ctx, this_val, JS_ATOM_name); | 37160 | name = JS_GetProperty(ctx, this_val, JS_ATOM_name); |
| 36340 | if (JS_IsUndefined(name)) | 37161 | if (JS_IsUndefined(name)) |
| 36341 | name = JS_AtomToString(ctx, JS_ATOM_empty_string); | 37162 | name = JS_AtomToString(ctx, JS_ATOM_empty_string); |
| @@ -36435,12 +37256,6 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, · 93 unmodified lines |
| 36435 | if (JS_IsException(obj)) | 37256 | if (JS_IsException(obj)) |
| 36436 | return obj; | 37257 | return obj; |
| 36437 | if (magic == JS_AGGREGATE_ERROR) { | 37258 | if (magic == JS_AGGREGATE_ERROR) { |
| 36438 | JSObject *p; | | |
| 36439 | JSValue error_list = iterator_to_array(ctx, argv[0]); | | |
| 36440 | if (JS_IsException(error_list)) | | |
| 36441 | goto exception; | | |
| 36442 | p = JS_VALUE_GET_OBJ(obj); | | |
| 36443 | p->u.object_data = error_list; | | |
| 36444 | message = argv[1]; | 37259 | message = argv[1]; |
| 36445 | } else { | 37260 | } else { |
| 36446 | message = argv[0]; | 37261 | message = argv[0]; |
| @@ -36448,17 +37263,26 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, · 1 unmodified line |
| 36448 | | 37263 | |
| 36449 | if (!JS_IsUndefined(message)) { | 37264 | if (!JS_IsUndefined(message)) { |
| 36450 | msg = JS_ToString(ctx, message); | 37265 | msg = JS_ToString(ctx, message); |
| 36451 | if (unlikely(JS_IsException(msg))) { | 37266 | if (unlikely(JS_IsException(msg))) |
| 36452 | exception: | 37267 | goto exception; |
| 36453 | JS_FreeValue(ctx, obj); | | |
| 36454 | return JS_EXCEPTION; | | |
| 36455 | } | | |
| 36456 | JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, | 37268 | JS_DefinePropertyValue(ctx, obj, JS_ATOM_message, msg, |
| 36457 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); | 37269 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); |
| 36458 | } | 37270 | } |
| | 37271 | |
| | 37272 | if (magic == JS_AGGREGATE_ERROR) { |
| | 37273 | JSValue error_list = iterator_to_array(ctx, argv[0]); |
| | 37274 | if (JS_IsException(error_list)) |
| | 37275 | goto exception; |
| | 37276 | JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, error_list, |
| | 37277 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); |
| | 37278 | } |
| | 37279 | |
| 36459 | /* skip the Error() function in the backtrace */ | 37280 | /* skip the Error() function in the backtrace */ |
| 36460 | build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); | 37281 | build_backtrace(ctx, obj, NULL, 0, JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL); |
| 36461 | return obj; | 37282 | return obj; |
| | 37283 | exception: |
| | 37284 | JS_FreeValue(ctx, obj); |
| | 37285 | return JS_EXCEPTION; |
| 36462 | } | 37286 | } |
| 36463 | | 37287 | |
| 36464 | static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, | 37288 | static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, |
| @@ -36498,56 +37322,22 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = { · 33 unmodified lines |
| 36498 | | 37322 | |
| 36499 | /* AggregateError */ | 37323 | /* AggregateError */ |
| 36500 | | 37324 | |
| 36501 | /* used by C code. 'errors' must be a fast array. */ | 37325 | /* used by C code. */ |
| 36502 | static JSValue js_aggregate_error_constructor(JSContext *ctx, | 37326 | static JSValue js_aggregate_error_constructor(JSContext *ctx, |
| 36503 | JSValueConst errors) | 37327 | JSValueConst errors) |
| 36504 | { | 37328 | { |
| 36505 | JSValue obj; | 37329 | JSValue obj; |
| 36506 | JSObject *p; | | |
| 36507 | | 37330 | |
| 36508 | obj = JS_NewObjectProtoClass(ctx, | 37331 | obj = JS_NewObjectProtoClass(ctx, |
| 36509 | ctx->native_error_proto[JS_AGGREGATE_ERROR], | 37332 | ctx->native_error_proto[JS_AGGREGATE_ERROR], |
| 36510 | JS_CLASS_ERROR); | 37333 | JS_CLASS_ERROR); |
| 36511 | if (JS_IsException(obj)) | 37334 | if (JS_IsException(obj)) |
| 36512 | return obj; | 37335 | return obj; |
| 36513 | p = JS_VALUE_GET_OBJ(obj); | 37336 | JS_DefinePropertyValue(ctx, obj, JS_ATOM_errors, JS_DupValue(ctx, errors), |
| 36514 | p->u.object_data = JS_DupValue(ctx, errors); | 37337 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); |
| 36515 | return obj; | 37338 | return obj; |
| 36516 | } | 37339 | } |
| 36517 | | 37340 | |
| 36518 | static JSValue js_aggregate_error_errors(JSContext *ctx, JSValueConst this_val) | | |
| 36519 | { | | |
| 36520 | JSObject *p; | | |
| 36521 | JSValue r, *arr; | | |
| 36522 | uint32_t len, i; | | |
| 36523 | | | |
| 36524 | if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) | | |
| 36525 | goto invalid_type; | | |
| 36526 | p = JS_VALUE_GET_OBJ(this_val); | | |
| 36527 | if (p->class_id != JS_CLASS_ERROR) | | |
| 36528 | goto invalid_type; | | |
| 36529 | if (!js_get_fast_array(ctx, p->u.object_data, &arr, &len)) { | | |
| 36530 | invalid_type: | | |
| 36531 | return JS_ThrowTypeError(ctx, "not an AggregateError"); | | |
| 36532 | } | | |
| 36533 | r = JS_NewArray(ctx); | | |
| 36534 | if (JS_IsException(r)) | | |
| 36535 | goto exception; | | |
| 36536 | for(i = 0; i < len; i++) { | | |
| 36537 | if (JS_DefinePropertyValueInt64(ctx, r, i, JS_DupValue(ctx, arr[i]), | | |
| 36538 | JS_PROP_C_W_E | JS_PROP_THROW) < 0) | | |
| 36539 | goto exception; | | |
| 36540 | } | | |
| 36541 | return r; | | |
| 36542 | exception: | | |
| 36543 | JS_FreeValue(ctx, r); | | |
| 36544 | return JS_EXCEPTION; | | |
| 36545 | } | | |
| 36546 | | | |
| 36547 | static const JSCFunctionListEntry js_aggregate_error_proto_funcs[] = { | | |
| 36548 | JS_CGETSET_DEF("errors", js_aggregate_error_errors, NULL), | | |
| 36549 | }; | | |
| 36550 | | | |
| 36551 | /* Array */ | 37341 | /* Array */ |
| 36552 | | 37342 | |
| 36553 | static int JS_CopySubArray(JSContext *ctx, | 37343 | static int JS_CopySubArray(JSContext *ctx, |
| @@ -39130,22 +39920,25 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, · 2576 unmodified lines |
| 39130 | p1 = JS_VALUE_GET_STRING(v); | 39920 | p1 = JS_VALUE_GET_STRING(v); |
| 39131 | len = p->len; | 39921 | len = p->len; |
| 39132 | v_len = p1->len; | 39922 | v_len = p1->len; |
| 39133 | pos = (magic & 2) ? len : 0; | 39923 | pos = (magic == 2) ? len : 0; |
| 39134 | if (argc > 1 && !JS_IsUndefined(argv[1])) { | 39924 | if (argc > 1 && !JS_IsUndefined(argv[1])) { |
| 39135 | if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0)) | 39925 | if (JS_ToInt32Clamp(ctx, &pos, argv[1], 0, len, 0)) |
| 39136 | goto fail; | 39926 | goto fail; |
| 39137 | } | 39927 | } |
| 39138 | len -= v_len; | 39928 | len -= v_len; |
| 39139 | start = pos; | 39929 | ret = 0; |
| 39140 | stop = len; | 39930 | if (magic == 0) { |
| 39141 | if (magic & 1) { | 39931 | start = pos; |
| 39142 | stop = pos; | 39932 | stop = len; |
| 39143 | } | 39933 | } else { |
| 39144 | if (magic & 2) { | 39934 | if (magic == 1) { |
| 39145 | pos -= v_len; | 39935 | if (pos > len) |
| | 39936 | goto done; |
| | 39937 | } else { |
| | 39938 | pos -= v_len; |
| | 39939 | } |
| 39146 | start = stop = pos; | 39940 | start = stop = pos; |
| 39147 | } | 39941 | } |
| 39148 | ret = 0; | | |
| 39149 | if (start >= 0 && start <= stop) { | 39942 | if (start >= 0 && start <= stop) { |
| 39150 | for (i = start;; i++) { | 39943 | for (i = start;; i++) { |
| 39151 | if (!string_cmp(p, p1, i, 0, v_len)) { | 39944 | if (!string_cmp(p, p1, i, 0, v_len)) { |
| @@ -39156,6 +39949,7 @@ static JSValue js_string_includes(JSContext *ctx, JSValueConst this_val, · 4 unmodified lines |
| 39156 | break; | 39949 | break; |
| 39157 | } | 39950 | } |
| 39158 | } | 39951 | } |
| | 39952 | done: |
| 39159 | JS_FreeValue(ctx, str); | 39953 | JS_FreeValue(ctx, str); |
| 39160 | JS_FreeValue(ctx, v); | 39954 | JS_FreeValue(ctx, v); |
| 39161 | return JS_NewBool(ctx, ret); | 39955 | return JS_NewBool(ctx, ret); |
| @@ -40372,46 +41166,23 @@ static double js_math_round(double a) · 1210 unmodified lines |
| 40372 | static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, | 41166 | static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, |
| 40373 | int argc, JSValueConst *argv) | 41167 | int argc, JSValueConst *argv) |
| 40374 | { | 41168 | { |
| 40375 | double r, a, b; | 41169 | double r, a; |
| 40376 | int i; | 41170 | int i; |
| 40377 | | 41171 | |
| 40378 | if (argc == 2) { | 41172 | r = 0; |
| 40379 | /* use the more precise built-in function when possible */ | 41173 | if (argc > 0) { |
| 40380 | if (JS_ToFloat64(ctx, &a, argv[0])) | 41174 | if (JS_ToFloat64(ctx, &r, argv[0])) |
| 40381 | return JS_EXCEPTION; | | |
| 40382 | if (JS_ToFloat64(ctx, &b, argv[1])) | | |
| 40383 | return JS_EXCEPTION; | | |
| 40384 | r = hypot(a, b); | | |
| 40385 | } else if (argc == 0) { | | |
| 40386 | r = 0; | | |
| 40387 | } else { | | |
| 40388 | double *tab, a_max; | | |
| 40389 | tab = js_malloc(ctx, sizeof(tab[0]) * argc); | | |
| 40390 | if (!tab) | | |
| 40391 | return JS_EXCEPTION; | 41175 | return JS_EXCEPTION; |
| 40392 | /* avoid overflow by taking the maximum */ | 41176 | if (argc == 1) { |
| 40393 | a_max = 0; | 41177 | r = fabs(r); |
| 40394 | for(i = 0; i < argc; i++) { | | |
| 40395 | if (JS_ToFloat64(ctx, &a, argv[i])) { | | |
| 40396 | js_free(ctx, tab); | | |
| 40397 | return JS_EXCEPTION; | | |
| 40398 | } | | |
| 40399 | a = fabs(a); | | |
| 40400 | tab[i] = a; | | |
| 40401 | if (a > a_max) | | |
| 40402 | a_max = a; | | |
| 40403 | } | | |
| 40404 | if (a_max == 0 || !isfinite(a_max)) { | | |
| 40405 | r = a_max; | | |
| 40406 | } else { | 41178 | } else { |
| 40407 | r = 0; | 41179 | /* use the built-in function to minimize precision loss */ |
| 40408 | for(i = 0; i < argc; i++) { | 41180 | for (i = 1; i < argc; i++) { |
| 40409 | a = tab[i] / a_max; | 41181 | if (JS_ToFloat64(ctx, &a, argv[i])) |
| 40410 | r += a * a; | 41182 | return JS_EXCEPTION; |
| | 41183 | r = hypot(r, a); |
| 40411 | } | 41184 | } |
| 40412 | r = a_max * sqrt(r); | | |
| 40413 | } | 41185 | } |
| 40414 | js_free(ctx, tab); | | |
| 40415 | } | 41186 | } |
| 40416 | return JS_NewFloat64(ctx, r); | 41187 | return JS_NewFloat64(ctx, r); |
| 40417 | } | 41188 | } |
| @@ -42093,58 +42864,69 @@ void JS_AddIntrinsicRegExp(JSContext *ctx) · 1675 unmodified lines |
| 42093 | | 42864 | |
| 42094 | /* JSON */ | 42865 | /* JSON */ |
| 42095 | | 42866 | |
| 42096 | /* XXX: this parser is less strict than the JSON standard because we | 42867 | static int json_parse_expect(JSParseState *s, int tok) |
| 42097 | reuse the Javascript tokenizer. It could be improved by adding a | 42868 | { |
| 42098 | specific JSON parse flag. */ | 42869 | if (s->token.val != tok) { |
| | 42870 | /* XXX: dump token correctly in all cases */ |
| | 42871 | return js_parse_error(s, "expecting '%c'", tok); |
| | 42872 | } |
| | 42873 | return json_next_token(s); |
| | 42874 | } |
| | 42875 | |
| 42099 | static JSValue json_parse_value(JSParseState *s) | 42876 | static JSValue json_parse_value(JSParseState *s) |
| 42100 | { | 42877 | { |
| 42101 | JSContext *ctx = s->ctx; | 42878 | JSContext *ctx = s->ctx; |
| 42102 | JSValue val = JS_NULL; | 42879 | JSValue val = JS_NULL; |
| 42103 | BOOL is_neg; | | |
| 42104 | int ret; | 42880 | int ret; |
| 42105 | | 42881 | |
| 42106 | switch(s->token.val) { | 42882 | switch(s->token.val) { |
| 42107 | case '{': | 42883 | case '{': |
| 42108 | { | 42884 | { |
| 42109 | JSValue prop_val, prop_str; | 42885 | JSValue prop_val; |
| 42110 | | 42886 | JSAtom prop_name; |
| 42111 | if (next_token(s)) | 42887 | |
| | 42888 | if (json_next_token(s)) |
| 42112 | goto fail; | 42889 | goto fail; |
| 42113 | val = JS_NewObject(ctx); | 42890 | val = JS_NewObject(ctx); |
| 42114 | if (JS_IsException(val)) | 42891 | if (JS_IsException(val)) |
| 42115 | goto fail; | 42892 | goto fail; |
| 42116 | if (s->token.val != '}') { | 42893 | if (s->token.val != '}') { |
| 42117 | for(;;) { | 42894 | for(;;) { |
| 42118 | if (s->token.val != TOK_STRING) { | 42895 | if (s->token.val == TOK_STRING) { |
| | 42896 | prop_name = JS_ValueToAtom(ctx, s->token.u.str.str); |
| | 42897 | if (prop_name == JS_ATOM_NULL) |
| | 42898 | goto fail; |
| | 42899 | } else if (s->ext_json && s->token.val == TOK_IDENT) { |
| | 42900 | prop_name = JS_DupAtom(ctx, s->token.u.ident.atom); |
| | 42901 | } else { |
| 42119 | js_parse_error(s, "expecting property name"); | 42902 | js_parse_error(s, "expecting property name"); |
| 42120 | goto fail; | 42903 | goto fail; |
| 42121 | } | 42904 | } |
| 42122 | prop_str = JS_DupValue(ctx, s->token.u.str.str); | 42905 | if (json_next_token(s)) |
| 42123 | if (next_token(s)) { | 42906 | goto fail1; |
| 42124 | JS_FreeValue(ctx, prop_str); | 42907 | if (json_parse_expect(s, ':')) |
| 42125 | goto fail; | 42908 | goto fail1; |
| 42126 | } | | |
| 42127 | if (js_parse_expect(s, ':')) { | | |
| 42128 | JS_FreeValue(ctx, prop_str); | | |
| 42129 | goto fail; | | |
| 42130 | } | | |
| 42131 | prop_val = json_parse_value(s); | 42909 | prop_val = json_parse_value(s); |
| 42132 | if (JS_IsException(prop_val)) { | 42910 | if (JS_IsException(prop_val)) { |
| 42133 | JS_FreeValue(ctx, prop_str); | 42911 | fail1: |
| | 42912 | JS_FreeAtom(ctx, prop_name); |
| 42134 | goto fail; | 42913 | goto fail; |
| 42135 | } | 42914 | } |
| 42136 | ret = JS_DefinePropertyValueValue(ctx, val, prop_str, | 42915 | ret = JS_DefinePropertyValue(ctx, val, prop_name, |
| 42137 | prop_val, JS_PROP_C_W_E); | 42916 | prop_val, JS_PROP_C_W_E); |
| | 42917 | JS_FreeAtom(ctx, prop_name); |
| 42138 | if (ret < 0) | 42918 | if (ret < 0) |
| 42139 | goto fail; | 42919 | goto fail; |
| 42140 | | 42920 | |
| 42141 | if (s->token.val != ',') | 42921 | if (s->token.val != ',') |
| 42142 | break; | 42922 | break; |
| 42143 | if (next_token(s)) | 42923 | if (json_next_token(s)) |
| 42144 | goto fail; | 42924 | goto fail; |
| | 42925 | if (s->ext_json && s->token.val == '}') |
| | 42926 | break; |
| 42145 | } | 42927 | } |
| 42146 | } | 42928 | } |
| 42147 | if (js_parse_expect(s, '}')) | 42929 | if (json_parse_expect(s, '}')) |
| 42148 | goto fail; | 42930 | goto fail; |
| 42149 | } | 42931 | } |
| 42150 | break; | 42932 | break; |
| @@ -42153,7 +42935,7 @@ static JSValue json_parse_value(JSParseState *s) · 2 unmodified lines |
| 42153 | JSValue el; | 42935 | JSValue el; |
| 42154 | uint32_t idx; | 42936 | uint32_t idx; |
| 42155 | | 42937 | |
| 42156 | if (next_token(s)) | 42938 | if (json_next_token(s)) |
| 42157 | goto fail; | 42939 | goto fail; |
| 42158 | val = JS_NewArray(ctx); | 42940 | val = JS_NewArray(ctx); |
| 42159 | if (JS_IsException(val)) | 42941 | if (JS_IsException(val)) |
| @@ -42169,52 +42951,41 @@ static JSValue json_parse_value(JSParseState *s) · 9 unmodified lines |
| 42169 | goto fail; | 42951 | goto fail; |
| 42170 | if (s->token.val != ',') | 42952 | if (s->token.val != ',') |
| 42171 | break; | 42953 | break; |
| 42172 | if (next_token(s)) | 42954 | if (json_next_token(s)) |
| 42173 | goto fail; | 42955 | goto fail; |
| 42174 | idx++; | 42956 | idx++; |
| | 42957 | if (s->ext_json && s->token.val == ']') |
| | 42958 | break; |
| 42175 | } | 42959 | } |
| 42176 | } | 42960 | } |
| 42177 | if (js_parse_expect(s, ']')) | 42961 | if (json_parse_expect(s, ']')) |
| 42178 | goto fail; | 42962 | goto fail; |
| 42179 | } | 42963 | } |
| 42180 | break; | 42964 | break; |
| 42181 | case TOK_STRING: | 42965 | case TOK_STRING: |
| 42182 | val = JS_DupValue(ctx, s->token.u.str.str); | 42966 | val = JS_DupValue(ctx, s->token.u.str.str); |
| 42183 | if (next_token(s)) | 42967 | if (json_next_token(s)) |
| 42184 | goto fail; | 42968 | goto fail; |
| 42185 | break; | 42969 | break; |
| 42186 | case TOK_NUMBER: | 42970 | case TOK_NUMBER: |
| 42187 | is_neg = 0; | | |
| 42188 | goto number; | | |
| 42189 | case '-': | | |
| 42190 | if (next_token(s)) | | |
| 42191 | goto fail; | | |
| 42192 | if (s->token.val != TOK_NUMBER) { | | |
| 42193 | js_parse_error(s, "number expected"); | | |
| 42194 | goto fail; | | |
| 42195 | } | | |
| 42196 | is_neg = 1; | | |
| 42197 | number: | | |
| 42198 | val = s->token.u.num.val; | 42971 | val = s->token.u.num.val; |
| 42199 | if (is_neg) { | 42972 | if (json_next_token(s)) |
| 42200 | double d; | | |
| 42201 | JS_ToFloat64(ctx, &d, val); /* no exception possible */ | | |
| 42202 | val = JS_NewFloat64(ctx, -d); | | |
| 42203 | } | | |
| 42204 | if (next_token(s)) | | |
| 42205 | goto fail; | 42973 | goto fail; |
| 42206 | break; | 42974 | break; |
| 42207 | case TOK_FALSE: | 42975 | case TOK_IDENT: |
| 42208 | case TOK_TRUE: | 42976 | if (s->token.u.ident.atom == JS_ATOM_false || |
| 42209 | val = JS_NewBool(ctx, s->token.val - TOK_FALSE); | 42977 | s->token.u.ident.atom == JS_ATOM_true) { |
| 42210 | if (next_token(s)) | 42978 | val = JS_NewBool(ctx, (s->token.u.ident.atom == JS_ATOM_true)); |
| 42211 | goto fail; | 42979 | } else if (s->token.u.ident.atom == JS_ATOM_null) { |
| 42212 | break; | 42980 | val = JS_NULL; |
| 42213 | case TOK_NULL: | 42981 | } else { |
| 42214 | if (next_token(s)) | 42982 | goto def_token; |
| | 42983 | } |
| | 42984 | if (json_next_token(s)) |
| 42215 | goto fail; | 42985 | goto fail; |
| 42216 | break; | 42986 | break; |
| 42217 | default: | 42987 | default: |
| | 42988 | def_token: |
| 42218 | if (s->token.val == TOK_EOF) { | 42989 | if (s->token.val == TOK_EOF) { |
| 42219 | js_parse_error(s, "unexpected end of input"); | 42990 | js_parse_error(s, "unexpected end of input"); |
| 42220 | } else { | 42991 | } else { |
| @@ -42229,15 +43000,15 @@ static JSValue json_parse_value(JSParseState *s) · 8 unmodified lines |
| 42229 | return JS_EXCEPTION; | 43000 | return JS_EXCEPTION; |
| 42230 | } | 43001 | } |
| 42231 | | 43002 | |
| 42232 | JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, | 43003 | JSValue JS_ParseJSON2(JSContext *ctx, const char *buf, size_t buf_len, |
| 42233 | const char *filename) | 43004 | const char *filename, int flags) |
| 42234 | { | 43005 | { |
| 42235 | JSParseState s1, *s = &s1; | 43006 | JSParseState s1, *s = &s1; |
| 42236 | JSValue val; | 43007 | JSValue val = JS_UNDEFINED; |
| 42237 | | 43008 | |
| 42238 | js_parse_init(ctx, s, buf, buf_len, filename); | 43009 | js_parse_init(ctx, s, buf, buf_len, filename); |
| 42239 | | 43010 | s->ext_json = ((flags & JS_PARSE_JSON_EXT) != 0); |
| 42240 | if (next_token(s)) | 43011 | if (json_next_token(s)) |
| 42241 | goto fail; | 43012 | goto fail; |
| 42242 | val = json_parse_value(s); | 43013 | val = json_parse_value(s); |
| 42243 | if (JS_IsException(val)) | 43014 | if (JS_IsException(val)) |
| @@ -42248,10 +43019,17 @@ JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, · 4 unmodified lines |
| 42248 | } | 43019 | } |
| 42249 | return val; | 43020 | return val; |
| 42250 | fail: | 43021 | fail: |
| | 43022 | JS_FreeValue(ctx, val); |
| 42251 | free_token(s, &s->token); | 43023 | free_token(s, &s->token); |
| 42252 | return JS_EXCEPTION; | 43024 | return JS_EXCEPTION; |
| 42253 | } | 43025 | } |
| 42254 | | 43026 | |
| | 43027 | JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, |
| | 43028 | const char *filename) |
| | 43029 | { |
| | 43030 | return JS_ParseJSON2(ctx, buf, buf_len, filename, 0); |
| | 43031 | } |
| | 43032 | |
| 42255 | static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, | 43033 | static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder, |
| 42256 | JSAtom name, JSValueConst reviver) | 43034 | JSAtom name, JSValueConst reviver) |
| 42257 | { | 43035 | { |
| @@ -42960,7 +43738,6 @@ static void js_proxy_finalizer(JSRuntime *rt, JSValue val) · 702 unmodified lines |
| 42960 | if (s) { | 43738 | if (s) { |
| 42961 | JS_FreeValueRT(rt, s->target); | 43739 | JS_FreeValueRT(rt, s->target); |
| 42962 | JS_FreeValueRT(rt, s->handler); | 43740 | JS_FreeValueRT(rt, s->handler); |
| 42963 | JS_FreeValueRT(rt, s->proto); | | |
| 42964 | js_free_rt(rt, s); | 43741 | js_free_rt(rt, s); |
| 42965 | } | 43742 | } |
| 42966 | } | 43743 | } |
| @@ -42972,7 +43749,6 @@ static void js_proxy_mark(JSRuntime *rt, JSValueConst val, · 5 unmodified lines |
| 42972 | if (s) { | 43749 | if (s) { |
| 42973 | JS_MarkValue(rt, s->target, mark_func); | 43750 | JS_MarkValue(rt, s->target, mark_func); |
| 42974 | JS_MarkValue(rt, s->handler, mark_func); | 43751 | JS_MarkValue(rt, s->handler, mark_func); |
| 42975 | JS_MarkValue(rt, s->proto, mark_func); | | |
| 42976 | } | 43752 | } |
| 42977 | } | 43753 | } |
| 42978 | | 43754 | |
| @@ -43007,17 +43783,12 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod, · 28 unmodified lines |
| 43007 | return s; | 43783 | return s; |
| 43008 | } | 43784 | } |
| 43009 | | 43785 | |
| 43010 | static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) | 43786 | static JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) |
| 43011 | { | 43787 | { |
| 43012 | JSProxyData *s; | 43788 | JSProxyData *s; |
| 43013 | JSValue method, ret; | 43789 | JSValue method, ret, proto1; |
| 43014 | JSValueConst proto1; | | |
| 43015 | int res; | 43790 | int res; |
| 43016 | | 43791 | |
| 43017 | /* must check for timeout to avoid infinite loop in instanceof */ | | |
| 43018 | if (js_poll_interrupts(ctx)) | | |
| 43019 | return JS_EXCEPTION; | | |
| 43020 | | | |
| 43021 | s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf); | 43792 | s = get_proxy_method(ctx, &method, obj, JS_ATOM_getPrototypeOf); |
| 43022 | if (!s) | 43793 | if (!s) |
| 43023 | return JS_EXCEPTION; | 43794 | return JS_EXCEPTION; |
| @@ -43043,22 +43814,22 @@ static JSValueConst js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj) · 19 unmodified lines |
| 43043 | return JS_EXCEPTION; | 43814 | return JS_EXCEPTION; |
| 43044 | } | 43815 | } |
| 43045 | if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) { | 43816 | if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) { |
| | 43817 | JS_FreeValue(ctx, proto1); |
| 43046 | fail: | 43818 | fail: |
| 43047 | JS_FreeValue(ctx, ret); | 43819 | JS_FreeValue(ctx, ret); |
| 43048 | return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); | 43820 | return JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); |
| 43049 | } | 43821 | } |
| | 43822 | JS_FreeValue(ctx, proto1); |
| 43050 | } | 43823 | } |
| 43051 | /* store the prototype in the proxy so that its refcount is at least 1 */ | 43824 | return ret; |
| 43052 | set_value(ctx, &s->proto, ret); | | |
| 43053 | return (JSValueConst)ret; | | |
| 43054 | } | 43825 | } |
| 43055 | | 43826 | |
| 43056 | static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, | 43827 | static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, |
| 43057 | JSValueConst proto_val, BOOL throw_flag) | 43828 | JSValueConst proto_val, BOOL throw_flag) |
| 43058 | { | 43829 | { |
| 43059 | JSProxyData *s; | 43830 | JSProxyData *s; |
| 43060 | JSValue method, ret; | 43831 | JSValue method, ret, proto1; |
| 43061 | JSValueConst args[2], proto1; | 43832 | JSValueConst args[2]; |
| 43062 | BOOL res; | 43833 | BOOL res; |
| 43063 | int res2; | 43834 | int res2; |
| 43064 | | 43835 | |
| @@ -43089,9 +43860,11 @@ static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, · 24 unmodified lines |
| 43089 | if (JS_IsException(proto1)) | 43860 | if (JS_IsException(proto1)) |
| 43090 | return -1; | 43861 | return -1; |
| 43091 | if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) { | 43862 | if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) { |
| | 43863 | JS_FreeValue(ctx, proto1); |
| 43092 | JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); | 43864 | JS_ThrowTypeError(ctx, "proxy: inconsistent prototype"); |
| 43093 | return -1; | 43865 | return -1; |
| 43094 | } | 43866 | } |
| | 43867 | JS_FreeValue(ctx, proto1); |
| 43095 | } | 43868 | } |
| 43096 | return TRUE; | 43869 | return TRUE; |
| 43097 | } | 43870 | } |
| @@ -43829,7 +44602,6 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, · 731 unmodified lines |
| 43829 | } | 44602 | } |
| 43830 | s->target = JS_DupValue(ctx, target); | 44603 | s->target = JS_DupValue(ctx, target); |
| 43831 | s->handler = JS_DupValue(ctx, handler); | 44604 | s->handler = JS_DupValue(ctx, handler); |
| 43832 | s->proto = JS_NULL; | | |
| 43833 | s->is_func = JS_IsFunction(ctx, target); | 44605 | s->is_func = JS_IsFunction(ctx, target); |
| 43834 | s->is_revoked = FALSE; | 44606 | s->is_revoked = FALSE; |
| 43835 | JS_SetOpaque(obj, s); | 44607 | JS_SetOpaque(obj, s); |
| @@ -45414,10 +46186,10 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx, · 1578 unmodified lines |
| 45414 | static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, | 46186 | static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, |
| 45415 | int argc, JSValueConst *argv, int magic) | 46187 | int argc, JSValueConst *argv, int magic) |
| 45416 | { | 46188 | { |
| 45417 | JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret; | 46189 | JSValue result_promise, resolving_funcs[2], item, next_promise, ret; |
| 45418 | JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED; | 46190 | JSValue next_method = JS_UNDEFINED, values = JS_UNDEFINED; |
| 45419 | JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element; | 46191 | JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element; |
| 45420 | JSValue promise_resolve = JS_UNDEFINED; | 46192 | JSValue promise_resolve = JS_UNDEFINED, iter = JS_UNDEFINED; |
| 45421 | JSValueConst then_args[2], resolve_element_data[5]; | 46193 | JSValueConst then_args[2], resolve_element_data[5]; |
| 45422 | BOOL done; | 46194 | BOOL done; |
| 45423 | int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); | 46195 | int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any); |
| @@ -45427,6 +46199,10 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 3 unmodified lines |
| 45427 | result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); | 46199 | result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); |
| 45428 | if (JS_IsException(result_promise)) | 46200 | if (JS_IsException(result_promise)) |
| 45429 | return result_promise; | 46201 | return result_promise; |
| | 46202 | promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); |
| | 46203 | if (JS_IsException(promise_resolve) || |
| | 46204 | check_function(ctx, promise_resolve)) |
| | 46205 | goto fail_reject; |
| 45430 | iter = JS_GetIterator(ctx, argv[0], FALSE); | 46206 | iter = JS_GetIterator(ctx, argv[0], FALSE); |
| 45431 | if (JS_IsException(iter)) { | 46207 | if (JS_IsException(iter)) { |
| 45432 | JSValue error; | 46208 | JSValue error; |
| @@ -45454,11 +46230,6 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 21 unmodified lines |
| 45454 | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) | 46230 | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0) |
| 45455 | goto fail_reject; | 46231 | goto fail_reject; |
| 45456 | | 46232 | |
| 45457 | promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); | | |
| 45458 | if (JS_IsException(promise_resolve) || | | |
| 45459 | check_function(ctx, promise_resolve)) | | |
| 45460 | goto fail_reject1; | | |
| 45461 | | | |
| 45462 | index = 0; | 46233 | index = 0; |
| 45463 | for(;;) { | 46234 | for(;;) { |
| 45464 | /* XXX: conformance: should close the iterator if error on 'done' | 46235 | /* XXX: conformance: should close the iterator if error on 'done' |
| @@ -45560,8 +46331,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val, · 95 unmodified lines |
| 45560 | static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, | 46331 | static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, |
| 45561 | int argc, JSValueConst *argv) | 46332 | int argc, JSValueConst *argv) |
| 45562 | { | 46333 | { |
| 45563 | JSValue result_promise, resolving_funcs[2], iter, item, next_promise, ret; | 46334 | JSValue result_promise, resolving_funcs[2], item, next_promise, ret; |
| 45564 | JSValue next_method = JS_UNDEFINED; | 46335 | JSValue next_method = JS_UNDEFINED, iter = JS_UNDEFINED; |
| 45565 | JSValue promise_resolve = JS_UNDEFINED; | 46336 | JSValue promise_resolve = JS_UNDEFINED; |
| 45566 | BOOL done; | 46337 | BOOL done; |
| 45567 | | 46338 | |
| @@ -45570,6 +46341,10 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, · 2 unmodified lines |
| 45570 | result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); | 46341 | result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val); |
| 45571 | if (JS_IsException(result_promise)) | 46342 | if (JS_IsException(result_promise)) |
| 45572 | return result_promise; | 46343 | return result_promise; |
| | 46344 | promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); |
| | 46345 | if (JS_IsException(promise_resolve) || |
| | 46346 | check_function(ctx, promise_resolve)) |
| | 46347 | goto fail_reject; |
| 45573 | iter = JS_GetIterator(ctx, argv[0], FALSE); | 46348 | iter = JS_GetIterator(ctx, argv[0], FALSE); |
| 45574 | if (JS_IsException(iter)) { | 46349 | if (JS_IsException(iter)) { |
| 45575 | JSValue error; | 46350 | JSValue error; |
| @@ -45586,11 +46361,6 @@ static JSValue js_promise_race(JSContext *ctx, JSValueConst this_val, · 10 unmodified lines |
| 45586 | if (JS_IsException(next_method)) | 46361 | if (JS_IsException(next_method)) |
| 45587 | goto fail_reject; | 46362 | goto fail_reject; |
| 45588 | | 46363 | |
| 45589 | promise_resolve = JS_GetProperty(ctx, this_val, JS_ATOM_resolve); | | |
| 45590 | if (JS_IsException(promise_resolve) || | | |
| 45591 | check_function(ctx, promise_resolve)) | | |
| 45592 | goto fail_reject1; | | |
| 45593 | | | |
| 45594 | for(;;) { | 46364 | for(;;) { |
| 45595 | /* XXX: conformance: should close the iterator if error on 'done' | 46365 | /* XXX: conformance: should close the iterator if error on 'done' |
| 45596 | access, but not on 'value' access */ | 46366 | access, but not on 'value' access */ |
| @@ -49385,9 +50155,6 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) · 3788 unmodified lines |
| 49385 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); | 50155 | JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); |
| 49386 | ctx->native_error_proto[i] = proto; | 50156 | ctx->native_error_proto[i] = proto; |
| 49387 | } | 50157 | } |
| 49388 | JS_SetPropertyFunctionList(ctx, ctx->native_error_proto[JS_AGGREGATE_ERROR], | | |
| 49389 | js_aggregate_error_proto_funcs, | | |
| 49390 | countof(js_aggregate_error_proto_funcs)); | | |
| 49391 | | 50158 | |
| 49392 | /* the array prototype is an array */ | 50159 | /* the array prototype is an array */ |
| 49393 | ctx->class_proto[JS_CLASS_ARRAY] = | 50160 | ctx->class_proto[JS_CLASS_ARRAY] = |
| @@ -49621,6 +50388,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, · 227 unmodified lines |
| 49621 | JSFreeArrayBufferDataFunc *free_func, | 50388 | JSFreeArrayBufferDataFunc *free_func, |
| 49622 | void *opaque, BOOL alloc_flag) | 50389 | void *opaque, BOOL alloc_flag) |
| 49623 | { | 50390 | { |
| | 50391 | JSRuntime *rt = ctx->rt; |
| 49624 | JSValue obj; | 50392 | JSValue obj; |
| 49625 | JSArrayBuffer *abuf = NULL; | 50393 | JSArrayBuffer *abuf = NULL; |
| 49626 | | 50394 | |
| @@ -49637,11 +50405,24 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, · 10 unmodified lines |
| 49637 | goto fail; | 50405 | goto fail; |
| 49638 | abuf->byte_length = len; | 50406 | abuf->byte_length = len; |
| 49639 | if (alloc_flag) { | 50407 | if (alloc_flag) { |
| 49640 | /* the allocation must be done after the object creation */ | 50408 | if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER && |
| 49641 | abuf->data = js_mallocz(ctx, max_int(len, 1)); | 50409 | rt->sab_funcs.sab_alloc) { |
| 49642 | if (!abuf->data) | 50410 | abuf->data = rt->sab_funcs.sab_alloc(rt->sab_funcs.sab_opaque, |
| 49643 | goto fail; | 50411 | max_int(len, 1)); |
| | 50412 | if (!abuf->data) |
| | 50413 | goto fail; |
| | 50414 | memset(abuf->data, 0, len); |
| | 50415 | } else { |
| | 50416 | /* the allocation must be done after the object creation */ |
| | 50417 | abuf->data = js_mallocz(ctx, max_int(len, 1)); |
| | 50418 | if (!abuf->data) |
| | 50419 | goto fail; |
| | 50420 | } |
| 49644 | } else { | 50421 | } else { |
| | 50422 | if (class_id == JS_CLASS_SHARED_ARRAY_BUFFER && |
| | 50423 | rt->sab_funcs.sab_dup) { |
| | 50424 | rt->sab_funcs.sab_dup(rt->sab_funcs.sab_opaque, buf); |
| | 50425 | } |
| 49645 | abuf->data = buf; | 50426 | abuf->data = buf; |
| 49646 | } | 50427 | } |
| 49647 | init_list_head(&abuf->array_list); | 50428 | init_list_head(&abuf->array_list); |
| @@ -49731,8 +50512,12 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValue val) · 83 unmodified lines |
| 49731 | array finalizers using it, so abuf->array_list is not | 50512 | array finalizers using it, so abuf->array_list is not |
| 49732 | necessarily empty. */ | 50513 | necessarily empty. */ |
| 49733 | // assert(list_empty(&abuf->array_list)); | 50514 | // assert(list_empty(&abuf->array_list)); |
| 49734 | if (abuf->free_func) | 50515 | if (abuf->shared && rt->sab_funcs.sab_free) { |
| 49735 | abuf->free_func(rt, abuf->opaque, abuf->data); | 50516 | rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data); |
| | 50517 | } else { |
| | 50518 | if (abuf->free_func) |
| | 50519 | abuf->free_func(rt, abuf->opaque, abuf->data); |
| | 50520 | } |
| 49736 | js_free_rt(rt, abuf); | 50521 | js_free_rt(rt, abuf); |
| 49737 | } | 50522 | } |
| 49738 | } | 50523 | } |
| @@ -50208,11 +50993,6 @@ static JSValue js_typed_array___getLength(JSContext *ctx, · 469 unmodified lines |
| 50208 | } | 50993 | } |
| 50209 | #endif | 50994 | #endif |
| 50210 | | 50995 | |
| 50211 | static JSValue js_typed_array_constructor(JSContext *ctx, | | |
| 50212 | JSValueConst this_val, | | |
| 50213 | int argc, JSValueConst *argv, | | |
| 50214 | int classid); | | |
| 50215 | | | |
| 50216 | static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, | 50996 | static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, |
| 50217 | int argc, JSValueConst *argv) | 50997 | int argc, JSValueConst *argv) |
| 50218 | { | 50998 | { |
| @@ -51967,9 +52747,10 @@ typedef enum AtomicsOpEnum { · 1748 unmodified lines |
| 51967 | } AtomicsOpEnum; | 52747 | } AtomicsOpEnum; |
| 51968 | | 52748 | |
| 51969 | static void *js_atomics_get_ptr(JSContext *ctx, | 52749 | static void *js_atomics_get_ptr(JSContext *ctx, |
| | 52750 | JSArrayBuffer **pabuf, |
| 51970 | int *psize_log2, JSClassID *pclass_id, | 52751 | int *psize_log2, JSClassID *pclass_id, |
| 51971 | JSValueConst obj, JSValueConst idx_val, | 52752 | JSValueConst obj, JSValueConst idx_val, |
| 51972 | BOOL is_waitable) | 52753 | int is_waitable) |
| 51973 | { | 52754 | { |
| 51974 | JSObject *p; | 52755 | JSObject *p; |
| 51975 | JSTypedArray *ta; | 52756 | JSTypedArray *ta; |
| @@ -52004,18 +52785,27 @@ static void *js_atomics_get_ptr(JSContext *ctx, · 28 unmodified lines |
| 52004 | ta = p->u.typed_array; | 52785 | ta = p->u.typed_array; |
| 52005 | abuf = ta->buffer->u.array_buffer; | 52786 | abuf = ta->buffer->u.array_buffer; |
| 52006 | if (!abuf->shared) { | 52787 | if (!abuf->shared) { |
| 52007 | JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray"); | 52788 | if (is_waitable == 2) { |
| 52008 | return NULL; | 52789 | JS_ThrowTypeError(ctx, "not a SharedArrayBuffer TypedArray"); |
| | 52790 | return NULL; |
| | 52791 | } |
| | 52792 | if (abuf->detached) { |
| | 52793 | JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| | 52794 | return NULL; |
| | 52795 | } |
| 52009 | } | 52796 | } |
| 52010 | if (JS_ToIndex(ctx, &idx, idx_val)) { | 52797 | if (JS_ToIndex(ctx, &idx, idx_val)) { |
| 52011 | return NULL; | 52798 | return NULL; |
| 52012 | } | 52799 | } |
| | 52800 | /* if the array buffer is detached, p->u.array.count = 0 */ |
| 52013 | if (idx >= p->u.array.count) { | 52801 | if (idx >= p->u.array.count) { |
| 52014 | JS_ThrowRangeError(ctx, "out-of-bound access"); | 52802 | JS_ThrowRangeError(ctx, "out-of-bound access"); |
| 52015 | return NULL; | 52803 | return NULL; |
| 52016 | } | 52804 | } |
| 52017 | size_log2 = typed_array_size_log2(p->class_id); | 52805 | size_log2 = typed_array_size_log2(p->class_id); |
| 52018 | ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); | 52806 | ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); |
| | 52807 | if (pabuf) |
| | 52808 | *pabuf = abuf; |
| 52019 | if (psize_log2) | 52809 | if (psize_log2) |
| 52020 | *psize_log2 = size_log2; | 52810 | *psize_log2 = size_log2; |
| 52021 | if (pclass_id) | 52811 | if (pclass_id) |
| @@ -52036,17 +52826,18 @@ static JSValue js_atomics_op(JSContext *ctx, · 14 unmodified lines |
| 52036 | void *ptr; | 52826 | void *ptr; |
| 52037 | JSValue ret; | 52827 | JSValue ret; |
| 52038 | JSClassID class_id; | 52828 | JSClassID class_id; |
| | 52829 | JSArrayBuffer *abuf; |
| 52039 | | 52830 | |
| 52040 | ptr = js_atomics_get_ptr(ctx, &size_log2, &class_id, | 52831 | ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, &class_id, |
| 52041 | argv[0], argv[1], FALSE); | 52832 | argv[0], argv[1], 0); |
| 52042 | if (!ptr) | 52833 | if (!ptr) |
| 52043 | return JS_EXCEPTION; | 52834 | return JS_EXCEPTION; |
| 52044 | rep_val = 0; | 52835 | rep_val = 0; |
| 52045 | if (op == ATOMICS_OP_LOAD) { | 52836 | if (op == ATOMICS_OP_LOAD) { |
| 52046 | v = 0; | 52837 | v = 0; |
| 52047 | } else | 52838 | } else { |
| 52048 | #ifdef CONFIG_BIGNUM | 52839 | #ifdef CONFIG_BIGNUM |
| 52049 | if (size_log2 == 3) { | 52840 | if (size_log2 == 3) { |
| 52050 | int64_t v64; | 52841 | int64_t v64; |
| 52051 | if (JS_ToBigInt64(ctx, &v64, argv[2])) | 52842 | if (JS_ToBigInt64(ctx, &v64, argv[2])) |
| 52052 | return JS_EXCEPTION; | 52843 | return JS_EXCEPTION; |
| @@ -52056,19 +52847,23 @@ static JSValue js_atomics_op(JSContext *ctx, · 3 unmodified lines |
| 52056 | return JS_EXCEPTION; | 52847 | return JS_EXCEPTION; |
| 52057 | rep_val = v64; | 52848 | rep_val = v64; |
| 52058 | } | 52849 | } |
| 52059 | } else | 52850 | } else |
| 52060 | #endif | 52851 | #endif |
| 52061 | { | 52852 | { |
| 52062 | uint32_t v32; | 52853 | uint32_t v32; |
| 52063 | if (JS_ToUint32(ctx, &v32, argv[2])) | 52854 | if (JS_ToUint32(ctx, &v32, argv[2])) |
| 52064 | return JS_EXCEPTION; | 52855 | return JS_EXCEPTION; |
| 52065 | v = v32; | 52856 | v = v32; |
| 52066 | if (op == ATOMICS_OP_COMPARE_EXCHANGE) { | 52857 | if (op == ATOMICS_OP_COMPARE_EXCHANGE) { |
| 52067 | if (JS_ToUint32(ctx, &v32, argv[3])) | 52858 | if (JS_ToUint32(ctx, &v32, argv[3])) |
| 52068 | return JS_EXCEPTION; | 52859 | return JS_EXCEPTION; |
| 52069 | rep_val = v32; | 52860 | rep_val = v32; |
| 52070 | } | 52861 | } |
| | 52862 | } |
| | 52863 | if (abuf->detached) |
| | 52864 | return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| 52071 | } | 52865 | } |
| | 52866 | |
| 52072 | switch(op | (size_log2 << 3)) { | 52867 | switch(op | (size_log2 << 3)) { |
| 52073 | | 52868 | |
| 52074 | #ifdef CONFIG_BIGNUM | 52869 | #ifdef CONFIG_BIGNUM |
| @@ -52195,8 +52990,10 @@ static JSValue js_atomics_store(JSContext *ctx, · 120 unmodified lines |
| 52195 | int size_log2; | 52990 | int size_log2; |
| 52196 | void *ptr; | 52991 | void *ptr; |
| 52197 | JSValue ret; | 52992 | JSValue ret; |
| | 52993 | JSArrayBuffer *abuf; |
| 52198 | | 52994 | |
| 52199 | ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], FALSE); | 52995 | ptr = js_atomics_get_ptr(ctx, &abuf, &size_log2, NULL, |
| | 52996 | argv[0], argv[1], 0); |
| 52200 | if (!ptr) | 52997 | if (!ptr) |
| 52201 | return JS_EXCEPTION; | 52998 | return JS_EXCEPTION; |
| 52202 | #ifdef CONFIG_BIGNUM | 52999 | #ifdef CONFIG_BIGNUM |
| @@ -52209,6 +53006,8 @@ static JSValue js_atomics_store(JSContext *ctx, · 6 unmodified lines |
| 52209 | JS_FreeValue(ctx, ret); | 53006 | JS_FreeValue(ctx, ret); |
| 52210 | return JS_EXCEPTION; | 53007 | return JS_EXCEPTION; |
| 52211 | } | 53008 | } |
| | 53009 | if (abuf->detached) |
| | 53010 | return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| 52212 | atomic_store((_Atomic(uint64_t) *)ptr, v64); | 53011 | atomic_store((_Atomic(uint64_t) *)ptr, v64); |
| 52213 | } else | 53012 | } else |
| 52214 | #endif | 53013 | #endif |
| @@ -52222,6 +53021,8 @@ static JSValue js_atomics_store(JSContext *ctx, · 7 unmodified lines |
| 52222 | JS_FreeValue(ctx, ret); | 53021 | JS_FreeValue(ctx, ret); |
| 52223 | return JS_EXCEPTION; | 53022 | return JS_EXCEPTION; |
| 52224 | } | 53023 | } |
| | 53024 | if (abuf->detached) |
| | 53025 | return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| 52225 | switch(size_log2) { | 53026 | switch(size_log2) { |
| 52226 | case 0: | 53027 | case 0: |
| 52227 | atomic_store((_Atomic(uint8_t) *)ptr, v); | 53028 | atomic_store((_Atomic(uint8_t) *)ptr, v); |
| @@ -52278,7 +53079,8 @@ static JSValue js_atomics_wait(JSContext *ctx, · 50 unmodified lines |
| 52278 | int ret, size_log2, res; | 53079 | int ret, size_log2, res; |
| 52279 | double d; | 53080 | double d; |
| 52280 | | 53081 | |
| 52281 | ptr = js_atomics_get_ptr(ctx, &size_log2, NULL, argv[0], argv[1], TRUE); | 53082 | ptr = js_atomics_get_ptr(ctx, NULL, &size_log2, NULL, |
| | 53083 | argv[0], argv[1], 2); |
| 52282 | if (!ptr) | 53084 | if (!ptr) |
| 52283 | return JS_EXCEPTION; | 53085 | return JS_EXCEPTION; |
| 52284 | #ifdef CONFIG_BIGNUM | 53086 | #ifdef CONFIG_BIGNUM |
| @@ -52357,8 +53159,9 @@ static JSValue js_atomics_notify(JSContext *ctx, · 72 unmodified lines |
| 52357 | int32_t count, n; | 53159 | int32_t count, n; |
| 52358 | void *ptr; | 53160 | void *ptr; |
| 52359 | JSAtomicsWaiter *waiter; | 53161 | JSAtomicsWaiter *waiter; |
| | 53162 | JSArrayBuffer *abuf; |
| 52360 | | 53163 | |
| 52361 | ptr = js_atomics_get_ptr(ctx, NULL, NULL, argv[0], argv[1], TRUE); | 53164 | ptr = js_atomics_get_ptr(ctx, &abuf, NULL, NULL, argv[0], argv[1], 1); |
| 52362 | if (!ptr) | 53165 | if (!ptr) |
| 52363 | return JS_EXCEPTION; | 53166 | return JS_EXCEPTION; |
| 52364 | | 53167 | |
| @@ -52368,9 +53171,11 @@ static JSValue js_atomics_notify(JSContext *ctx, · 3 unmodified lines |
| 52368 | if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0)) | 53171 | if (JS_ToInt32Clamp(ctx, &count, argv[2], 0, INT32_MAX, 0)) |
| 52369 | return JS_EXCEPTION; | 53172 | return JS_EXCEPTION; |
| 52370 | } | 53173 | } |
| | 53174 | if (abuf->detached) |
| | 53175 | return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); |
| 52371 | | 53176 | |
| 52372 | n = 0; | 53177 | n = 0; |
| 52373 | if (count > 0) { | 53178 | if (abuf->shared && count > 0) { |
| 52374 | pthread_mutex_lock(&js_atomics_mutex); | 53179 | pthread_mutex_lock(&js_atomics_mutex); |
| 52375 | init_list_head(&waiter_list); | 53180 | init_list_head(&waiter_list); |
| 52376 | list_for_each_safe(el, el1, &js_atomics_waiter_list) { | 53181 | list_for_each_safe(el, el1, &js_atomics_waiter_list) { |