quickjs 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -103,6 +103,7 @@
103
103
  //#define DUMP_ATOMS /* dump atoms in JS_FreeContext */
104
104
  //#define DUMP_SHAPES /* dump shapes in JS_FreeContext */
105
105
  //#define DUMP_MODULE_RESOLVE
106
+ //#define DUMP_MODULE_EXEC
106
107
  //#define DUMP_PROMISE
107
108
  //#define DUMP_READ_OBJECT
108
109
  //#define DUMP_ROPE_REBALANCE
@@ -147,6 +148,7 @@ enum {
147
148
  JS_CLASS_UINT32_ARRAY, /* u.array (typed_array) */
148
149
  JS_CLASS_BIG_INT64_ARRAY, /* u.array (typed_array) */
149
150
  JS_CLASS_BIG_UINT64_ARRAY, /* u.array (typed_array) */
151
+ JS_CLASS_FLOAT16_ARRAY, /* u.array (typed_array) */
150
152
  JS_CLASS_FLOAT32_ARRAY, /* u.array (typed_array) */
151
153
  JS_CLASS_FLOAT64_ARRAY, /* u.array (typed_array) */
152
154
  JS_CLASS_DATAVIEW, /* u.typed_array */
@@ -263,6 +265,8 @@ struct JSRuntime {
263
265
  uintptr_t stack_limit; /* lower stack limit */
264
266
 
265
267
  JSValue current_exception;
268
+ /* true if the current exception cannot be catched */
269
+ BOOL current_exception_is_uncatchable : 8;
266
270
  /* true if inside an out of memory error, to avoid recursing */
267
271
  BOOL in_out_of_memory : 8;
268
272
 
@@ -277,7 +281,12 @@ struct JSRuntime {
277
281
  struct list_head job_list; /* list of JSJobEntry.link */
278
282
 
279
283
  JSModuleNormalizeFunc *module_normalize_func;
280
- JSModuleLoaderFunc *module_loader_func;
284
+ BOOL module_loader_has_attr;
285
+ union {
286
+ JSModuleLoaderFunc *module_loader_func;
287
+ JSModuleLoaderFunc2 *module_loader_func2;
288
+ } u;
289
+ JSModuleCheckSupportedImportAttributes *module_check_attrs;
281
290
  void *module_loader_opaque;
282
291
  /* timestamp for internal use in module evaluation */
283
292
  int64_t module_async_evaluation_next_timestamp;
@@ -332,6 +341,7 @@ typedef enum {
332
341
  JS_GC_OBJ_TYPE_VAR_REF,
333
342
  JS_GC_OBJ_TYPE_ASYNC_FUNCTION,
334
343
  JS_GC_OBJ_TYPE_JS_CONTEXT,
344
+ JS_GC_OBJ_TYPE_MODULE,
335
345
  } JSGCObjectTypeEnum;
336
346
 
337
347
  /* header for GC objects. GC objects are C data structures with a
@@ -753,6 +763,7 @@ typedef struct {
753
763
  typedef struct JSReqModuleEntry {
754
764
  JSAtom module_name;
755
765
  JSModuleDef *module; /* used using resolution */
766
+ JSValue attributes; /* JS_UNDEFINED or an object contains the attributes as key/value */
756
767
  } JSReqModuleEntry;
757
768
 
758
769
  typedef enum JSExportTypeEnum {
@@ -780,6 +791,7 @@ typedef struct JSStarExportEntry {
780
791
 
781
792
  typedef struct JSImportEntry {
782
793
  int var_idx; /* closure variable index */
794
+ BOOL is_star; /* import_name = '*' is a valid import name, so need a flag */
783
795
  JSAtom import_name;
784
796
  int req_module_idx; /* in req_module_entries */
785
797
  } JSImportEntry;
@@ -794,7 +806,7 @@ typedef enum {
794
806
  } JSModuleStatus;
795
807
 
796
808
  struct JSModuleDef {
797
- JSRefCountHeader header; /* must come first, 32-bit */
809
+ JSGCObjectHeader header; /* must come first */
798
810
  JSAtom module_name;
799
811
  struct list_head link;
800
812
 
@@ -829,7 +841,8 @@ struct JSModuleDef {
829
841
  int async_parent_modules_count;
830
842
  int async_parent_modules_size;
831
843
  int pending_async_dependencies;
832
- BOOL async_evaluation;
844
+ BOOL async_evaluation; /* true: async_evaluation_timestamp corresponds to [[AsyncEvaluationOrder]]
845
+ false: [[AsyncEvaluationOrder]] is UNSET or DONE */
833
846
  int64_t async_evaluation_timestamp;
834
847
  JSModuleDef *cycle_root;
835
848
  JSValue promise; /* corresponds to spec field: capability */
@@ -840,11 +853,12 @@ struct JSModuleDef {
840
853
  BOOL eval_has_exception : 8;
841
854
  JSValue eval_exception;
842
855
  JSValue meta_obj; /* for import.meta */
856
+ JSValue private_value; /* private value for C modules */
843
857
  };
844
858
 
845
859
  typedef struct JSJobEntry {
846
860
  struct list_head link;
847
- JSContext *ctx;
861
+ JSContext *realm;
848
862
  JSJobFunc *job_func;
849
863
  int argc;
850
864
  JSValue argv[0];
@@ -911,7 +925,7 @@ struct JSObject {
911
925
  uint8_t is_exotic : 1; /* TRUE if object has exotic property handlers */
912
926
  uint8_t fast_array : 1; /* TRUE if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS and typed arrays) */
913
927
  uint8_t is_constructor : 1; /* TRUE if object is a constructor function */
914
- uint8_t is_uncatchable_error : 1; /* if TRUE, error is not catchable */
928
+ uint8_t has_immutable_prototype : 1; /* cannot modify the prototype */
915
929
  uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */
916
930
  uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */
917
931
  uint16_t class_id; /* see JS_CLASS_x */
@@ -971,6 +985,7 @@ struct JSObject {
971
985
  uint32_t *uint32_ptr; /* JS_CLASS_UINT32_ARRAY */
972
986
  int64_t *int64_ptr; /* JS_CLASS_INT64_ARRAY */
973
987
  uint64_t *uint64_ptr; /* JS_CLASS_UINT64_ARRAY */
988
+ uint16_t *fp16_ptr; /* JS_CLASS_FLOAT16_ARRAY */
974
989
  float *float_ptr; /* JS_CLASS_FLOAT32_ARRAY */
975
990
  double *double_ptr; /* JS_CLASS_FLOAT64_ARRAY */
976
991
  } u;
@@ -981,6 +996,27 @@ struct JSObject {
981
996
  } u;
982
997
  };
983
998
 
999
+ typedef struct JSMapRecord {
1000
+ int ref_count; /* used during enumeration to avoid freeing the record */
1001
+ BOOL empty : 8; /* TRUE if the record is deleted */
1002
+ struct list_head link;
1003
+ struct JSMapRecord *hash_next;
1004
+ JSValue key;
1005
+ JSValue value;
1006
+ } JSMapRecord;
1007
+
1008
+ typedef struct JSMapState {
1009
+ BOOL is_weak; /* TRUE if WeakSet/WeakMap */
1010
+ struct list_head records; /* list of JSMapRecord.link */
1011
+ uint32_t record_count;
1012
+ JSMapRecord **hash_table;
1013
+ int hash_bits;
1014
+ uint32_t hash_size; /* = 2 ^ hash_bits */
1015
+ uint32_t record_count_threshold; /* count at which a hash table
1016
+ resize is needed */
1017
+ JSWeakRefHeader weakref_header; /* only used if is_weak = TRUE */
1018
+ } JSMapState;
1019
+
984
1020
  enum {
985
1021
  __JS_ATOM_NULL = JS_ATOM_NULL,
986
1022
  #define DEF(name, str) JS_ATOM_ ## name,
@@ -1059,12 +1095,10 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p);
1059
1095
  static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt);
1060
1096
  static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
1061
1097
  static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p);
1062
- static __maybe_unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val);
1063
- static __maybe_unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
1064
- static __maybe_unused void JS_PrintValue(JSContext *ctx,
1065
- const char *str,
1066
- JSValueConst val);
1098
+ static __maybe_unused void JS_DumpValueRT(JSRuntime *rt, const char *str, JSValueConst val);
1099
+ static __maybe_unused void JS_DumpValue(JSContext *ctx, const char *str, JSValueConst val);
1067
1100
  static __maybe_unused void JS_DumpShapes(JSRuntime *rt);
1101
+ static void js_dump_value_write(void *opaque, const char *buf, size_t len);
1068
1102
  static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
1069
1103
  int argc, JSValueConst *argv, int magic);
1070
1104
  static void js_array_finalizer(JSRuntime *rt, JSValue val);
@@ -1189,11 +1223,11 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
1189
1223
  static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
1190
1224
  const char *input, size_t input_len,
1191
1225
  const char *filename, int flags, int scope_idx);
1192
- static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
1226
+ static void js_free_module_def(JSRuntime *rt, JSModuleDef *m);
1193
1227
  static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
1194
1228
  JS_MarkFunc *mark_func);
1195
1229
  static JSValue js_import_meta(JSContext *ctx);
1196
- static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier);
1230
+ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options);
1197
1231
  static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
1198
1232
  static JSValue js_new_promise_capability(JSContext *ctx,
1199
1233
  JSValue *resolving_funcs,
@@ -1257,6 +1291,13 @@ static void finrec_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh);
1257
1291
  static void JS_RunGCInternal(JSRuntime *rt, BOOL remove_weak_objects);
1258
1292
  static JSValue js_array_from_iterator(JSContext *ctx, uint32_t *plen,
1259
1293
  JSValueConst obj, JSValueConst method);
1294
+ static int js_string_find_invalid_codepoint(JSString *p);
1295
+ static JSValue js_regexp_toString(JSContext *ctx, JSValueConst this_val,
1296
+ int argc, JSValueConst *argv);
1297
+ static JSValue get_date_string(JSContext *ctx, JSValueConst this_val,
1298
+ int argc, JSValueConst *argv, int magic);
1299
+ static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val,
1300
+ int argc, JSValueConst *argv);
1260
1301
 
1261
1302
  static const JSClassExoticMethods js_arguments_exotic_methods;
1262
1303
  static const JSClassExoticMethods js_string_exotic_methods;
@@ -1429,6 +1470,23 @@ static inline void js_dbuf_init(JSContext *ctx, DynBuf *s)
1429
1470
  dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
1430
1471
  }
1431
1472
 
1473
+ static void *js_realloc_bytecode_rt(void *opaque, void *ptr, size_t size)
1474
+ {
1475
+ JSRuntime *rt = opaque;
1476
+ if (size > (INT32_MAX / 2)) {
1477
+ /* the bytecode cannot be larger than 2G. Leave some slack to
1478
+ avoid some overflows. */
1479
+ return NULL;
1480
+ } else {
1481
+ return rt->mf.js_realloc(&rt->malloc_state, ptr, size);
1482
+ }
1483
+ }
1484
+
1485
+ static inline void js_dbuf_bytecode_init(JSContext *ctx, DynBuf *s)
1486
+ {
1487
+ dbuf_init2(s, ctx->rt, js_realloc_bytecode_rt);
1488
+ }
1489
+
1432
1490
  static inline int is_digit(int c) {
1433
1491
  return c >= '0' && c <= '9';
1434
1492
  }
@@ -1473,6 +1531,7 @@ static JSClassShortDef const js_std_class_def[] = {
1473
1531
  { JS_ATOM_Uint32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_UINT32_ARRAY */
1474
1532
  { JS_ATOM_BigInt64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_INT64_ARRAY */
1475
1533
  { JS_ATOM_BigUint64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_BIG_UINT64_ARRAY */
1534
+ { JS_ATOM_Float16Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT16_ARRAY */
1476
1535
  { JS_ATOM_Float32Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT32_ARRAY */
1477
1536
  { JS_ATOM_Float64Array, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_FLOAT64_ARRAY */
1478
1537
  { JS_ATOM_DataView, js_typed_array_finalizer, js_typed_array_mark }, /* JS_CLASS_DATAVIEW */
@@ -1741,7 +1800,7 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
1741
1800
  e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));
1742
1801
  if (!e)
1743
1802
  return -1;
1744
- e->ctx = ctx;
1803
+ e->realm = JS_DupContext(ctx);
1745
1804
  e->job_func = job_func;
1746
1805
  e->argc = argc;
1747
1806
  for(i = 0; i < argc; i++) {
@@ -1757,7 +1816,10 @@ BOOL JS_IsJobPending(JSRuntime *rt)
1757
1816
  }
1758
1817
 
1759
1818
  /* return < 0 if exception, 0 if no job pending, 1 if a job was
1760
- executed successfully. the context of the job is stored in '*pctx' */
1819
+ executed successfully. The context of the job is stored in '*pctx'
1820
+ if pctx != NULL. It may be NULL if the context was already
1821
+ destroyed or if no job was pending. The 'pctx' parameter is now
1822
+ absolete. */
1761
1823
  int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
1762
1824
  {
1763
1825
  JSContext *ctx;
@@ -1766,15 +1828,16 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
1766
1828
  int i, ret;
1767
1829
 
1768
1830
  if (list_empty(&rt->job_list)) {
1769
- *pctx = NULL;
1831
+ if (pctx)
1832
+ *pctx = NULL;
1770
1833
  return 0;
1771
1834
  }
1772
1835
 
1773
1836
  /* get the first pending job and execute it */
1774
1837
  e = list_entry(rt->job_list.next, JSJobEntry, link);
1775
1838
  list_del(&e->link);
1776
- ctx = e->ctx;
1777
- res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv);
1839
+ ctx = e->realm;
1840
+ res = e->job_func(ctx, e->argc, (JSValueConst *)e->argv);
1778
1841
  for(i = 0; i < e->argc; i++)
1779
1842
  JS_FreeValue(ctx, e->argv[i]);
1780
1843
  if (JS_IsException(res))
@@ -1783,7 +1846,13 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
1783
1846
  ret = 1;
1784
1847
  JS_FreeValue(ctx, res);
1785
1848
  js_free(ctx, e);
1786
- *pctx = ctx;
1849
+ if (pctx) {
1850
+ if (ctx->header.ref_count > 1)
1851
+ *pctx = ctx;
1852
+ else
1853
+ *pctx = NULL;
1854
+ }
1855
+ JS_FreeContext(ctx);
1787
1856
  return ret;
1788
1857
  }
1789
1858
 
@@ -1864,6 +1933,7 @@ void JS_FreeRuntime(JSRuntime *rt)
1864
1933
  JSJobEntry *e = list_entry(el, JSJobEntry, link);
1865
1934
  for(i = 0; i < e->argc; i++)
1866
1935
  JS_FreeValueRT(rt, e->argv[i]);
1936
+ JS_FreeContext(e->realm);
1867
1937
  js_free_rt(rt, e);
1868
1938
  }
1869
1939
  init_list_head(&rt->job_list);
@@ -2139,7 +2209,13 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
2139
2209
  JSModuleDef *m = list_entry(el, JSModuleDef, link);
2140
2210
  if (flag == JS_FREE_MODULE_ALL ||
2141
2211
  (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) {
2142
- js_free_module_def(ctx, m);
2212
+ /* warning: the module may be referenced elsewhere. It
2213
+ could be simpler to use an array instead of a list for
2214
+ 'ctx->loaded_modules' */
2215
+ list_del(&m->link);
2216
+ m->link.prev = NULL;
2217
+ m->link.next = NULL;
2218
+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
2143
2219
  }
2144
2220
  }
2145
2221
  }
@@ -2157,11 +2233,9 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,
2157
2233
  int i;
2158
2234
  struct list_head *el;
2159
2235
 
2160
- /* modules are not seen by the GC, so we directly mark the objects
2161
- referenced by each module */
2162
2236
  list_for_each(el, &ctx->loaded_modules) {
2163
2237
  JSModuleDef *m = list_entry(el, JSModuleDef, link);
2164
- js_mark_module_def(rt, m, mark_func);
2238
+ JS_MarkValue(rt, JS_MKPTR(JS_TAG_MODULE, m), mark_func);
2165
2239
  }
2166
2240
 
2167
2241
  JS_MarkValue(rt, ctx->global_obj, mark_func);
@@ -2401,18 +2475,18 @@ static uint32_t hash_string_rope(JSValueConst val, uint32_t h)
2401
2475
  }
2402
2476
  }
2403
2477
 
2404
- static __maybe_unused void JS_DumpChar(JSRuntime *rt, int c, int sep)
2478
+ static __maybe_unused void JS_DumpChar(FILE *fo, int c, int sep)
2405
2479
  {
2406
2480
  if (c == sep || c == '\\') {
2407
- putchar('\\');
2408
- putchar(c);
2481
+ fputc('\\', fo);
2482
+ fputc(c, fo);
2409
2483
  } else if (c >= ' ' && c <= 126) {
2410
- putchar(c);
2484
+ fputc(c, fo);
2411
2485
  } else if (c == '\n') {
2412
- putchar('\\');
2413
- putchar('n');
2486
+ fputc('\\', fo);
2487
+ fputc('n', fo);
2414
2488
  } else {
2415
- printf("\\u%04x", c);
2489
+ fprintf(fo, "\\u%04x", c);
2416
2490
  }
2417
2491
  }
2418
2492
 
@@ -2428,7 +2502,7 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt, const JSString *p)
2428
2502
  sep = (p->header.ref_count == 1) ? '\"' : '\'';
2429
2503
  putchar(sep);
2430
2504
  for(i = 0; i < p->len; i++) {
2431
- JS_DumpChar(rt, string_get(p, i), sep);
2505
+ JS_DumpChar(stdout, string_get(p, i), sep);
2432
2506
  }
2433
2507
  putchar(sep);
2434
2508
  }
@@ -3172,54 +3246,19 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
3172
3246
  !(p->len == 0 && p->is_wide_char != 0));
3173
3247
  }
3174
3248
 
3175
- static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
3176
- {
3177
- char buf[ATOM_GET_STR_BUF_SIZE];
3178
- const char *p;
3179
- int i;
3180
-
3181
- /* XXX: should handle embedded null characters */
3182
- /* XXX: should move encoding code to JS_AtomGetStr */
3183
- p = JS_AtomGetStr(ctx, buf, sizeof(buf), atom);
3184
- for (i = 0; p[i]; i++) {
3185
- int c = (unsigned char)p[i];
3186
- if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
3187
- (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0)))
3188
- break;
3189
- }
3190
- if (i > 0 && p[i] == '\0') {
3191
- printf("%s", p);
3192
- } else {
3193
- putchar('"');
3194
- printf("%.*s", i, p);
3195
- for (; p[i]; i++) {
3196
- int c = (unsigned char)p[i];
3197
- if (c == '\"' || c == '\\') {
3198
- putchar('\\');
3199
- putchar(c);
3200
- } else if (c >= ' ' && c <= 126) {
3201
- putchar(c);
3202
- } else if (c == '\n') {
3203
- putchar('\\');
3204
- putchar('n');
3205
- } else {
3206
- printf("\\u%04x", c);
3207
- }
3208
- }
3209
- putchar('\"');
3210
- }
3211
- }
3212
-
3213
3249
  /* free with JS_FreeCString() */
3214
- const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)
3250
+ const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom)
3215
3251
  {
3216
3252
  JSValue str;
3217
3253
  const char *cstr;
3218
3254
 
3219
3255
  str = JS_AtomToString(ctx, atom);
3220
- if (JS_IsException(str))
3256
+ if (JS_IsException(str)) {
3257
+ if (plen)
3258
+ *plen = 0;
3221
3259
  return NULL;
3222
- cstr = JS_ToCString(ctx, str);
3260
+ }
3261
+ cstr = JS_ToCStringLen(ctx, plen, str);
3223
3262
  JS_FreeValue(ctx, str);
3224
3263
  return cstr;
3225
3264
  }
@@ -5050,7 +5089,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
5050
5089
  p->is_exotic = 0;
5051
5090
  p->fast_array = 0;
5052
5091
  p->is_constructor = 0;
5053
- p->is_uncatchable_error = 0;
5092
+ p->has_immutable_prototype = 0;
5054
5093
  p->tmp_mark = 0;
5055
5094
  p->is_HTMLDDA = 0;
5056
5095
  p->weakref_count = 0;
@@ -5100,6 +5139,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
5100
5139
  case JS_CLASS_UINT32_ARRAY:
5101
5140
  case JS_CLASS_BIG_INT64_ARRAY:
5102
5141
  case JS_CLASS_BIG_UINT64_ARRAY:
5142
+ case JS_CLASS_FLOAT16_ARRAY:
5103
5143
  case JS_CLASS_FLOAT32_ARRAY:
5104
5144
  case JS_CLASS_FLOAT64_ARRAY:
5105
5145
  p->is_exotic = 1;
@@ -5347,6 +5387,10 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
5347
5387
  if (!name)
5348
5388
  name = "";
5349
5389
  name_atom = JS_NewAtom(ctx, name);
5390
+ if (name_atom == JS_ATOM_NULL) {
5391
+ JS_FreeValue(ctx, func_obj);
5392
+ return JS_EXCEPTION;
5393
+ }
5350
5394
  js_function_set_properties(ctx, func_obj, name_atom, length);
5351
5395
  JS_FreeAtom(ctx, name_atom);
5352
5396
  return func_obj;
@@ -5772,6 +5816,9 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
5772
5816
  case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
5773
5817
  __async_func_free(rt, (JSAsyncFunctionState *)gp);
5774
5818
  break;
5819
+ case JS_GC_OBJ_TYPE_MODULE:
5820
+ js_free_module_def(rt, (JSModuleDef *)gp);
5821
+ break;
5775
5822
  default:
5776
5823
  abort();
5777
5824
  }
@@ -5836,6 +5883,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
5836
5883
  break;
5837
5884
  case JS_TAG_OBJECT:
5838
5885
  case JS_TAG_FUNCTION_BYTECODE:
5886
+ case JS_TAG_MODULE:
5839
5887
  {
5840
5888
  JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);
5841
5889
  if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
@@ -5848,9 +5896,6 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
5848
5896
  }
5849
5897
  }
5850
5898
  break;
5851
- case JS_TAG_MODULE:
5852
- abort(); /* never freed here */
5853
- break;
5854
5899
  case JS_TAG_BIG_INT:
5855
5900
  {
5856
5901
  JSBigInt *p = JS_VALUE_GET_PTR(v);
@@ -5924,6 +5969,7 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
5924
5969
  switch(JS_VALUE_GET_TAG(val)) {
5925
5970
  case JS_TAG_OBJECT:
5926
5971
  case JS_TAG_FUNCTION_BYTECODE:
5972
+ case JS_TAG_MODULE:
5927
5973
  mark_func(rt, JS_VALUE_GET_PTR(val));
5928
5974
  break;
5929
5975
  default:
@@ -6036,6 +6082,12 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
6036
6082
  JS_MarkContext(rt, ctx, mark_func);
6037
6083
  }
6038
6084
  break;
6085
+ case JS_GC_OBJ_TYPE_MODULE:
6086
+ {
6087
+ JSModuleDef *m = (JSModuleDef *)gp;
6088
+ js_mark_module_def(rt, m, mark_func);
6089
+ }
6090
+ break;
6039
6091
  default:
6040
6092
  abort();
6041
6093
  }
@@ -6132,6 +6184,7 @@ static void gc_free_cycles(JSRuntime *rt)
6132
6184
  case JS_GC_OBJ_TYPE_JS_OBJECT:
6133
6185
  case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
6134
6186
  case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
6187
+ case JS_GC_OBJ_TYPE_MODULE:
6135
6188
  #ifdef DUMP_GC_FREE
6136
6189
  if (!header_done) {
6137
6190
  printf("Freeing cycles:\n");
@@ -6154,7 +6207,8 @@ static void gc_free_cycles(JSRuntime *rt)
6154
6207
  p = list_entry(el, JSGCObjectHeader, link);
6155
6208
  assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
6156
6209
  p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
6157
- p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
6210
+ p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION ||
6211
+ p->gc_obj_type == JS_GC_OBJ_TYPE_MODULE);
6158
6212
  if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT &&
6159
6213
  ((JSObject *)p)->weakref_count != 0) {
6160
6214
  /* keep the object because there are weak references to it */
@@ -6491,6 +6545,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s)
6491
6545
  case JS_CLASS_UINT32_ARRAY: /* u.typed_array / u.array */
6492
6546
  case JS_CLASS_BIG_INT64_ARRAY: /* u.typed_array / u.array */
6493
6547
  case JS_CLASS_BIG_UINT64_ARRAY: /* u.typed_array / u.array */
6548
+ case JS_CLASS_FLOAT16_ARRAY: /* u.typed_array / u.array */
6494
6549
  case JS_CLASS_FLOAT32_ARRAY: /* u.typed_array / u.array */
6495
6550
  case JS_CLASS_FLOAT64_ARRAY: /* u.typed_array / u.array */
6496
6551
  case JS_CLASS_DATAVIEW: /* u.typed_array */
@@ -6697,6 +6752,7 @@ JSValue JS_Throw(JSContext *ctx, JSValue obj)
6697
6752
  JSRuntime *rt = ctx->rt;
6698
6753
  JS_FreeValue(ctx, rt->current_exception);
6699
6754
  rt->current_exception = obj;
6755
+ rt->current_exception_is_uncatchable = FALSE;
6700
6756
  return JS_EXCEPTION;
6701
6757
  }
6702
6758
 
@@ -6838,20 +6894,30 @@ static int find_line_num(JSContext *ctx, JSFunctionBytecode *b,
6838
6894
  return 0;
6839
6895
  }
6840
6896
 
6841
- /* in order to avoid executing arbitrary code during the stack trace
6842
- generation, we only look at simple 'name' properties containing a
6843
- string. */
6844
- static const char *get_func_name(JSContext *ctx, JSValueConst func)
6897
+ /* return a string property without executing arbitrary JS code (used
6898
+ when dumping the stack trace or in debug print). */
6899
+ static const char *get_prop_string(JSContext *ctx, JSValueConst obj, JSAtom prop)
6845
6900
  {
6901
+ JSObject *p;
6846
6902
  JSProperty *pr;
6847
6903
  JSShapeProperty *prs;
6848
6904
  JSValueConst val;
6849
6905
 
6850
- if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)
6851
- return NULL;
6852
- prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name);
6853
- if (!prs)
6906
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
6854
6907
  return NULL;
6908
+ p = JS_VALUE_GET_OBJ(obj);
6909
+ prs = find_own_property(&pr, p, prop);
6910
+ if (!prs) {
6911
+ /* we look at one level in the prototype to handle the 'name'
6912
+ field of the Error objects */
6913
+ p = p->shape->proto;
6914
+ if (!p)
6915
+ return NULL;
6916
+ prs = find_own_property(&pr, p, prop);
6917
+ if (!prs)
6918
+ return NULL;
6919
+ }
6920
+
6855
6921
  if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
6856
6922
  return NULL;
6857
6923
  val = pr->u.value;
@@ -6875,6 +6941,9 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
6875
6941
  const char *str1;
6876
6942
  JSObject *p;
6877
6943
 
6944
+ if (!JS_IsObject(error_obj))
6945
+ return; /* protection in the out of memory case */
6946
+
6878
6947
  js_dbuf_init(ctx, &dbuf);
6879
6948
  if (filename) {
6880
6949
  dbuf_printf(&dbuf, " at %s", filename);
@@ -6882,13 +6951,17 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
6882
6951
  dbuf_printf(&dbuf, ":%d:%d", line_num, col_num);
6883
6952
  dbuf_putc(&dbuf, '\n');
6884
6953
  str = JS_NewString(ctx, filename);
6954
+ if (JS_IsException(str))
6955
+ return;
6885
6956
  /* Note: SpiderMonkey does that, could update once there is a standard */
6886
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,
6887
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
6888
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
6889
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
6890
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num),
6891
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
6957
+ if (JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,
6958
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 ||
6959
+ JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
6960
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 ||
6961
+ JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num),
6962
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) {
6963
+ return;
6964
+ }
6892
6965
  }
6893
6966
  for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
6894
6967
  if (sf->js_mode & JS_MODE_BACKTRACE_BARRIER)
@@ -6897,7 +6970,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
6897
6970
  backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
6898
6971
  continue;
6899
6972
  }
6900
- func_name_str = get_func_name(ctx, sf->cur_func);
6973
+ func_name_str = get_prop_string(ctx, sf->cur_func, JS_ATOM_name);
6901
6974
  if (!func_name_str || func_name_str[0] == '\0')
6902
6975
  str1 = "<anonymous>";
6903
6976
  else
@@ -6973,9 +7046,9 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
6973
7046
  JS_DefinePropertyValue(ctx, obj, JS_ATOM_message,
6974
7047
  JS_NewString(ctx, buf),
6975
7048
  JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
6976
- }
6977
- if (add_backtrace) {
6978
- build_backtrace(ctx, obj, NULL, 0, 0, 0);
7049
+ if (add_backtrace) {
7050
+ build_backtrace(ctx, obj, NULL, 0, 0, 0);
7051
+ }
6979
7052
  }
6980
7053
  ret = JS_Throw(ctx, obj);
6981
7054
  return ret;
@@ -7164,7 +7237,7 @@ static JSValue JS_ThrowTypeErrorInvalidClass(JSContext *ctx, int class_id)
7164
7237
  static void JS_ThrowInterrupted(JSContext *ctx)
7165
7238
  {
7166
7239
  JS_ThrowInternalError(ctx, "interrupted");
7167
- JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);
7240
+ JS_SetUncatchableException(ctx, TRUE);
7168
7241
  }
7169
7242
 
7170
7243
  static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
@@ -7189,6 +7262,15 @@ static inline __exception int js_poll_interrupts(JSContext *ctx)
7189
7262
  }
7190
7263
  }
7191
7264
 
7265
+ static void JS_SetImmutablePrototype(JSContext *ctx, JSValueConst obj)
7266
+ {
7267
+ JSObject *p;
7268
+ if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
7269
+ return;
7270
+ p = JS_VALUE_GET_OBJ(obj);
7271
+ p->has_immutable_prototype = TRUE;
7272
+ }
7273
+
7192
7274
  /* Return -1 (exception) or TRUE/FALSE. 'throw_flag' = FALSE indicates
7193
7275
  that it is called from Reflect.setPrototypeOf(). */
7194
7276
  static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
@@ -7238,7 +7320,15 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj,
7238
7320
  sh = p->shape;
7239
7321
  if (sh->proto == proto)
7240
7322
  return TRUE;
7241
- if (!p->extensible) {
7323
+ if (unlikely(p->has_immutable_prototype)) {
7324
+ if (throw_flag) {
7325
+ JS_ThrowTypeError(ctx, "prototype is immutable");
7326
+ return -1;
7327
+ } else {
7328
+ return FALSE;
7329
+ }
7330
+ }
7331
+ if (unlikely(!p->extensible)) {
7242
7332
  if (throw_flag) {
7243
7333
  JS_ThrowTypeError(ctx, "object is not extensible");
7244
7334
  return -1;
@@ -7861,7 +7951,7 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque)
7861
7951
  return 1;
7862
7952
  }
7863
7953
 
7864
- static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
7954
+ void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
7865
7955
  {
7866
7956
  uint32_t i;
7867
7957
  if (tab) {
@@ -7955,7 +8045,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
7955
8045
  /* set the "is_enumerable" field if necessary */
7956
8046
  res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);
7957
8047
  if (res < 0) {
7958
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
8048
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
7959
8049
  return -1;
7960
8050
  }
7961
8051
  if (res) {
@@ -7986,7 +8076,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
7986
8076
  if (atom_count < exotic_keys_count || atom_count > INT32_MAX) {
7987
8077
  add_overflow:
7988
8078
  JS_ThrowOutOfMemory(ctx);
7989
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
8079
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
7990
8080
  return -1;
7991
8081
  }
7992
8082
  /* XXX: need generic way to test for js_malloc(ctx, a * b) overflow */
@@ -7994,7 +8084,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
7994
8084
  /* avoid allocating 0 bytes */
7995
8085
  tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1));
7996
8086
  if (!tab_atom) {
7997
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
8087
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
7998
8088
  return -1;
7999
8089
  }
8000
8090
 
@@ -8039,7 +8129,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
8039
8129
  for(i = 0; i < len; i++) {
8040
8130
  tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
8041
8131
  if (tab_atom[num_index].atom == JS_ATOM_NULL) {
8042
- js_free_prop_enum(ctx, tab_atom, num_index);
8132
+ JS_FreePropertyEnum(ctx, tab_atom, num_index);
8043
8133
  return -1;
8044
8134
  }
8045
8135
  tab_atom[num_index].is_enumerable = TRUE;
@@ -8335,6 +8425,9 @@ static JSValue JS_GetPropertyValue(JSContext *ctx, JSValueConst this_obj,
8335
8425
  case JS_CLASS_BIG_UINT64_ARRAY:
8336
8426
  if (unlikely(idx >= p->u.array.count)) goto slow_path;
8337
8427
  return JS_NewBigUint64(ctx, p->u.array.u.uint64_ptr[idx]);
8428
+ case JS_CLASS_FLOAT16_ARRAY:
8429
+ if (unlikely(idx >= p->u.array.count)) goto slow_path;
8430
+ return __JS_NewFloat64(ctx, fromfp16(p->u.array.u.fp16_ptr[idx]));
8338
8431
  case JS_CLASS_FLOAT32_ARRAY:
8339
8432
  if (unlikely(idx >= p->u.array.count)) goto slow_path;
8340
8433
  return __JS_NewFloat64(ctx, p->u.array.u.float_ptr[idx]);
@@ -8427,6 +8520,8 @@ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
8427
8520
  JSAtom atom;
8428
8521
  JSValue ret;
8429
8522
  atom = JS_NewAtom(ctx, prop);
8523
+ if (atom == JS_ATOM_NULL)
8524
+ return JS_EXCEPTION;
8430
8525
  ret = JS_GetProperty(ctx, this_obj, atom);
8431
8526
  JS_FreeAtom(ctx, atom);
8432
8527
  return ret;
@@ -9169,6 +9264,13 @@ static int JS_SetPropertyValue(JSContext *ctx, JSValueConst this_obj,
9169
9264
  p->u.array.u.uint64_ptr[idx] = v;
9170
9265
  }
9171
9266
  break;
9267
+ case JS_CLASS_FLOAT16_ARRAY:
9268
+ if (JS_ToFloat64Free(ctx, &d, val))
9269
+ return -1;
9270
+ if (unlikely(idx >= (uint32_t)p->u.array.count))
9271
+ goto ta_out_of_bound;
9272
+ p->u.array.u.fp16_ptr[idx] = tofp16(d);
9273
+ break;
9172
9274
  case JS_CLASS_FLOAT32_ARRAY:
9173
9275
  if (JS_ToFloat64Free(ctx, &d, val))
9174
9276
  return -1;
@@ -9239,6 +9341,10 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
9239
9341
  JSAtom atom;
9240
9342
  int ret;
9241
9343
  atom = JS_NewAtom(ctx, prop);
9344
+ if (atom == JS_ATOM_NULL) {
9345
+ JS_FreeValue(ctx, val);
9346
+ return -1;
9347
+ }
9242
9348
  ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW);
9243
9349
  JS_FreeAtom(ctx, atom);
9244
9350
  return ret;
@@ -9795,6 +9901,10 @@ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
9795
9901
  JSAtom atom;
9796
9902
  int ret;
9797
9903
  atom = JS_NewAtom(ctx, prop);
9904
+ if (atom == JS_ATOM_NULL) {
9905
+ JS_FreeValue(ctx, val);
9906
+ return -1;
9907
+ }
9798
9908
  ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);
9799
9909
  JS_FreeAtom(ctx, atom);
9800
9910
  return ret;
@@ -10098,6 +10208,29 @@ static int JS_SetGlobalVar(JSContext *ctx, JSAtom prop, JSValue val,
10098
10208
  return JS_SetPropertyInternal(ctx, ctx->global_obj, prop, val, ctx->global_obj, flags);
10099
10209
  }
10100
10210
 
10211
+ /* return -1, FALSE or TRUE */
10212
+ static int JS_DeleteGlobalVar(JSContext *ctx, JSAtom prop)
10213
+ {
10214
+ JSObject *p;
10215
+ JSShapeProperty *prs;
10216
+ JSProperty *pr;
10217
+ int ret;
10218
+
10219
+ /* 9.1.1.4.7 DeleteBinding ( N ) */
10220
+ p = JS_VALUE_GET_OBJ(ctx->global_var_obj);
10221
+ prs = find_own_property(&pr, p, prop);
10222
+ if (prs)
10223
+ return FALSE; /* lexical variables cannot be deleted */
10224
+ ret = JS_HasProperty(ctx, ctx->global_obj, prop);
10225
+ if (ret < 0)
10226
+ return -1;
10227
+ if (ret) {
10228
+ return JS_DeleteProperty(ctx, ctx->global_obj, prop, 0);
10229
+ } else {
10230
+ return TRUE;
10231
+ }
10232
+ }
10233
+
10101
10234
  /* return -1, FALSE or TRUE. return FALSE if not configurable or
10102
10235
  invalid object. return -1 in case of exception.
10103
10236
  flags can be 0, JS_PROP_THROW or JS_PROP_THROW_STRICT */
@@ -10196,29 +10329,10 @@ BOOL JS_IsError(JSContext *ctx, JSValueConst val)
10196
10329
  return (p->class_id == JS_CLASS_ERROR);
10197
10330
  }
10198
10331
 
10199
- /* used to avoid catching interrupt exceptions */
10200
- BOOL JS_IsUncatchableError(JSContext *ctx, JSValueConst val)
10332
+ /* must be called after JS_Throw() */
10333
+ void JS_SetUncatchableException(JSContext *ctx, BOOL flag)
10201
10334
  {
10202
- JSObject *p;
10203
- if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
10204
- return FALSE;
10205
- p = JS_VALUE_GET_OBJ(val);
10206
- return p->class_id == JS_CLASS_ERROR && p->is_uncatchable_error;
10207
- }
10208
-
10209
- void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)
10210
- {
10211
- JSObject *p;
10212
- if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT)
10213
- return;
10214
- p = JS_VALUE_GET_OBJ(val);
10215
- if (p->class_id == JS_CLASS_ERROR)
10216
- p->is_uncatchable_error = flag;
10217
- }
10218
-
10219
- void JS_ResetUncatchableError(JSContext *ctx)
10220
- {
10221
- JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE);
10335
+ ctx->rt->current_exception_is_uncatchable = flag;
10222
10336
  }
10223
10337
 
10224
10338
  void JS_SetOpaque(JSValue obj, void *opaque)
@@ -10504,6 +10618,15 @@ static inline js_limb_t js_limb_clz(js_limb_t a)
10504
10618
  }
10505
10619
  #endif
10506
10620
 
10621
+ /* handle a = 0 too */
10622
+ static inline js_limb_t js_limb_safe_clz(js_limb_t a)
10623
+ {
10624
+ if (a == 0)
10625
+ return JS_LIMB_BITS;
10626
+ else
10627
+ return js_limb_clz(a);
10628
+ }
10629
+
10507
10630
  static js_limb_t mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2,
10508
10631
  js_limb_t n, js_limb_t carry)
10509
10632
  {
@@ -11649,6 +11772,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx,
11649
11772
  const char *str, int radix)
11650
11773
  {
11651
11774
  const char *p = str;
11775
+ size_t n_digits1;
11652
11776
  int is_neg, n_digits, n_limbs, len, log2_radix, n_bits, i;
11653
11777
  JSBigInt *r;
11654
11778
  js_limb_t v, c, h;
@@ -11660,10 +11784,16 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx,
11660
11784
  }
11661
11785
  while (*p == '0')
11662
11786
  p++;
11663
- n_digits = strlen(p);
11787
+ n_digits1 = strlen(p);
11788
+ /* the real check for overflox is done js_bigint_new(). Here
11789
+ we just avoid integer overflow */
11790
+ if (n_digits1 > JS_BIGINT_MAX_SIZE * JS_LIMB_BITS) {
11791
+ JS_ThrowRangeError(ctx, "BigInt is too large to allocate");
11792
+ return NULL;
11793
+ }
11794
+ n_digits = n_digits1;
11664
11795
  log2_radix = 32 - clz32(radix - 1); /* ceil(log2(radix)) */
11665
11796
  /* compute the maximum number of limbs */
11666
- /* XXX: overflow */
11667
11797
  if (radix == 10) {
11668
11798
  n_bits = (n_digits * 27 + 7) / 8; /* >= ceil(n_digits * log2(10)) */
11669
11799
  } else {
@@ -11852,7 +11982,7 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
11852
11982
  r = tmp;
11853
11983
  }
11854
11984
  log2_radix = 31 - clz32(radix); /* floor(log2(radix)) */
11855
- n_bits = r->len * JS_LIMB_BITS - js_limb_clz(r->tab[r->len - 1]);
11985
+ n_bits = r->len * JS_LIMB_BITS - js_limb_safe_clz(r->tab[r->len - 1]);
11856
11986
  /* n_digits is exact only if radix is a power of
11857
11987
  two. Otherwise it is >= the exact number of digits */
11858
11988
  n_digits = (n_bits + log2_radix - 1) / log2_radix;
@@ -11894,11 +12024,10 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
11894
12024
  bit_pos = i * log2_radix;
11895
12025
  pos = bit_pos / JS_LIMB_BITS;
11896
12026
  shift = bit_pos % JS_LIMB_BITS;
11897
- if (likely((shift + log2_radix) <= JS_LIMB_BITS)) {
11898
- c = r->tab[pos] >> shift;
11899
- } else {
11900
- c = (r->tab[pos] >> shift) |
11901
- (r->tab[pos + 1] << (JS_LIMB_BITS - shift));
12027
+ c = r->tab[pos] >> shift;
12028
+ if ((shift + log2_radix) > JS_LIMB_BITS &&
12029
+ (pos + 1) < r->len) {
12030
+ c |= r->tab[pos + 1] << (JS_LIMB_BITS - shift);
11902
12031
  }
11903
12032
  c &= (radix - 1);
11904
12033
  *--q = digits[c];
@@ -12099,7 +12228,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
12099
12228
  case ATOD_TYPE_FLOAT64:
12100
12229
  {
12101
12230
  double d;
12102
- d = js_atod(buf,NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY,
12231
+ d = js_atod(buf, NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY,
12103
12232
  &atod_mem);
12104
12233
  /* return int or float64 */
12105
12234
  val = JS_NewFloat64(ctx, d);
@@ -12111,8 +12240,10 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
12111
12240
  if (has_legacy_octal || is_float)
12112
12241
  goto fail;
12113
12242
  r = js_bigint_from_string(ctx, buf, radix);
12114
- if (!r)
12115
- goto mem_error;
12243
+ if (!r) {
12244
+ val = JS_EXCEPTION;
12245
+ goto done;
12246
+ }
12116
12247
  val = JS_CompactBigInt(ctx, r);
12117
12248
  }
12118
12249
  break;
@@ -12871,27 +13002,71 @@ static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)
12871
13002
  return JS_ToString(ctx, val);
12872
13003
  }
12873
13004
 
12874
- static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
13005
+ #define JS_PRINT_MAX_DEPTH 8
13006
+
13007
+ typedef struct {
13008
+ JSRuntime *rt;
13009
+ JSContext *ctx; /* may be NULL */
13010
+ JSPrintValueOptions options;
13011
+ JSPrintValueWrite *write_func;
13012
+ void *write_opaque;
13013
+ int level;
13014
+ JSObject *print_stack[JS_PRINT_MAX_DEPTH]; /* level values */
13015
+ } JSPrintValueState;
13016
+
13017
+ static void js_print_value(JSPrintValueState *s, JSValueConst val);
13018
+
13019
+ static void js_putc(JSPrintValueState *s, char c)
12875
13020
  {
12876
- JSValue val;
12877
- JSString *p;
12878
- int i;
12879
- uint32_t c;
12880
- StringBuffer b_s, *b = &b_s;
12881
- char buf[16];
13021
+ s->write_func(s->write_opaque, &c, 1);
13022
+ }
12882
13023
 
12883
- val = JS_ToStringCheckObject(ctx, val1);
12884
- if (JS_IsException(val))
12885
- return val;
12886
- p = JS_VALUE_GET_STRING(val);
13024
+ static void js_puts(JSPrintValueState *s, const char *str)
13025
+ {
13026
+ s->write_func(s->write_opaque, str, strlen(str));
13027
+ }
12887
13028
 
12888
- if (string_buffer_init(ctx, b, p->len + 2))
12889
- goto fail;
13029
+ static void __attribute__((format(printf, 2, 3))) js_printf(JSPrintValueState *s, const char *fmt, ...)
13030
+ {
13031
+ va_list ap;
13032
+ char buf[256];
13033
+
13034
+ va_start(ap, fmt);
13035
+ vsnprintf(buf, sizeof(buf), fmt, ap);
13036
+ va_end(ap);
13037
+ s->write_func(s->write_opaque, buf, strlen(buf));
13038
+ }
12890
13039
 
12891
- if (string_buffer_putc8(b, '\"'))
12892
- goto fail;
12893
- for(i = 0; i < p->len; ) {
12894
- c = string_getc(p, &i);
13040
+ static void js_print_float64(JSPrintValueState *s, double d)
13041
+ {
13042
+ JSDTOATempMem dtoa_mem;
13043
+ char buf[32];
13044
+ int len;
13045
+ len = js_dtoa(buf, d, 10, 0, JS_DTOA_FORMAT_FREE | JS_DTOA_MINUS_ZERO, &dtoa_mem);
13046
+ s->write_func(s->write_opaque, buf, len);
13047
+ }
13048
+
13049
+ static uint32_t js_string_get_length(JSValueConst val)
13050
+ {
13051
+ if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) {
13052
+ JSString *p = JS_VALUE_GET_STRING(val);
13053
+ return p->len;
13054
+ } else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) {
13055
+ JSStringRope *r = JS_VALUE_GET_PTR(val);
13056
+ return r->len;
13057
+ } else {
13058
+ return 0;
13059
+ }
13060
+ }
13061
+
13062
+ /* pretty print the first 'len' characters of 'p' */
13063
+ static void js_print_string1(JSPrintValueState *s, JSString *p, int len, int sep)
13064
+ {
13065
+ uint8_t buf[UTF8_CHAR_LEN_MAX];
13066
+ int l, i, c, c1;
13067
+
13068
+ for(i = 0; i < len; i++) {
13069
+ c = string_get(p, i);
12895
13070
  switch(c) {
12896
13071
  case '\t':
12897
13072
  c = 't';
@@ -12908,188 +13083,528 @@ static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
12908
13083
  case '\f':
12909
13084
  c = 'f';
12910
13085
  goto quote;
12911
- case '\"':
12912
13086
  case '\\':
12913
13087
  quote:
12914
- if (string_buffer_putc8(b, '\\'))
12915
- goto fail;
12916
- if (string_buffer_putc8(b, c))
12917
- goto fail;
13088
+ js_putc(s, '\\');
13089
+ js_putc(s, c);
12918
13090
  break;
12919
13091
  default:
12920
- if (c < 32 || is_surrogate(c)) {
12921
- snprintf(buf, sizeof(buf), "\\u%04x", c);
12922
- if (string_buffer_puts8(b, buf))
12923
- goto fail;
13092
+ if (c == sep)
13093
+ goto quote;
13094
+ if (c >= 32 && c <= 126) {
13095
+ js_putc(s, c);
13096
+ } else if (c < 32 ||
13097
+ (c >= 0x7f && c <= 0x9f)) {
13098
+ escape:
13099
+ js_printf(s, "\\u%04x", c);
12924
13100
  } else {
12925
- if (string_buffer_putc(b, c))
12926
- goto fail;
13101
+ if (is_hi_surrogate(c)) {
13102
+ if ((i + 1) >= len)
13103
+ goto escape;
13104
+ c1 = string_get(p, i + 1);
13105
+ if (!is_lo_surrogate(c1))
13106
+ goto escape;
13107
+ i++;
13108
+ c = from_surrogate(c, c1);
13109
+ } else if (is_lo_surrogate(c)) {
13110
+ goto escape;
13111
+ }
13112
+ l = unicode_to_utf8(buf, c);
13113
+ s->write_func(s->write_opaque, (char *)buf, l);
12927
13114
  }
12928
13115
  break;
12929
13116
  }
12930
13117
  }
12931
- if (string_buffer_putc8(b, '\"'))
12932
- goto fail;
12933
- JS_FreeValue(ctx, val);
12934
- return string_buffer_end(b);
12935
- fail:
12936
- JS_FreeValue(ctx, val);
12937
- string_buffer_free(b);
12938
- return JS_EXCEPTION;
12939
13118
  }
12940
13119
 
12941
- static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
13120
+ static void js_print_string_rec(JSPrintValueState *s, JSValueConst val,
13121
+ int sep, uint32_t pos)
12942
13122
  {
12943
- printf("%14s %4s %4s %14s %10s %s\n",
12944
- "ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
13123
+ if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING) {
13124
+ JSString *p = JS_VALUE_GET_STRING(val);
13125
+ uint32_t len;
13126
+ if (pos < s->options.max_string_length) {
13127
+ len = min_uint32(p->len, s->options.max_string_length - pos);
13128
+ js_print_string1(s, p, len, sep);
13129
+ }
13130
+ } else if (JS_VALUE_GET_TAG(val) == JS_TAG_STRING_ROPE) {
13131
+ JSStringRope *r = JS_VALUE_GET_PTR(val);
13132
+ js_print_string_rec(s, r->left, sep, pos);
13133
+ js_print_string_rec(s, r->right, sep, pos + js_string_get_length(r->left));
13134
+ } else {
13135
+ js_printf(s, "<invalid string tag %d>", (int)JS_VALUE_GET_TAG(val));
13136
+ }
12945
13137
  }
12946
13138
 
12947
- /* for debug only: dump an object without side effect */
12948
- static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
13139
+ static void js_print_string(JSPrintValueState *s, JSValueConst val)
12949
13140
  {
12950
- uint32_t i;
12951
- char atom_buf[ATOM_GET_STR_BUF_SIZE];
12952
- JSShape *sh;
12953
- JSShapeProperty *prs;
12954
- JSProperty *pr;
12955
- BOOL is_first = TRUE;
13141
+ int sep;
13142
+ if (s->options.raw_dump && JS_VALUE_GET_TAG(val) == JS_TAG_STRING) {
13143
+ JSString *p = JS_VALUE_GET_STRING(val);
13144
+ js_printf(s, "%d", p->header.ref_count);
13145
+ sep = (p->header.ref_count == 1) ? '\"' : '\'';
13146
+ } else {
13147
+ sep = '\"';
13148
+ }
13149
+ js_putc(s, sep);
13150
+ js_print_string_rec(s, val, sep, 0);
13151
+ js_putc(s, sep);
13152
+ if (js_string_get_length(val) > s->options.max_string_length) {
13153
+ uint32_t n = js_string_get_length(val) - s->options.max_string_length;
13154
+ js_printf(s, "... %u more character%s", n, n > 1 ? "s" : "");
13155
+ }
13156
+ }
12956
13157
 
12957
- /* XXX: should encode atoms with special characters */
12958
- sh = p->shape; /* the shape can be NULL while freeing an object */
12959
- printf("%14p %4d ",
12960
- (void *)p,
12961
- p->header.ref_count);
12962
- if (sh) {
12963
- printf("%3d%c %14p ",
12964
- sh->header.ref_count,
12965
- " *"[sh->is_hashed],
12966
- (void *)sh->proto);
13158
+ static void js_print_raw_string(JSPrintValueState *s, JSValueConst val)
13159
+ {
13160
+ const char *cstr;
13161
+ size_t len;
13162
+ cstr = JS_ToCStringLen(s->ctx, &len, val);
13163
+ if (cstr) {
13164
+ s->write_func(s->write_opaque, cstr, len);
13165
+ JS_FreeCString(s->ctx, cstr);
13166
+ }
13167
+ }
13168
+
13169
+ static BOOL is_ascii_ident(const JSString *p)
13170
+ {
13171
+ int i, c;
13172
+
13173
+ if (p->len == 0)
13174
+ return FALSE;
13175
+ for(i = 0; i < p->len; i++) {
13176
+ c = string_get(p, i);
13177
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
13178
+ (c == '_' || c == '$') || (c >= '0' && c <= '9' && i > 0)))
13179
+ return FALSE;
13180
+ }
13181
+ return TRUE;
13182
+ }
13183
+
13184
+ static void js_print_atom(JSPrintValueState *s, JSAtom atom)
13185
+ {
13186
+ int i;
13187
+ if (__JS_AtomIsTaggedInt(atom)) {
13188
+ js_printf(s, "%u", __JS_AtomToUInt32(atom));
13189
+ } else if (atom == JS_ATOM_NULL) {
13190
+ js_puts(s, "<null>");
12967
13191
  } else {
12968
- printf("%3s %14s ", "-", "-");
13192
+ assert(atom < s->rt->atom_size);
13193
+ JSString *p;
13194
+ p = s->rt->atom_array[atom];
13195
+ if (is_ascii_ident(p)) {
13196
+ for(i = 0; i < p->len; i++) {
13197
+ js_putc(s, string_get(p, i));
13198
+ }
13199
+ } else {
13200
+ js_putc(s, '"');
13201
+ js_print_string1(s, p, p->len, '\"');
13202
+ js_putc(s, '"');
13203
+ }
12969
13204
  }
12970
- printf("%10s ",
12971
- JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), rt->class_array[p->class_id].class_name));
12972
- if (p->is_exotic && p->fast_array) {
12973
- printf("[ ");
12974
- for(i = 0; i < p->u.array.count; i++) {
12975
- if (i != 0)
12976
- printf(", ");
12977
- switch (p->class_id) {
12978
- case JS_CLASS_ARRAY:
12979
- case JS_CLASS_ARGUMENTS:
12980
- JS_DumpValueShort(rt, p->u.array.u.values[i]);
13205
+ }
13206
+
13207
+ /* return 0 if invalid length */
13208
+ static uint32_t js_print_array_get_length(JSObject *p)
13209
+ {
13210
+ JSProperty *pr;
13211
+ JSShapeProperty *prs;
13212
+ JSValueConst val;
13213
+
13214
+ prs = find_own_property(&pr, p, JS_ATOM_length);
13215
+ if (!prs)
13216
+ return 0;
13217
+ if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
13218
+ return 0;
13219
+ val = pr->u.value;
13220
+ switch(JS_VALUE_GET_NORM_TAG(val)) {
13221
+ case JS_TAG_INT:
13222
+ return JS_VALUE_GET_INT(val);
13223
+ case JS_TAG_FLOAT64:
13224
+ return (uint32_t)JS_VALUE_GET_FLOAT64(val);
13225
+ default:
13226
+ return 0;
13227
+ }
13228
+ }
13229
+
13230
+ static void js_print_comma(JSPrintValueState *s, int *pcomma_state)
13231
+ {
13232
+ switch(*pcomma_state) {
13233
+ case 0:
13234
+ break;
13235
+ case 1:
13236
+ js_printf(s, ", ");
13237
+ break;
13238
+ case 2:
13239
+ js_printf(s, " { ");
13240
+ break;
13241
+ }
13242
+ *pcomma_state = 1;
13243
+ }
13244
+
13245
+ static void js_print_more_items(JSPrintValueState *s, int *pcomma_state,
13246
+ uint32_t n)
13247
+ {
13248
+ js_print_comma(s, pcomma_state);
13249
+ js_printf(s, "... %u more item%s", n, n > 1 ? "s" : "");
13250
+ }
13251
+
13252
+ /* similar to js_regexp_toString() but without side effect */
13253
+ static void js_print_regexp(JSPrintValueState *s, JSObject *p1)
13254
+ {
13255
+ JSRegExp *re = &p1->u.regexp;
13256
+ JSString *p;
13257
+ int i, n, c, c2, bra, flags;
13258
+ static const char regexp_flags[] = { 'g', 'i', 'm', 's', 'u', 'y', 'd', 'v' };
13259
+
13260
+ p = re->pattern;
13261
+ js_putc(s, '/');
13262
+ if (p->len == 0) {
13263
+ js_puts(s, "(?:)");
13264
+ } else {
13265
+ bra = 0;
13266
+ for (i = 0, n = p->len; i < n;) {
13267
+ c2 = -1;
13268
+ switch (c = string_get(p, i++)) {
13269
+ case '\\':
13270
+ if (i < n)
13271
+ c2 = string_get(p, i++);
13272
+ break;
13273
+ case ']':
13274
+ bra = 0;
13275
+ break;
13276
+ case '[':
13277
+ if (!bra) {
13278
+ if (i < n && string_get(p, i) == ']')
13279
+ c2 = string_get(p, i++);
13280
+ bra = 1;
13281
+ }
13282
+ break;
13283
+ case '\n':
13284
+ c = '\\';
13285
+ c2 = 'n';
13286
+ break;
13287
+ case '\r':
13288
+ c = '\\';
13289
+ c2 = 'r';
12981
13290
  break;
13291
+ case '/':
13292
+ if (!bra) {
13293
+ c = '\\';
13294
+ c2 = '/';
13295
+ }
13296
+ break;
13297
+ }
13298
+ js_putc(s, c);
13299
+ if (c2 >= 0)
13300
+ js_putc(s, c2);
13301
+ }
13302
+ }
13303
+ js_putc(s, '/');
13304
+
13305
+ flags = lre_get_flags(re->bytecode->u.str8);
13306
+ for(i = 0; i < countof(regexp_flags); i++) {
13307
+ if ((flags >> i) & 1) {
13308
+ js_putc(s, regexp_flags[i]);
13309
+ }
13310
+ }
13311
+ }
13312
+
13313
+ /* similar to js_error_toString() but without side effect */
13314
+ static void js_print_error(JSPrintValueState *s, JSObject *p)
13315
+ {
13316
+ const char *str;
13317
+ size_t len;
13318
+
13319
+ str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_name);
13320
+ if (!str) {
13321
+ js_puts(s, "Error");
13322
+ } else {
13323
+ js_puts(s, str);
13324
+ JS_FreeCString(s->ctx, str);
13325
+ }
13326
+
13327
+ str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_message);
13328
+ if (str && str[0] != '\0') {
13329
+ js_puts(s, ": ");
13330
+ js_puts(s, str);
13331
+ }
13332
+ JS_FreeCString(s->ctx, str);
13333
+
13334
+ /* dump the stack if present */
13335
+ str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_stack);
13336
+ if (str) {
13337
+ js_putc(s, '\n');
13338
+
13339
+ /* XXX: should remove the last '\n' in stack as
13340
+ v8. SpiderMonkey does not do it */
13341
+ len = strlen(str);
13342
+ if (len > 0 && str[len - 1] == '\n')
13343
+ len--;
13344
+ s->write_func(s->write_opaque, str, len);
13345
+
13346
+ JS_FreeCString(s->ctx, str);
13347
+ }
13348
+ }
13349
+
13350
+ static void js_print_object(JSPrintValueState *s, JSObject *p)
13351
+ {
13352
+ JSRuntime *rt = s->rt;
13353
+ JSShape *sh;
13354
+ JSShapeProperty *prs;
13355
+ JSProperty *pr;
13356
+ int comma_state;
13357
+ BOOL is_array;
13358
+ uint32_t i;
13359
+
13360
+ comma_state = 0;
13361
+ is_array = FALSE;
13362
+ if (p->class_id == JS_CLASS_ARRAY) {
13363
+ is_array = TRUE;
13364
+ js_printf(s, "[ ");
13365
+ /* XXX: print array like properties even if not fast array */
13366
+ if (p->fast_array) {
13367
+ uint32_t len, n, len1;
13368
+ len = js_print_array_get_length(p);
13369
+
13370
+ len1 = min_uint32(p->u.array.count, s->options.max_item_count);
13371
+ for(i = 0; i < len1; i++) {
13372
+ js_print_comma(s, &comma_state);
13373
+ js_print_value(s, p->u.array.u.values[i]);
13374
+ }
13375
+ if (len1 < p->u.array.count)
13376
+ js_print_more_items(s, &comma_state, p->u.array.count - len1);
13377
+ if (p->u.array.count < len) {
13378
+ n = len - p->u.array.count;
13379
+ js_print_comma(s, &comma_state);
13380
+ js_printf(s, "<%u empty item%s>", n, n > 1 ? "s" : "");
13381
+ }
13382
+ }
13383
+ } else if (p->class_id >= JS_CLASS_UINT8C_ARRAY && p->class_id <= JS_CLASS_FLOAT64_ARRAY) {
13384
+ uint32_t size = 1 << typed_array_size_log2(p->class_id);
13385
+ uint32_t len1;
13386
+ int64_t v;
13387
+
13388
+ js_print_atom(s, rt->class_array[p->class_id].class_name);
13389
+ js_printf(s, "(%u) [ ", p->u.array.count);
13390
+
13391
+ is_array = TRUE;
13392
+ len1 = min_uint32(p->u.array.count, s->options.max_item_count);
13393
+ for(i = 0; i < len1; i++) {
13394
+ const uint8_t *ptr = p->u.array.u.uint8_ptr + i * size;
13395
+ js_print_comma(s, &comma_state);
13396
+ switch(p->class_id) {
12982
13397
  case JS_CLASS_UINT8C_ARRAY:
12983
- case JS_CLASS_INT8_ARRAY:
12984
13398
  case JS_CLASS_UINT8_ARRAY:
13399
+ v = *ptr;
13400
+ goto ta_int64;
13401
+ case JS_CLASS_INT8_ARRAY:
13402
+ v = *(int8_t *)ptr;
13403
+ goto ta_int64;
12985
13404
  case JS_CLASS_INT16_ARRAY:
13405
+ v = *(int16_t *)ptr;
13406
+ goto ta_int64;
12986
13407
  case JS_CLASS_UINT16_ARRAY:
13408
+ v = *(uint16_t *)ptr;
13409
+ goto ta_int64;
12987
13410
  case JS_CLASS_INT32_ARRAY:
13411
+ v = *(int32_t *)ptr;
13412
+ goto ta_int64;
12988
13413
  case JS_CLASS_UINT32_ARRAY:
13414
+ v = *(uint32_t *)ptr;
13415
+ goto ta_int64;
12989
13416
  case JS_CLASS_BIG_INT64_ARRAY:
13417
+ v = *(int64_t *)ptr;
13418
+ ta_int64:
13419
+ js_printf(s, "%" PRId64, v);
13420
+ break;
12990
13421
  case JS_CLASS_BIG_UINT64_ARRAY:
13422
+ js_printf(s, "%" PRIu64, *(uint64_t *)ptr);
13423
+ break;
13424
+ case JS_CLASS_FLOAT16_ARRAY:
13425
+ js_print_float64(s, fromfp16(*(uint16_t *)ptr));
13426
+ break;
12991
13427
  case JS_CLASS_FLOAT32_ARRAY:
13428
+ js_print_float64(s, *(float *)ptr);
13429
+ break;
12992
13430
  case JS_CLASS_FLOAT64_ARRAY:
12993
- {
12994
- int size = 1 << typed_array_size_log2(p->class_id);
12995
- const uint8_t *b = p->u.array.u.uint8_ptr + i * size;
12996
- while (size-- > 0)
12997
- printf("%02X", *b++);
12998
- }
13431
+ js_print_float64(s, *(double *)ptr);
12999
13432
  break;
13000
13433
  }
13001
13434
  }
13002
- printf(" ] ");
13435
+ if (len1 < p->u.array.count)
13436
+ js_print_more_items(s, &comma_state, p->u.array.count - len1);
13437
+ } else if (p->class_id == JS_CLASS_BYTECODE_FUNCTION ||
13438
+ (rt->class_array[p->class_id].call != NULL &&
13439
+ p->class_id != JS_CLASS_PROXY)) {
13440
+ js_printf(s, "[Function");
13441
+ /* XXX: allow dump without ctx */
13442
+ if (!s->options.raw_dump && s->ctx) {
13443
+ const char *func_name_str;
13444
+ js_putc(s, ' ');
13445
+ func_name_str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_name);
13446
+ if (!func_name_str || func_name_str[0] == '\0')
13447
+ js_puts(s, "(anonymous)");
13448
+ else
13449
+ js_puts(s, func_name_str);
13450
+ JS_FreeCString(s->ctx, func_name_str);
13451
+ }
13452
+ js_printf(s, "]");
13453
+ comma_state = 2;
13454
+ } else if (p->class_id == JS_CLASS_MAP || p->class_id == JS_CLASS_SET) {
13455
+ JSMapState *ms = p->u.opaque;
13456
+ struct list_head *el;
13457
+
13458
+ if (!ms)
13459
+ goto default_obj;
13460
+ js_print_atom(s, rt->class_array[p->class_id].class_name);
13461
+ js_printf(s, "(%u) { ", ms->record_count);
13462
+ i = 0;
13463
+ list_for_each(el, &ms->records) {
13464
+ JSMapRecord *mr = list_entry(el, JSMapRecord, link);
13465
+ js_print_comma(s, &comma_state);
13466
+ if (mr->empty)
13467
+ continue;
13468
+ js_print_value(s, mr->key);
13469
+ if (p->class_id == JS_CLASS_MAP) {
13470
+ js_printf(s, " => ");
13471
+ js_print_value(s, mr->value);
13472
+ }
13473
+ i++;
13474
+ if (i >= s->options.max_item_count)
13475
+ break;
13476
+ }
13477
+ if (i < ms->record_count)
13478
+ js_print_more_items(s, &comma_state, ms->record_count - i);
13479
+ } else if (p->class_id == JS_CLASS_REGEXP && s->ctx) {
13480
+ js_print_regexp(s, p);
13481
+ comma_state = 2;
13482
+ } else if (p->class_id == JS_CLASS_DATE && s->ctx) {
13483
+ /* get_date_string() has no side effect */
13484
+ JSValue str = get_date_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 0, NULL, 0x23); /* toISOString() */
13485
+ if (JS_IsException(str))
13486
+ goto default_obj;
13487
+ js_print_raw_string(s, str);
13488
+ JS_FreeValueRT(s->rt, str);
13489
+ comma_state = 2;
13490
+ } else if (p->class_id == JS_CLASS_ERROR && s->ctx) {
13491
+ js_print_error(s, p);
13492
+ comma_state = 2;
13493
+ } else {
13494
+ default_obj:
13495
+ if (p->class_id != JS_CLASS_OBJECT) {
13496
+ js_print_atom(s, rt->class_array[p->class_id].class_name);
13497
+ js_printf(s, " ");
13498
+ }
13499
+ js_printf(s, "{ ");
13003
13500
  }
13004
-
13501
+
13502
+ sh = p->shape; /* the shape can be NULL while freeing an object */
13005
13503
  if (sh) {
13006
- printf("{ ");
13504
+ uint32_t j;
13505
+
13506
+ j = 0;
13007
13507
  for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) {
13008
13508
  if (prs->atom != JS_ATOM_NULL) {
13009
- pr = &p->prop[i];
13010
- if (!is_first)
13011
- printf(", ");
13012
- printf("%s: ",
13013
- JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), prs->atom));
13014
- if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
13015
- printf("[getset %p %p]", (void *)pr->u.getset.getter,
13016
- (void *)pr->u.getset.setter);
13017
- } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
13018
- printf("[varref %p]", (void *)pr->u.var_ref);
13019
- } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
13020
- printf("[autoinit %p %d %p]",
13021
- (void *)js_autoinit_get_realm(pr),
13022
- js_autoinit_get_id(pr),
13023
- (void *)pr->u.init.opaque);
13024
- } else {
13025
- JS_DumpValueShort(rt, pr->u.value);
13509
+ if (!(prs->flags & JS_PROP_ENUMERABLE) &&
13510
+ !s->options.show_hidden) {
13511
+ continue;
13512
+ }
13513
+ if (j < s->options.max_item_count) {
13514
+ pr = &p->prop[i];
13515
+ js_print_comma(s, &comma_state);
13516
+ js_print_atom(s, prs->atom);
13517
+ js_printf(s, ": ");
13518
+
13519
+ /* XXX: autoinit property */
13520
+ if ((prs->flags & JS_PROP_TMASK) == JS_PROP_GETSET) {
13521
+ if (s->options.raw_dump) {
13522
+ js_printf(s, "[Getter %p Setter %p]",
13523
+ pr->u.getset.getter, pr->u.getset.setter);
13524
+ } else {
13525
+ if (pr->u.getset.getter && pr->u.getset.setter) {
13526
+ js_printf(s, "[Getter/Setter]");
13527
+ } else if (pr->u.getset.setter) {
13528
+ js_printf(s, "[Setter]");
13529
+ } else {
13530
+ js_printf(s, "[Getter]");
13531
+ }
13532
+ }
13533
+ } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
13534
+ if (s->options.raw_dump) {
13535
+ js_printf(s, "[varref %p]", (void *)pr->u.var_ref);
13536
+ } else {
13537
+ js_print_value(s, *pr->u.var_ref->pvalue);
13538
+ }
13539
+ } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
13540
+ if (s->options.raw_dump) {
13541
+ js_printf(s, "[autoinit %p %d %p]",
13542
+ (void *)js_autoinit_get_realm(pr),
13543
+ js_autoinit_get_id(pr),
13544
+ (void *)pr->u.init.opaque);
13545
+ } else {
13546
+ /* XXX: could autoinit but need to restart
13547
+ the iteration */
13548
+ js_printf(s, "[autoinit]");
13549
+ }
13550
+ } else {
13551
+ js_print_value(s, pr->u.value);
13552
+ }
13026
13553
  }
13027
- is_first = FALSE;
13554
+ j++;
13028
13555
  }
13029
13556
  }
13030
- printf(" }");
13557
+ if (j > s->options.max_item_count)
13558
+ js_print_more_items(s, &comma_state, j - s->options.max_item_count);
13031
13559
  }
13032
-
13033
- if (js_class_has_bytecode(p->class_id)) {
13560
+ if (s->options.raw_dump && js_class_has_bytecode(p->class_id)) {
13034
13561
  JSFunctionBytecode *b = p->u.func.function_bytecode;
13035
- JSVarRef **var_refs;
13036
13562
  if (b->closure_var_count) {
13563
+ JSVarRef **var_refs;
13037
13564
  var_refs = p->u.func.var_refs;
13038
- printf(" Closure:");
13565
+
13566
+ js_print_comma(s, &comma_state);
13567
+ js_printf(s, "[[Closure]]: [");
13039
13568
  for(i = 0; i < b->closure_var_count; i++) {
13040
- printf(" ");
13041
- JS_DumpValueShort(rt, var_refs[i]->value);
13042
- }
13043
- if (p->u.func.home_object) {
13044
- printf(" HomeObject: ");
13045
- JS_DumpValueShort(rt, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
13569
+ if (i != 0)
13570
+ js_printf(s, ", ");
13571
+ js_print_value(s, var_refs[i]->value);
13046
13572
  }
13573
+ js_printf(s, " ]");
13574
+ }
13575
+ if (p->u.func.home_object) {
13576
+ js_print_comma(s, &comma_state);
13577
+ js_printf(s, "[[HomeObject]]: ");
13578
+ js_print_value(s, JS_MKPTR(JS_TAG_OBJECT, p->u.func.home_object));
13047
13579
  }
13048
13580
  }
13049
- printf("\n");
13050
- }
13051
13581
 
13052
- static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
13053
- {
13054
- if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
13055
- JS_DumpObject(rt, (JSObject *)p);
13056
- } else {
13057
- printf("%14p %4d ",
13058
- (void *)p,
13059
- p->ref_count);
13060
- switch(p->gc_obj_type) {
13061
- case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
13062
- printf("[function bytecode]");
13063
- break;
13064
- case JS_GC_OBJ_TYPE_SHAPE:
13065
- printf("[shape]");
13066
- break;
13067
- case JS_GC_OBJ_TYPE_VAR_REF:
13068
- printf("[var_ref]");
13069
- break;
13070
- case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
13071
- printf("[async_function]");
13072
- break;
13073
- case JS_GC_OBJ_TYPE_JS_CONTEXT:
13074
- printf("[js_context]");
13075
- break;
13076
- default:
13077
- printf("[unknown %d]", p->gc_obj_type);
13078
- break;
13582
+ if (!is_array) {
13583
+ if (comma_state != 2) {
13584
+ js_printf(s, " }");
13079
13585
  }
13080
- printf("\n");
13586
+ } else {
13587
+ js_printf(s, " ]");
13081
13588
  }
13082
13589
  }
13083
13590
 
13084
- static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
13085
- JSValueConst val)
13591
+ static int js_print_stack_index(JSPrintValueState *s, JSObject *p)
13592
+ {
13593
+ int i;
13594
+ for(i = 0; i < s->level; i++)
13595
+ if (s->print_stack[i] == p)
13596
+ return i;
13597
+ return -1;
13598
+ }
13599
+
13600
+ static void js_print_value(JSPrintValueState *s, JSValueConst val)
13086
13601
  {
13087
13602
  uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
13088
13603
  const char *str;
13089
13604
 
13090
13605
  switch(tag) {
13091
13606
  case JS_TAG_INT:
13092
- printf("%d", JS_VALUE_GET_INT(val));
13607
+ js_printf(s, "%d", JS_VALUE_GET_INT(val));
13093
13608
  break;
13094
13609
  case JS_TAG_BOOL:
13095
13610
  if (JS_VALUE_GET_BOOL(val))
@@ -13109,98 +13624,248 @@ static __maybe_unused void JS_DumpValueShort(JSRuntime *rt,
13109
13624
  case JS_TAG_UNDEFINED:
13110
13625
  str = "undefined";
13111
13626
  print_str:
13112
- printf("%s", str);
13627
+ js_puts(s, str);
13113
13628
  break;
13114
13629
  case JS_TAG_FLOAT64:
13115
- printf("%.14g", JS_VALUE_GET_FLOAT64(val));
13630
+ js_print_float64(s, JS_VALUE_GET_FLOAT64(val));
13116
13631
  break;
13117
13632
  case JS_TAG_SHORT_BIG_INT:
13118
- printf("%" PRId64 "n", (int64_t)JS_VALUE_GET_SHORT_BIG_INT(val));
13633
+ js_printf(s, "%" PRId64 "n", (int64_t)JS_VALUE_GET_SHORT_BIG_INT(val));
13119
13634
  break;
13120
13635
  case JS_TAG_BIG_INT:
13121
- {
13122
- JSBigInt *p = JS_VALUE_GET_PTR(val);
13636
+ if (!s->options.raw_dump && s->ctx) {
13637
+ JSValue str = js_bigint_to_string(s->ctx, val);
13638
+ if (JS_IsException(str))
13639
+ goto raw_bigint;
13640
+ js_print_raw_string(s, str);
13641
+ js_putc(s, 'n');
13642
+ JS_FreeValueRT(s->rt, str);
13643
+ } else {
13644
+ JSBigInt *p;
13123
13645
  int sgn, i;
13646
+ raw_bigint:
13647
+ p = JS_VALUE_GET_PTR(val);
13124
13648
  /* In order to avoid allocations we just dump the limbs */
13125
13649
  sgn = js_bigint_sign(p);
13126
13650
  if (sgn)
13127
- printf("BigInt.asIntN(%d,", p->len * JS_LIMB_BITS);
13128
- printf("0x");
13651
+ js_printf(s, "BigInt.asIntN(%d,", p->len * JS_LIMB_BITS);
13652
+ js_printf(s, "0x");
13129
13653
  for(i = p->len - 1; i >= 0; i--) {
13130
13654
  if (i != p->len - 1)
13131
- printf("_");
13655
+ js_putc(s, '_');
13132
13656
  #if JS_LIMB_BITS == 32
13133
- printf("%08x", p->tab[i]);
13657
+ js_printf(s, "%08x", p->tab[i]);
13134
13658
  #else
13135
- printf("%016" PRIx64, p->tab[i]);
13659
+ js_printf(s, "%016" PRIx64, p->tab[i]);
13136
13660
  #endif
13137
13661
  }
13138
- printf("n");
13662
+ js_putc(s, 'n');
13139
13663
  if (sgn)
13140
- printf(")");
13664
+ js_putc(s, ')');
13141
13665
  }
13142
13666
  break;
13143
13667
  case JS_TAG_STRING:
13144
- {
13145
- JSString *p;
13146
- p = JS_VALUE_GET_STRING(val);
13147
- JS_DumpString(rt, p);
13148
- }
13149
- break;
13150
13668
  case JS_TAG_STRING_ROPE:
13151
- {
13669
+ if (s->options.raw_dump && tag == JS_TAG_STRING_ROPE) {
13152
13670
  JSStringRope *r = JS_VALUE_GET_STRING_ROPE(val);
13153
- printf("[rope len=%d depth=%d]", r->len, r->depth);
13671
+ js_printf(s, "[rope len=%d depth=%d]", r->len, r->depth);
13672
+ } else {
13673
+ js_print_string(s, val);
13154
13674
  }
13155
13675
  break;
13156
13676
  case JS_TAG_FUNCTION_BYTECODE:
13157
13677
  {
13158
13678
  JSFunctionBytecode *b = JS_VALUE_GET_PTR(val);
13159
- char buf[ATOM_GET_STR_BUF_SIZE];
13160
- printf("[bytecode %s]", JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
13679
+ js_puts(s, "[bytecode ");
13680
+ js_print_atom(s, b->func_name);
13681
+ js_putc(s, ']');
13161
13682
  }
13162
13683
  break;
13163
13684
  case JS_TAG_OBJECT:
13164
13685
  {
13165
13686
  JSObject *p = JS_VALUE_GET_OBJ(val);
13166
- JSAtom atom = rt->class_array[p->class_id].class_name;
13167
- char atom_buf[ATOM_GET_STR_BUF_SIZE];
13168
- printf("[%s %p]",
13169
- JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), atom), (void *)p);
13687
+ int idx;
13688
+ idx = js_print_stack_index(s, p);
13689
+ if (idx >= 0) {
13690
+ js_printf(s, "[circular %d]", idx);
13691
+ } else if (s->level < s->options.max_depth) {
13692
+ s->print_stack[s->level++] = p;
13693
+ js_print_object(s, JS_VALUE_GET_OBJ(val));
13694
+ s->level--;
13695
+ } else {
13696
+ JSAtom atom = s->rt->class_array[p->class_id].class_name;
13697
+ js_putc(s, '[');
13698
+ js_print_atom(s, atom);
13699
+ if (s->options.raw_dump) {
13700
+ js_printf(s, " %p", (void *)p);
13701
+ }
13702
+ js_putc(s, ']');
13703
+ }
13170
13704
  }
13171
13705
  break;
13172
13706
  case JS_TAG_SYMBOL:
13173
13707
  {
13174
13708
  JSAtomStruct *p = JS_VALUE_GET_PTR(val);
13175
- char atom_buf[ATOM_GET_STR_BUF_SIZE];
13176
- printf("Symbol(%s)",
13177
- JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), js_get_atom_index(rt, p)));
13709
+ js_puts(s, "Symbol(");
13710
+ js_print_atom(s, js_get_atom_index(s->rt, p));
13711
+ js_putc(s, ')');
13178
13712
  }
13179
13713
  break;
13180
13714
  case JS_TAG_MODULE:
13181
- printf("[module]");
13715
+ js_puts(s, "[module]");
13182
13716
  break;
13183
13717
  default:
13184
- printf("[unknown tag %d]", tag);
13718
+ js_printf(s, "[unknown tag %d]", tag);
13185
13719
  break;
13186
13720
  }
13187
13721
  }
13188
13722
 
13189
- static __maybe_unused void JS_DumpValue(JSContext *ctx,
13190
- JSValueConst val)
13723
+ void JS_PrintValueSetDefaultOptions(JSPrintValueOptions *options)
13724
+ {
13725
+ memset(options, 0, sizeof(*options));
13726
+ options->max_depth = 2;
13727
+ options->max_string_length = 1000;
13728
+ options->max_item_count = 100;
13729
+ }
13730
+
13731
+ static void JS_PrintValueInternal(JSRuntime *rt, JSContext *ctx,
13732
+ JSPrintValueWrite *write_func, void *write_opaque,
13733
+ JSValueConst val, const JSPrintValueOptions *options)
13734
+ {
13735
+ JSPrintValueState ss, *s = &ss;
13736
+ if (options)
13737
+ s->options = *options;
13738
+ else
13739
+ JS_PrintValueSetDefaultOptions(&s->options);
13740
+ if (s->options.max_depth <= 0)
13741
+ s->options.max_depth = JS_PRINT_MAX_DEPTH;
13742
+ else
13743
+ s->options.max_depth = min_int(s->options.max_depth, JS_PRINT_MAX_DEPTH);
13744
+ if (s->options.max_string_length == 0)
13745
+ s->options.max_string_length = UINT32_MAX;
13746
+ if (s->options.max_item_count == 0)
13747
+ s->options.max_item_count = UINT32_MAX;
13748
+ s->rt = rt;
13749
+ s->ctx = ctx;
13750
+ s->write_func = write_func;
13751
+ s->write_opaque = write_opaque;
13752
+ s->level = 0;
13753
+ js_print_value(s, val);
13754
+ }
13755
+
13756
+ void JS_PrintValueRT(JSRuntime *rt, JSPrintValueWrite *write_func, void *write_opaque,
13757
+ JSValueConst val, const JSPrintValueOptions *options)
13758
+ {
13759
+ JS_PrintValueInternal(rt, NULL, write_func, write_opaque, val, options);
13760
+ }
13761
+
13762
+ void JS_PrintValue(JSContext *ctx, JSPrintValueWrite *write_func, void *write_opaque,
13763
+ JSValueConst val, const JSPrintValueOptions *options)
13764
+ {
13765
+ JS_PrintValueInternal(ctx->rt, ctx, write_func, write_opaque, val, options);
13766
+ }
13767
+
13768
+ static void js_dump_value_write(void *opaque, const char *buf, size_t len)
13769
+ {
13770
+ FILE *fo = opaque;
13771
+ fwrite(buf, 1, len, fo);
13772
+ }
13773
+
13774
+ static __maybe_unused void print_atom(JSContext *ctx, JSAtom atom)
13191
13775
  {
13192
- JS_DumpValueShort(ctx->rt, val);
13776
+ JSPrintValueState ss, *s = &ss;
13777
+ memset(s, 0, sizeof(*s));
13778
+ s->rt = ctx->rt;
13779
+ s->ctx = ctx;
13780
+ s->write_func = js_dump_value_write;
13781
+ s->write_opaque = stdout;
13782
+ js_print_atom(s, atom);
13193
13783
  }
13194
13784
 
13195
- static __maybe_unused void JS_PrintValue(JSContext *ctx,
13196
- const char *str,
13197
- JSValueConst val)
13785
+ static __maybe_unused void JS_DumpValue(JSContext *ctx, const char *str, JSValueConst val)
13198
13786
  {
13199
13787
  printf("%s=", str);
13200
- JS_DumpValueShort(ctx->rt, val);
13788
+ JS_PrintValue(ctx, js_dump_value_write, stdout, val, NULL);
13201
13789
  printf("\n");
13202
13790
  }
13203
13791
 
13792
+ static __maybe_unused void JS_DumpValueRT(JSRuntime *rt, const char *str, JSValueConst val)
13793
+ {
13794
+ printf("%s=", str);
13795
+ JS_PrintValueRT(rt, js_dump_value_write, stdout, val, NULL);
13796
+ printf("\n");
13797
+ }
13798
+
13799
+ static __maybe_unused void JS_DumpObjectHeader(JSRuntime *rt)
13800
+ {
13801
+ printf("%14s %4s %4s %14s %s\n",
13802
+ "ADDRESS", "REFS", "SHRF", "PROTO", "CONTENT");
13803
+ }
13804
+
13805
+ /* for debug only: dump an object without side effect */
13806
+ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
13807
+ {
13808
+ JSShape *sh;
13809
+ JSPrintValueOptions options;
13810
+
13811
+ /* XXX: should encode atoms with special characters */
13812
+ sh = p->shape; /* the shape can be NULL while freeing an object */
13813
+ printf("%14p %4d ",
13814
+ (void *)p,
13815
+ p->header.ref_count);
13816
+ if (sh) {
13817
+ printf("%3d%c %14p ",
13818
+ sh->header.ref_count,
13819
+ " *"[sh->is_hashed],
13820
+ (void *)sh->proto);
13821
+ } else {
13822
+ printf("%3s %14s ", "-", "-");
13823
+ }
13824
+
13825
+ JS_PrintValueSetDefaultOptions(&options);
13826
+ options.max_depth = 1;
13827
+ options.show_hidden = TRUE;
13828
+ options.raw_dump = TRUE;
13829
+ JS_PrintValueRT(rt, js_dump_value_write, stdout, JS_MKPTR(JS_TAG_OBJECT, p), &options);
13830
+
13831
+ printf("\n");
13832
+ }
13833
+
13834
+ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
13835
+ {
13836
+ if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) {
13837
+ JS_DumpObject(rt, (JSObject *)p);
13838
+ } else {
13839
+ printf("%14p %4d ",
13840
+ (void *)p,
13841
+ p->ref_count);
13842
+ switch(p->gc_obj_type) {
13843
+ case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
13844
+ printf("[function bytecode]");
13845
+ break;
13846
+ case JS_GC_OBJ_TYPE_SHAPE:
13847
+ printf("[shape]");
13848
+ break;
13849
+ case JS_GC_OBJ_TYPE_VAR_REF:
13850
+ printf("[var_ref]");
13851
+ break;
13852
+ case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
13853
+ printf("[async_function]");
13854
+ break;
13855
+ case JS_GC_OBJ_TYPE_JS_CONTEXT:
13856
+ printf("[js_context]");
13857
+ break;
13858
+ case JS_GC_OBJ_TYPE_MODULE:
13859
+ printf("[module]");
13860
+ break;
13861
+ default:
13862
+ printf("[unknown %d]", p->gc_obj_type);
13863
+ break;
13864
+ }
13865
+ printf("\n");
13866
+ }
13867
+ }
13868
+
13204
13869
  /* return -1 if exception (proxy case) or TRUE/FALSE */
13205
13870
  // TODO: should take flags to make proxy resolution and exceptions optional
13206
13871
  int JS_IsArray(JSContext *ctx, JSValueConst val)
@@ -15041,7 +15706,7 @@ static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
15041
15706
  JS_FreeValue(ctx, obj1);
15042
15707
  goto fail;
15043
15708
  }
15044
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
15709
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
15045
15710
  if (tab_atom_count != 0) {
15046
15711
  JS_FreeValue(ctx, obj1);
15047
15712
  goto slow_path;
@@ -15125,7 +15790,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
15125
15790
  JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
15126
15791
  return -1;
15127
15792
  }
15128
- js_free_prop_enum(ctx, it->tab_atom, it->atom_count);
15793
+ JS_FreePropertyEnum(ctx, it->tab_atom, it->atom_count);
15129
15794
  it->tab_atom = tab_atom;
15130
15795
  it->atom_count = tab_atom_count;
15131
15796
  it->idx = 0;
@@ -15506,6 +16171,7 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
15506
16171
  int is_array_iterator;
15507
16172
  JSValue *arrp;
15508
16173
  uint32_t i, count32, pos;
16174
+ JSCFunctionType ft;
15509
16175
 
15510
16176
  if (JS_VALUE_GET_TAG(sp[-2]) != JS_TAG_INT) {
15511
16177
  JS_ThrowInternalError(ctx, "invalid index for append");
@@ -15523,8 +16189,8 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
15523
16189
  iterator = JS_GetProperty(ctx, sp[-1], JS_ATOM_Symbol_iterator);
15524
16190
  if (JS_IsException(iterator))
15525
16191
  return -1;
15526
- is_array_iterator = JS_IsCFunction(ctx, iterator,
15527
- (JSCFunction *)js_create_array_iterator,
16192
+ ft.generic_magic = js_create_array_iterator;
16193
+ is_array_iterator = JS_IsCFunction(ctx, iterator, ft.generic,
15528
16194
  JS_ITERATOR_KIND_VALUE);
15529
16195
  JS_FreeValue(ctx, iterator);
15530
16196
 
@@ -15536,8 +16202,10 @@ static __exception int js_append_enumerate(JSContext *ctx, JSValue *sp)
15536
16202
  JS_FreeValue(ctx, enumobj);
15537
16203
  return -1;
15538
16204
  }
16205
+
16206
+ ft.iterator_next = js_array_iterator_next;
15539
16207
  if (is_array_iterator
15540
- && JS_IsCFunction(ctx, method, (JSCFunction *)js_array_iterator_next, 0)
16208
+ && JS_IsCFunction(ctx, method, ft.generic, 0)
15541
16209
  && js_get_fast_array(ctx, sp[-1], &arrp, &count32)) {
15542
16210
  uint32_t len;
15543
16211
  if (js_get_length32(ctx, &len, sp[-1]))
@@ -15648,10 +16316,10 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
15648
16316
  if (ret < 0)
15649
16317
  goto exception;
15650
16318
  }
15651
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
16319
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
15652
16320
  return 0;
15653
16321
  exception:
15654
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
16322
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
15655
16323
  return -1;
15656
16324
  }
15657
16325
 
@@ -16868,10 +17536,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
16868
17536
  {
16869
17537
  JSValue val;
16870
17538
  sf->cur_pc = pc;
16871
- val = js_dynamic_import(ctx, sp[-1]);
17539
+ val = js_dynamic_import(ctx, sp[-2], sp[-1]);
16872
17540
  if (JS_IsException(val))
16873
17541
  goto exception;
17542
+ JS_FreeValue(ctx, sp[-2]);
16874
17543
  JS_FreeValue(ctx, sp[-1]);
17544
+ sp--;
16875
17545
  sp[-1] = val;
16876
17546
  }
16877
17547
  BREAK;
@@ -17798,6 +18468,38 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
17798
18468
  }
17799
18469
  BREAK;
17800
18470
 
18471
+ CASE(OP_get_array_el3):
18472
+ {
18473
+ JSValue val;
18474
+
18475
+ switch (JS_VALUE_GET_TAG(sp[-2])) {
18476
+ case JS_TAG_INT:
18477
+ case JS_TAG_STRING:
18478
+ case JS_TAG_SYMBOL:
18479
+ /* undefined and null are tested in JS_GetPropertyValue() */
18480
+ break;
18481
+ default:
18482
+ /* must be tested nefore JS_ToPropertyKey */
18483
+ if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) {
18484
+ JS_ThrowTypeError(ctx, "value has no property");
18485
+ goto exception;
18486
+ }
18487
+ sf->cur_pc = pc;
18488
+ ret_val = JS_ToPropertyKey(ctx, sp[-1]);
18489
+ if (JS_IsException(ret_val))
18490
+ goto exception;
18491
+ JS_FreeValue(ctx, sp[-1]);
18492
+ sp[-1] = ret_val;
18493
+ break;
18494
+ }
18495
+ sf->cur_pc = pc;
18496
+ val = JS_GetPropertyValue(ctx, sp[-2], JS_DupValue(ctx, sp[-1]));
18497
+ *sp++ = val;
18498
+ if (unlikely(JS_IsException(val)))
18499
+ goto exception;
18500
+ }
18501
+ BREAK;
18502
+
17801
18503
  CASE(OP_get_ref_value):
17802
18504
  {
17803
18505
  JSValue val;
@@ -18020,12 +18722,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
18020
18722
  *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) +
18021
18723
  JS_VALUE_GET_FLOAT64(op2));
18022
18724
  sp--;
18023
- } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
18725
+ } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING &&
18726
+ JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
18024
18727
  sp--;
18025
18728
  sf->cur_pc = pc;
18026
- op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
18027
- if (JS_IsException(op2))
18028
- goto exception;
18029
18729
  if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), op2)) {
18030
18730
  JS_FreeValue(ctx, op2);
18031
18731
  } else {
@@ -18490,7 +19190,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
18490
19190
  pc += 4;
18491
19191
  sf->cur_pc = pc;
18492
19192
 
18493
- ret = JS_DeleteProperty(ctx, ctx->global_obj, atom, 0);
19193
+ ret = JS_DeleteGlobalVar(ctx, atom);
18494
19194
  if (unlikely(ret < 0))
18495
19195
  goto exception;
18496
19196
  *sp++ = JS_NewBool(ctx, ret);
@@ -18525,27 +19225,6 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
18525
19225
  }
18526
19226
  BREAK;
18527
19227
 
18528
- CASE(OP_to_propkey2):
18529
- /* must be tested first */
18530
- if (unlikely(JS_IsUndefined(sp[-2]) || JS_IsNull(sp[-2]))) {
18531
- JS_ThrowTypeError(ctx, "value has no property");
18532
- goto exception;
18533
- }
18534
- switch (JS_VALUE_GET_TAG(sp[-1])) {
18535
- case JS_TAG_INT:
18536
- case JS_TAG_STRING:
18537
- case JS_TAG_SYMBOL:
18538
- break;
18539
- default:
18540
- sf->cur_pc = pc;
18541
- ret_val = JS_ToPropertyKey(ctx, sp[-1]);
18542
- if (JS_IsException(ret_val))
18543
- goto exception;
18544
- JS_FreeValue(ctx, sp[-1]);
18545
- sp[-1] = ret_val;
18546
- break;
18547
- }
18548
- BREAK;
18549
19228
  #if 0
18550
19229
  CASE(OP_to_string):
18551
19230
  if (JS_VALUE_GET_TAG(sp[-1]) != JS_TAG_STRING) {
@@ -18737,7 +19416,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
18737
19416
  sf->cur_pc = pc;
18738
19417
  build_backtrace(ctx, rt->current_exception, NULL, 0, 0, 0);
18739
19418
  }
18740
- if (!JS_IsUncatchableError(ctx, rt->current_exception)) {
19419
+ if (!rt->current_exception_is_uncatchable) {
18741
19420
  while (sp > stack_buf) {
18742
19421
  JSValue val = *--sp;
18743
19422
  JS_FreeValue(ctx, val);
@@ -20436,6 +21115,7 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
20436
21115
  {
20437
21116
  uint32_t c;
20438
21117
  StringBuffer b_s, *b = &b_s;
21118
+ JSValue str;
20439
21119
 
20440
21120
  /* p points to the first byte of the template part */
20441
21121
  if (string_buffer_init(s->ctx, b, 32))
@@ -20478,9 +21158,12 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
20478
21158
  if (string_buffer_putc(b, c))
20479
21159
  goto fail;
20480
21160
  }
21161
+ str = string_buffer_end(b);
21162
+ if (JS_IsException(str))
21163
+ return -1;
20481
21164
  s->token.val = TOK_TEMPLATE;
20482
21165
  s->token.u.str.sep = c;
20483
- s->token.u.str.str = string_buffer_end(b);
21166
+ s->token.u.str.str = str;
20484
21167
  s->buf_ptr = p;
20485
21168
  return 0;
20486
21169
 
@@ -20499,7 +21182,8 @@ static __exception int js_parse_string(JSParseState *s, int sep,
20499
21182
  uint32_t c;
20500
21183
  StringBuffer b_s, *b = &b_s;
20501
21184
  const uint8_t *p_escape;
20502
-
21185
+ JSValue str;
21186
+
20503
21187
  /* string */
20504
21188
  if (string_buffer_init(s->ctx, b, 32))
20505
21189
  goto fail;
@@ -20508,11 +21192,6 @@ static __exception int js_parse_string(JSParseState *s, int sep,
20508
21192
  goto invalid_char;
20509
21193
  c = *p;
20510
21194
  if (c < 0x20) {
20511
- if (!s->cur_func) {
20512
- if (do_throw)
20513
- js_parse_error_pos(s, p, "invalid character in a JSON string");
20514
- goto fail;
20515
- }
20516
21195
  if (sep == '`') {
20517
21196
  if (c == '\r') {
20518
21197
  if (p[1] == '\n')
@@ -20558,8 +21237,6 @@ static __exception int js_parse_string(JSParseState *s, int sep,
20558
21237
  continue;
20559
21238
  default:
20560
21239
  if (c >= '0' && c <= '9') {
20561
- if (!s->cur_func)
20562
- goto invalid_escape; /* JSON case */
20563
21240
  if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')
20564
21241
  goto parse_escape;
20565
21242
  if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
@@ -20613,9 +21290,12 @@ static __exception int js_parse_string(JSParseState *s, int sep,
20613
21290
  if (string_buffer_putc(b, c))
20614
21291
  goto fail;
20615
21292
  }
21293
+ str = string_buffer_end(b);
21294
+ if (JS_IsException(str))
21295
+ return -1;
20616
21296
  token->val = TOK_STRING;
20617
21297
  token->u.str.sep = c;
20618
- token->u.str.str = string_buffer_end(b);
21298
+ token->u.str.str = str;
20619
21299
  *pp = p;
20620
21300
  return 0;
20621
21301
 
@@ -20643,6 +21323,7 @@ static __exception int js_parse_regexp(JSParseState *s)
20643
21323
  StringBuffer b_s, *b = &b_s;
20644
21324
  StringBuffer b2_s, *b2 = &b2_s;
20645
21325
  uint32_t c;
21326
+ JSValue body_str, flags_str;
20646
21327
 
20647
21328
  p = s->buf_ptr;
20648
21329
  p++;
@@ -20724,9 +21405,17 @@ static __exception int js_parse_regexp(JSParseState *s)
20724
21405
  p = p_next;
20725
21406
  }
20726
21407
 
21408
+ body_str = string_buffer_end(b);
21409
+ flags_str = string_buffer_end(b2);
21410
+ if (JS_IsException(body_str) ||
21411
+ JS_IsException(flags_str)) {
21412
+ JS_FreeValue(s->ctx, body_str);
21413
+ JS_FreeValue(s->ctx, flags_str);
21414
+ return -1;
21415
+ }
20727
21416
  s->token.val = TOK_REGEXP;
20728
- s->token.u.regexp.body = string_buffer_end(b);
20729
- s->token.u.regexp.flags = string_buffer_end(b2);
21417
+ s->token.u.regexp.body = body_str;
21418
+ s->token.u.regexp.flags = flags_str;
20730
21419
  s->buf_ptr = p;
20731
21420
  return 0;
20732
21421
  fail:
@@ -21296,6 +21985,7 @@ static __exception int next_token(JSParseState *s)
21296
21985
  }
21297
21986
 
21298
21987
  /* 'c' is the first character. Return JS_ATOM_NULL in case of error */
21988
+ /* XXX: accept unicode identifiers as JSON5 ? */
21299
21989
  static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
21300
21990
  {
21301
21991
  const uint8_t *p;
@@ -21328,6 +22018,178 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
21328
22018
  return atom;
21329
22019
  }
21330
22020
 
22021
+ static int json_parse_string(JSParseState *s, const uint8_t **pp, int sep)
22022
+ {
22023
+ const uint8_t *p, *p_next;
22024
+ int i;
22025
+ uint32_t c;
22026
+ StringBuffer b_s, *b = &b_s;
22027
+
22028
+ if (string_buffer_init(s->ctx, b, 32))
22029
+ goto fail;
22030
+
22031
+ p = *pp;
22032
+ for(;;) {
22033
+ if (p >= s->buf_end) {
22034
+ goto end_of_input;
22035
+ }
22036
+ c = *p++;
22037
+ if (c == sep)
22038
+ break;
22039
+ if (c < 0x20) {
22040
+ js_parse_error_pos(s, p - 1, "Bad control character in string literal");
22041
+ goto fail;
22042
+ }
22043
+ if (c == '\\') {
22044
+ c = *p++;
22045
+ switch(c) {
22046
+ case 'b': c = '\b'; break;
22047
+ case 'f': c = '\f'; break;
22048
+ case 'n': c = '\n'; break;
22049
+ case 'r': c = '\r'; break;
22050
+ case 't': c = '\t'; break;
22051
+ case '\\': break;
22052
+ case '/': break;
22053
+ case 'u':
22054
+ c = 0;
22055
+ for(i = 0; i < 4; i++) {
22056
+ int h = from_hex(*p++);
22057
+ if (h < 0) {
22058
+ js_parse_error_pos(s, p - 1, "Bad Unicode escape");
22059
+ goto fail;
22060
+ }
22061
+ c = (c << 4) | h;
22062
+ }
22063
+ break;
22064
+ case '\n':
22065
+ if (s->ext_json)
22066
+ continue;
22067
+ goto bad_escape;
22068
+ case 'v':
22069
+ if (s->ext_json) {
22070
+ c = '\v';
22071
+ break;
22072
+ }
22073
+ goto bad_escape;
22074
+ default:
22075
+ if (c == sep)
22076
+ break;
22077
+ if (p > s->buf_end)
22078
+ goto end_of_input;
22079
+ bad_escape:
22080
+ js_parse_error_pos(s, p - 1, "Bad escaped character");
22081
+ goto fail;
22082
+ }
22083
+ } else
22084
+ if (c >= 0x80) {
22085
+ c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
22086
+ if (c > 0x10FFFF) {
22087
+ js_parse_error_pos(s, p - 1, "Bad UTF-8 sequence");
22088
+ goto fail;
22089
+ }
22090
+ p = p_next;
22091
+ }
22092
+ if (string_buffer_putc(b, c))
22093
+ goto fail;
22094
+ }
22095
+ s->token.val = TOK_STRING;
22096
+ s->token.u.str.sep = sep;
22097
+ s->token.u.str.str = string_buffer_end(b);
22098
+ *pp = p;
22099
+ return 0;
22100
+
22101
+ end_of_input:
22102
+ js_parse_error(s, "Unexpected end of JSON input");
22103
+ fail:
22104
+ string_buffer_free(b);
22105
+ return -1;
22106
+ }
22107
+
22108
+ static int json_parse_number(JSParseState *s, const uint8_t **pp)
22109
+ {
22110
+ const uint8_t *p = *pp;
22111
+ const uint8_t *p_start = p;
22112
+ int radix;
22113
+ double d;
22114
+ JSATODTempMem atod_mem;
22115
+
22116
+ if (*p == '+' || *p == '-')
22117
+ p++;
22118
+
22119
+ if (!is_digit(*p)) {
22120
+ if (s->ext_json) {
22121
+ if (strstart((const char *)p, "Infinity", (const char **)&p)) {
22122
+ d = 1.0 / 0.0;
22123
+ if (*p_start == '-')
22124
+ d = -d;
22125
+ goto done;
22126
+ } else if (strstart((const char *)p, "NaN", (const char **)&p)) {
22127
+ d = NAN;
22128
+ goto done;
22129
+ } else if (*p != '.') {
22130
+ goto unexpected_token;
22131
+ }
22132
+ } else {
22133
+ goto unexpected_token;
22134
+ }
22135
+ }
22136
+
22137
+ if (p[0] == '0') {
22138
+ if (s->ext_json) {
22139
+ /* also accepts base 16, 8 and 2 prefix for integers */
22140
+ radix = 10;
22141
+ if (p[1] == 'x' || p[1] == 'X') {
22142
+ p += 2;
22143
+ radix = 16;
22144
+ } else if ((p[1] == 'o' || p[1] == 'O')) {
22145
+ p += 2;
22146
+ radix = 8;
22147
+ } else if ((p[1] == 'b' || p[1] == 'B')) {
22148
+ p += 2;
22149
+ radix = 2;
22150
+ }
22151
+ if (radix != 10) {
22152
+ /* prefix is present */
22153
+ if (to_digit(*p) >= radix) {
22154
+ unexpected_token:
22155
+ return js_parse_error_pos(s, p, "Unexpected token '%c'", *p);
22156
+ }
22157
+ d = js_atod((const char *)p_start, (const char **)&p, 0,
22158
+ JS_ATOD_INT_ONLY | JS_ATOD_ACCEPT_BIN_OCT, &atod_mem);
22159
+ goto done;
22160
+ }
22161
+ }
22162
+ if (is_digit(p[1]))
22163
+ return js_parse_error_pos(s, p, "Unexpected number");
22164
+ }
22165
+
22166
+ while (is_digit(*p))
22167
+ p++;
22168
+
22169
+ if (*p == '.') {
22170
+ p++;
22171
+ if (!is_digit(*p))
22172
+ return js_parse_error_pos(s, p, "Unterminated fractional number");
22173
+ while (is_digit(*p))
22174
+ p++;
22175
+ }
22176
+ if (*p == 'e' || *p == 'E') {
22177
+ p++;
22178
+ if (*p == '+' || *p == '-')
22179
+ p++;
22180
+ if (!is_digit(*p))
22181
+ return js_parse_error_pos(s, p, "Exponent part is missing a number");
22182
+ while (is_digit(*p))
22183
+ p++;
22184
+ }
22185
+ d = js_atod((const char *)p_start, NULL, 10, 0, &atod_mem);
22186
+ done:
22187
+ s->token.val = TOK_NUMBER;
22188
+ s->token.u.num.val = JS_NewFloat64(s->ctx, d);
22189
+ *pp = p;
22190
+ return 0;
22191
+ }
22192
+
21331
22193
  static __exception int json_next_token(JSParseState *s)
21332
22194
  {
21333
22195
  const uint8_t *p;
@@ -21359,7 +22221,8 @@ static __exception int json_next_token(JSParseState *s)
21359
22221
  }
21360
22222
  /* fall through */
21361
22223
  case '\"':
21362
- if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
22224
+ p++;
22225
+ if (json_parse_string(s, &p, c))
21363
22226
  goto fail;
21364
22227
  break;
21365
22228
  case '\r': /* accept DOS and MAC newline sequences */
@@ -21449,7 +22312,6 @@ static __exception int json_next_token(JSParseState *s)
21449
22312
  case 'Y': case 'Z':
21450
22313
  case '_':
21451
22314
  case '$':
21452
- /* identifier : only pure ascii characters are accepted */
21453
22315
  p++;
21454
22316
  atom = json_parse_ident(s, &p, c);
21455
22317
  if (atom == JS_ATOM_NULL)
@@ -21460,39 +22322,23 @@ static __exception int json_next_token(JSParseState *s)
21460
22322
  s->token.val = TOK_IDENT;
21461
22323
  break;
21462
22324
  case '+':
21463
- if (!s->ext_json || !is_digit(p[1]))
22325
+ if (!s->ext_json)
21464
22326
  goto def_token;
21465
22327
  goto parse_number;
21466
- case '0':
21467
- if (is_digit(p[1]))
22328
+ case '.':
22329
+ if (s->ext_json && is_digit(p[1]))
22330
+ goto parse_number;
22331
+ else
21468
22332
  goto def_token;
21469
- goto parse_number;
21470
22333
  case '-':
21471
- if (!is_digit(p[1]))
21472
- goto def_token;
21473
- goto parse_number;
22334
+ case '0':
21474
22335
  case '1': case '2': case '3': case '4':
21475
22336
  case '5': case '6': case '7': case '8':
21476
22337
  case '9':
21477
22338
  /* number */
21478
22339
  parse_number:
21479
- {
21480
- JSValue ret;
21481
- int flags, radix;
21482
- if (!s->ext_json) {
21483
- flags = 0;
21484
- radix = 10;
21485
- } else {
21486
- flags = ATOD_ACCEPT_BIN_OCT;
21487
- radix = 0;
21488
- }
21489
- ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,
21490
- flags);
21491
- if (JS_IsException(ret))
21492
- goto fail;
21493
- s->token.val = TOK_NUMBER;
21494
- s->token.u.num.val = ret;
21495
- }
22340
+ if (json_parse_number(s, &p))
22341
+ goto fail;
21496
22342
  break;
21497
22343
  default:
21498
22344
  if (c >= 128) {
@@ -21677,7 +22523,7 @@ BOOL JS_DetectModule(const char *input, size_t input_len)
21677
22523
  }
21678
22524
 
21679
22525
  static inline int get_prev_opcode(JSFunctionDef *fd) {
21680
- if (fd->last_opcode_pos < 0)
22526
+ if (fd->last_opcode_pos < 0 || dbuf_error(&fd->byte_code))
21681
22527
  return OP_invalid;
21682
22528
  else
21683
22529
  return fd->byte_code.buf[fd->last_opcode_pos];
@@ -21742,7 +22588,11 @@ static void emit_op(JSParseState *s, uint8_t val)
21742
22588
 
21743
22589
  static void emit_atom(JSParseState *s, JSAtom name)
21744
22590
  {
21745
- emit_u32(s, JS_DupAtom(s->ctx, name));
22591
+ DynBuf *bc = &s->cur_func->byte_code;
22592
+ if (dbuf_realloc(bc, bc->size + 4))
22593
+ return; /* not enough memory : don't duplicate the atom */
22594
+ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name));
22595
+ bc->size += 4;
21746
22596
  }
21747
22597
 
21748
22598
  static int update_label(JSFunctionDef *s, int label, int delta)
@@ -21756,29 +22606,33 @@ static int update_label(JSFunctionDef *s, int label, int delta)
21756
22606
  return ls->ref_count;
21757
22607
  }
21758
22608
 
21759
- static int new_label_fd(JSFunctionDef *fd, int label)
22609
+ static int new_label_fd(JSFunctionDef *fd)
21760
22610
  {
22611
+ int label;
21761
22612
  LabelSlot *ls;
21762
22613
 
21763
- if (label < 0) {
21764
- if (js_resize_array(fd->ctx, (void *)&fd->label_slots,
21765
- sizeof(fd->label_slots[0]),
21766
- &fd->label_size, fd->label_count + 1))
21767
- return -1;
21768
- label = fd->label_count++;
21769
- ls = &fd->label_slots[label];
21770
- ls->ref_count = 0;
21771
- ls->pos = -1;
21772
- ls->pos2 = -1;
21773
- ls->addr = -1;
21774
- ls->first_reloc = NULL;
21775
- }
22614
+ if (js_resize_array(fd->ctx, (void *)&fd->label_slots,
22615
+ sizeof(fd->label_slots[0]),
22616
+ &fd->label_size, fd->label_count + 1))
22617
+ return -1;
22618
+ label = fd->label_count++;
22619
+ ls = &fd->label_slots[label];
22620
+ ls->ref_count = 0;
22621
+ ls->pos = -1;
22622
+ ls->pos2 = -1;
22623
+ ls->addr = -1;
22624
+ ls->first_reloc = NULL;
21776
22625
  return label;
21777
22626
  }
21778
22627
 
21779
22628
  static int new_label(JSParseState *s)
21780
22629
  {
21781
- return new_label_fd(s->cur_func, -1);
22630
+ int label;
22631
+ label = new_label_fd(s->cur_func);
22632
+ if (unlikely(label < 0)) {
22633
+ dbuf_set_error(&s->cur_func->byte_code);
22634
+ }
22635
+ return label;
21782
22636
  }
21783
22637
 
21784
22638
  /* don't update the last opcode and don't emit line number info */
@@ -21806,8 +22660,11 @@ static int emit_label(JSParseState *s, int label)
21806
22660
  static int emit_goto(JSParseState *s, int opcode, int label)
21807
22661
  {
21808
22662
  if (js_is_live_code(s)) {
21809
- if (label < 0)
22663
+ if (label < 0) {
21810
22664
  label = new_label(s);
22665
+ if (label < 0)
22666
+ return -1;
22667
+ }
21811
22668
  emit_op(s, opcode);
21812
22669
  emit_u32(s, label);
21813
22670
  s->cur_func->label_slots[label].ref_count++;
@@ -23848,6 +24705,8 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
23848
24705
  switch(opcode) {
23849
24706
  case OP_scope_get_var:
23850
24707
  label = new_label(s);
24708
+ if (label < 0)
24709
+ return -1;
23851
24710
  emit_op(s, OP_scope_make_ref);
23852
24711
  emit_atom(s, name);
23853
24712
  emit_u32(s, label);
@@ -23866,10 +24725,7 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
23866
24725
  emit_u16(s, scope);
23867
24726
  break;
23868
24727
  case OP_get_array_el:
23869
- /* XXX: replace by a single opcode ? */
23870
- emit_op(s, OP_to_propkey2);
23871
- emit_op(s, OP_dup2);
23872
- emit_op(s, OP_get_array_el);
24728
+ emit_op(s, OP_get_array_el3);
23873
24729
  break;
23874
24730
  case OP_get_super_value:
23875
24731
  emit_op(s, OP_to_propkey);
@@ -23883,6 +24739,8 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
23883
24739
  switch(opcode) {
23884
24740
  case OP_scope_get_var:
23885
24741
  label = new_label(s);
24742
+ if (label < 0)
24743
+ return -1;
23886
24744
  emit_op(s, OP_scope_make_ref);
23887
24745
  emit_atom(s, name);
23888
24746
  emit_u32(s, label);
@@ -24298,7 +25156,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
24298
25156
  continue;
24299
25157
  }
24300
25158
  if (prop_name == JS_ATOM_NULL) {
24301
- emit_op(s, OP_to_propkey2);
25159
+ emit_op(s, OP_to_propkey);
24302
25160
  if (has_ellipsis) {
24303
25161
  /* define the property in excludeList */
24304
25162
  emit_op(s, OP_perm3);
@@ -24892,6 +25750,23 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
24892
25750
  return js_parse_error(s, "invalid use of 'import()'");
24893
25751
  if (js_parse_assign_expr(s))
24894
25752
  return -1;
25753
+ if (s->token.val == ',') {
25754
+ if (next_token(s))
25755
+ return -1;
25756
+ if (s->token.val != ')') {
25757
+ if (js_parse_assign_expr(s))
25758
+ return -1;
25759
+ /* accept a trailing comma */
25760
+ if (s->token.val == ',') {
25761
+ if (next_token(s))
25762
+ return -1;
25763
+ }
25764
+ } else {
25765
+ emit_op(s, OP_undefined);
25766
+ }
25767
+ } else {
25768
+ emit_op(s, OP_undefined);
25769
+ }
24895
25770
  if (js_parse_expect(s, ')'))
24896
25771
  return -1;
24897
25772
  emit_op(s, OP_import);
@@ -24908,6 +25783,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
24908
25783
  BOOL has_optional_chain = FALSE;
24909
25784
 
24910
25785
  if (s->token.val == TOK_QUESTION_MARK_DOT) {
25786
+ if ((parse_flags & PF_POSTFIX_CALL) == 0)
25787
+ return js_parse_error(s, "new keyword cannot be used with an optional chain");
24911
25788
  op_token_ptr = s->token.ptr;
24912
25789
  /* optional chaining */
24913
25790
  if (next_token(s))
@@ -27451,7 +28328,7 @@ fail:
27451
28328
  return -1;
27452
28329
  }
27453
28330
 
27454
- /* 'name' is freed */
28331
+ /* 'name' is freed. The module is referenced by 'ctx->loaded_modules' */
27455
28332
  static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
27456
28333
  {
27457
28334
  JSModuleDef *m;
@@ -27461,6 +28338,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
27461
28338
  return NULL;
27462
28339
  }
27463
28340
  m->header.ref_count = 1;
28341
+ add_gc_object(ctx->rt, &m->header, JS_GC_OBJ_TYPE_MODULE);
27464
28342
  m->module_name = name;
27465
28343
  m->module_ns = JS_UNDEFINED;
27466
28344
  m->func_obj = JS_UNDEFINED;
@@ -27469,6 +28347,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
27469
28347
  m->promise = JS_UNDEFINED;
27470
28348
  m->resolving_funcs[0] = JS_UNDEFINED;
27471
28349
  m->resolving_funcs[1] = JS_UNDEFINED;
28350
+ m->private_value = JS_UNDEFINED;
27472
28351
  list_add_tail(&m->link, &ctx->loaded_modules);
27473
28352
  return m;
27474
28353
  }
@@ -27478,6 +28357,11 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
27478
28357
  {
27479
28358
  int i;
27480
28359
 
28360
+ for(i = 0; i < m->req_module_entries_count; i++) {
28361
+ JSReqModuleEntry *rme = &m->req_module_entries[i];
28362
+ JS_MarkValue(rt, rme->attributes, mark_func);
28363
+ }
28364
+
27481
28365
  for(i = 0; i < m->export_entries_count; i++) {
27482
28366
  JSExportEntry *me = &m->export_entries[i];
27483
28367
  if (me->export_type == JS_EXPORT_TYPE_LOCAL &&
@@ -27493,61 +28377,65 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
27493
28377
  JS_MarkValue(rt, m->promise, mark_func);
27494
28378
  JS_MarkValue(rt, m->resolving_funcs[0], mark_func);
27495
28379
  JS_MarkValue(rt, m->resolving_funcs[1], mark_func);
28380
+ JS_MarkValue(rt, m->private_value, mark_func);
27496
28381
  }
27497
28382
 
27498
- static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
28383
+ static void js_free_module_def(JSRuntime *rt, JSModuleDef *m)
27499
28384
  {
27500
28385
  int i;
27501
28386
 
27502
- JS_FreeAtom(ctx, m->module_name);
28387
+ JS_FreeAtomRT(rt, m->module_name);
27503
28388
 
27504
28389
  for(i = 0; i < m->req_module_entries_count; i++) {
27505
28390
  JSReqModuleEntry *rme = &m->req_module_entries[i];
27506
- JS_FreeAtom(ctx, rme->module_name);
28391
+ JS_FreeAtomRT(rt, rme->module_name);
28392
+ JS_FreeValueRT(rt, rme->attributes);
27507
28393
  }
27508
- js_free(ctx, m->req_module_entries);
28394
+ js_free_rt(rt, m->req_module_entries);
27509
28395
 
27510
28396
  for(i = 0; i < m->export_entries_count; i++) {
27511
28397
  JSExportEntry *me = &m->export_entries[i];
27512
28398
  if (me->export_type == JS_EXPORT_TYPE_LOCAL)
27513
- free_var_ref(ctx->rt, me->u.local.var_ref);
27514
- JS_FreeAtom(ctx, me->export_name);
27515
- JS_FreeAtom(ctx, me->local_name);
28399
+ free_var_ref(rt, me->u.local.var_ref);
28400
+ JS_FreeAtomRT(rt, me->export_name);
28401
+ JS_FreeAtomRT(rt, me->local_name);
27516
28402
  }
27517
- js_free(ctx, m->export_entries);
28403
+ js_free_rt(rt, m->export_entries);
27518
28404
 
27519
- js_free(ctx, m->star_export_entries);
28405
+ js_free_rt(rt, m->star_export_entries);
27520
28406
 
27521
28407
  for(i = 0; i < m->import_entries_count; i++) {
27522
28408
  JSImportEntry *mi = &m->import_entries[i];
27523
- JS_FreeAtom(ctx, mi->import_name);
28409
+ JS_FreeAtomRT(rt, mi->import_name);
27524
28410
  }
27525
- js_free(ctx, m->import_entries);
27526
- js_free(ctx, m->async_parent_modules);
28411
+ js_free_rt(rt, m->import_entries);
28412
+ js_free_rt(rt, m->async_parent_modules);
27527
28413
 
27528
- JS_FreeValue(ctx, m->module_ns);
27529
- JS_FreeValue(ctx, m->func_obj);
27530
- JS_FreeValue(ctx, m->eval_exception);
27531
- JS_FreeValue(ctx, m->meta_obj);
27532
- JS_FreeValue(ctx, m->promise);
27533
- JS_FreeValue(ctx, m->resolving_funcs[0]);
27534
- JS_FreeValue(ctx, m->resolving_funcs[1]);
27535
- list_del(&m->link);
27536
- js_free(ctx, m);
28414
+ JS_FreeValueRT(rt, m->module_ns);
28415
+ JS_FreeValueRT(rt, m->func_obj);
28416
+ JS_FreeValueRT(rt, m->eval_exception);
28417
+ JS_FreeValueRT(rt, m->meta_obj);
28418
+ JS_FreeValueRT(rt, m->promise);
28419
+ JS_FreeValueRT(rt, m->resolving_funcs[0]);
28420
+ JS_FreeValueRT(rt, m->resolving_funcs[1]);
28421
+ JS_FreeValueRT(rt, m->private_value);
28422
+ /* during the GC the finalizers are called in an arbitrary
28423
+ order so the module may no longer be referenced by the JSContext list */
28424
+ if (m->link.next) {
28425
+ list_del(&m->link);
28426
+ }
28427
+ remove_gc_object(&m->header);
28428
+ if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && m->header.ref_count != 0) {
28429
+ list_add_tail(&m->header.link, &rt->gc_zero_ref_count_list);
28430
+ } else {
28431
+ js_free_rt(rt, m);
28432
+ }
27537
28433
  }
27538
28434
 
27539
28435
  static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
27540
28436
  JSAtom module_name)
27541
28437
  {
27542
28438
  JSReqModuleEntry *rme;
27543
- int i;
27544
-
27545
- /* no need to add the module request if it is already present */
27546
- for(i = 0; i < m->req_module_entries_count; i++) {
27547
- rme = &m->req_module_entries[i];
27548
- if (rme->module_name == module_name)
27549
- return i;
27550
- }
27551
28439
 
27552
28440
  if (js_resize_array(ctx, (void **)&m->req_module_entries,
27553
28441
  sizeof(JSReqModuleEntry),
@@ -27557,7 +28445,8 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
27557
28445
  rme = &m->req_module_entries[m->req_module_entries_count++];
27558
28446
  rme->module_name = JS_DupAtom(ctx, module_name);
27559
28447
  rme->module = NULL;
27560
- return i;
28448
+ rme->attributes = JS_UNDEFINED;
28449
+ return m->req_module_entries_count - 1;
27561
28450
  }
27562
28451
 
27563
28452
  static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,
@@ -27637,6 +28526,8 @@ JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
27637
28526
  if (name == JS_ATOM_NULL)
27638
28527
  return NULL;
27639
28528
  m = js_new_module_def(ctx, name);
28529
+ if (!m)
28530
+ return NULL;
27640
28531
  m->init_func = func;
27641
28532
  return m;
27642
28533
  }
@@ -27676,12 +28567,38 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
27676
28567
  return -1;
27677
28568
  }
27678
28569
 
28570
+ int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val)
28571
+ {
28572
+ set_value(ctx, &m->private_value, val);
28573
+ return 0;
28574
+ }
28575
+
28576
+ JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m)
28577
+ {
28578
+ return JS_DupValue(ctx, m->private_value);
28579
+ }
28580
+
27679
28581
  void JS_SetModuleLoaderFunc(JSRuntime *rt,
27680
28582
  JSModuleNormalizeFunc *module_normalize,
27681
28583
  JSModuleLoaderFunc *module_loader, void *opaque)
27682
28584
  {
27683
28585
  rt->module_normalize_func = module_normalize;
27684
- rt->module_loader_func = module_loader;
28586
+ rt->module_loader_has_attr = FALSE;
28587
+ rt->u.module_loader_func = module_loader;
28588
+ rt->module_check_attrs = NULL;
28589
+ rt->module_loader_opaque = opaque;
28590
+ }
28591
+
28592
+ void JS_SetModuleLoaderFunc2(JSRuntime *rt,
28593
+ JSModuleNormalizeFunc *module_normalize,
28594
+ JSModuleLoaderFunc2 *module_loader,
28595
+ JSModuleCheckSupportedImportAttributes *module_check_attrs,
28596
+ void *opaque)
28597
+ {
28598
+ rt->module_normalize_func = module_normalize;
28599
+ rt->module_loader_has_attr = TRUE;
28600
+ rt->u.module_loader_func2 = module_loader;
28601
+ rt->module_check_attrs = module_check_attrs;
27685
28602
  rt->module_loader_opaque = opaque;
27686
28603
  }
27687
28604
 
@@ -27762,7 +28679,8 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name)
27762
28679
  /* return NULL in case of exception (e.g. module could not be loaded) */
27763
28680
  static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
27764
28681
  const char *base_cname,
27765
- const char *cname1)
28682
+ const char *cname1,
28683
+ JSValueConst attributes)
27766
28684
  {
27767
28685
  JSRuntime *rt = ctx->rt;
27768
28686
  JSModuleDef *m;
@@ -27795,22 +28713,26 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
27795
28713
  JS_FreeAtom(ctx, module_name);
27796
28714
 
27797
28715
  /* load the module */
27798
- if (!rt->module_loader_func) {
28716
+ if (!rt->u.module_loader_func) {
27799
28717
  /* XXX: use a syntax error ? */
27800
28718
  JS_ThrowReferenceError(ctx, "could not load module '%s'",
27801
28719
  cname);
27802
28720
  js_free(ctx, cname);
27803
28721
  return NULL;
27804
28722
  }
27805
-
27806
- m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque);
28723
+ if (rt->module_loader_has_attr) {
28724
+ m = rt->u.module_loader_func2(ctx, cname, rt->module_loader_opaque, attributes);
28725
+ } else {
28726
+ m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque);
28727
+ }
27807
28728
  js_free(ctx, cname);
27808
28729
  return m;
27809
28730
  }
27810
28731
 
27811
28732
  static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,
27812
- JSAtom base_module_name,
27813
- JSAtom module_name1)
28733
+ JSAtom base_module_name,
28734
+ JSAtom module_name1,
28735
+ JSValueConst attributes)
27814
28736
  {
27815
28737
  const char *base_cname, *cname;
27816
28738
  JSModuleDef *m;
@@ -27823,7 +28745,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,
27823
28745
  JS_FreeCString(ctx, base_cname);
27824
28746
  return NULL;
27825
28747
  }
27826
- m = js_host_resolve_imported_module(ctx, base_cname, cname);
28748
+ m = js_host_resolve_imported_module(ctx, base_cname, cname, attributes);
27827
28749
  JS_FreeCString(ctx, base_cname);
27828
28750
  JS_FreeCString(ctx, cname);
27829
28751
  return m;
@@ -28285,7 +29207,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m)
28285
29207
  for(i = 0; i < m->req_module_entries_count; i++) {
28286
29208
  JSReqModuleEntry *rme = &m->req_module_entries[i];
28287
29209
  m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,
28288
- rme->module_name);
29210
+ rme->module_name,
29211
+ rme->attributes);
28289
29212
  if (!m1)
28290
29213
  return -1;
28291
29214
  rme->module = m1;
@@ -28512,7 +29435,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m,
28512
29435
  printf(": ");
28513
29436
  #endif
28514
29437
  m1 = m->req_module_entries[mi->req_module_idx].module;
28515
- if (mi->import_name == JS_ATOM__star_) {
29438
+ if (mi->is_star) {
28516
29439
  JSValue val;
28517
29440
  /* name space import */
28518
29441
  val = JS_GetModuleNamespace(ctx, m1);
@@ -28762,14 +29685,15 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
28762
29685
 
28763
29686
  static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
28764
29687
  const char *filename,
28765
- JSValueConst *resolving_funcs)
29688
+ JSValueConst *resolving_funcs,
29689
+ JSValueConst attributes)
28766
29690
  {
28767
29691
  JSValue evaluate_promise;
28768
29692
  JSModuleDef *m;
28769
29693
  JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
28770
29694
  JSValueConst func_data[3];
28771
29695
 
28772
- m = js_host_resolve_imported_module(ctx, basename, filename);
29696
+ m = js_host_resolve_imported_module(ctx, basename, filename, attributes);
28773
29697
  if (!m)
28774
29698
  goto fail;
28775
29699
 
@@ -28816,7 +29740,7 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename,
28816
29740
  if (JS_IsException(promise))
28817
29741
  return JS_EXCEPTION;
28818
29742
  JS_LoadModuleInternal(ctx, basename, filename,
28819
- (JSValueConst *)resolving_funcs);
29743
+ (JSValueConst *)resolving_funcs, JS_UNDEFINED);
28820
29744
  JS_FreeValue(ctx, resolving_funcs[0]);
28821
29745
  JS_FreeValue(ctx, resolving_funcs[1]);
28822
29746
  return promise;
@@ -28828,6 +29752,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
28828
29752
  JSValueConst *resolving_funcs = argv;
28829
29753
  JSValueConst basename_val = argv[2];
28830
29754
  JSValueConst specifier = argv[3];
29755
+ JSValueConst attributes = argv[4];
28831
29756
  const char *basename = NULL, *filename;
28832
29757
  JSValue ret, err;
28833
29758
 
@@ -28844,7 +29769,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
28844
29769
  goto exception;
28845
29770
 
28846
29771
  JS_LoadModuleInternal(ctx, basename, filename,
28847
- resolving_funcs);
29772
+ resolving_funcs, attributes);
28848
29773
  JS_FreeCString(ctx, filename);
28849
29774
  JS_FreeCString(ctx, basename);
28850
29775
  return JS_UNDEFINED;
@@ -28858,11 +29783,12 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
28858
29783
  return JS_UNDEFINED;
28859
29784
  }
28860
29785
 
28861
- static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
29786
+ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options)
28862
29787
  {
28863
29788
  JSAtom basename;
28864
- JSValue promise, resolving_funcs[2], basename_val;
28865
- JSValueConst args[4];
29789
+ JSValue promise, resolving_funcs[2], basename_val, err, ret;
29790
+ JSValue specifier_str = JS_UNDEFINED, attributes = JS_UNDEFINED, attributes_obj = JS_UNDEFINED;
29791
+ JSValueConst args[5];
28866
29792
 
28867
29793
  basename = JS_GetScriptOrModuleName(ctx, 0);
28868
29794
  if (basename == JS_ATOM_NULL)
@@ -28879,19 +29805,82 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
28879
29805
  return promise;
28880
29806
  }
28881
29807
 
29808
+ /* the string conversion must occur here */
29809
+ specifier_str = JS_ToString(ctx, specifier);
29810
+ if (JS_IsException(specifier_str))
29811
+ goto exception;
29812
+
29813
+ if (!JS_IsUndefined(options)) {
29814
+ if (!JS_IsObject(options)) {
29815
+ JS_ThrowTypeError(ctx, "options must be an object");
29816
+ goto exception;
29817
+ }
29818
+ attributes_obj = JS_GetProperty(ctx, options, JS_ATOM_with);
29819
+ if (JS_IsException(attributes_obj))
29820
+ goto exception;
29821
+ if (!JS_IsUndefined(attributes_obj)) {
29822
+ JSPropertyEnum *atoms;
29823
+ uint32_t atoms_len, i;
29824
+ JSValue val;
29825
+
29826
+ if (!JS_IsObject(attributes_obj)) {
29827
+ JS_ThrowTypeError(ctx, "options.with must be an object");
29828
+ goto exception;
29829
+ }
29830
+ attributes = JS_NewObjectProto(ctx, JS_NULL);
29831
+ if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &atoms_len, JS_VALUE_GET_OBJ(attributes_obj),
29832
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
29833
+ goto exception;
29834
+ }
29835
+ for(i = 0; i < atoms_len; i++) {
29836
+ val = JS_GetProperty(ctx, attributes_obj, atoms[i].atom);
29837
+ if (JS_IsException(val))
29838
+ goto exception1;
29839
+ if (!JS_IsString(val)) {
29840
+ JS_FreeValue(ctx, val);
29841
+ JS_ThrowTypeError(ctx, "module attribute values must be strings");
29842
+ goto exception1;
29843
+ }
29844
+ if (JS_DefinePropertyValue(ctx, attributes, atoms[i].atom, val,
29845
+ JS_PROP_C_W_E) < 0) {
29846
+ exception1:
29847
+ JS_FreePropertyEnum(ctx, atoms, atoms_len);
29848
+ goto exception;
29849
+ }
29850
+ }
29851
+ JS_FreePropertyEnum(ctx, atoms, atoms_len);
29852
+ if (ctx->rt->module_check_attrs &&
29853
+ ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, attributes) < 0) {
29854
+ goto exception;
29855
+ }
29856
+ JS_FreeValue(ctx, attributes_obj);
29857
+ }
29858
+ }
29859
+
28882
29860
  args[0] = resolving_funcs[0];
28883
29861
  args[1] = resolving_funcs[1];
28884
29862
  args[2] = basename_val;
28885
- args[3] = specifier;
28886
-
29863
+ args[3] = specifier_str;
29864
+ args[4] = attributes;
29865
+
28887
29866
  /* cannot run JS_LoadModuleInternal synchronously because it would
28888
29867
  cause an unexpected recursion in js_evaluate_module() */
28889
- JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
28890
-
29868
+ JS_EnqueueJob(ctx, js_dynamic_import_job, 5, args);
29869
+ done:
28891
29870
  JS_FreeValue(ctx, basename_val);
28892
29871
  JS_FreeValue(ctx, resolving_funcs[0]);
28893
29872
  JS_FreeValue(ctx, resolving_funcs[1]);
29873
+ JS_FreeValue(ctx, specifier_str);
29874
+ JS_FreeValue(ctx, attributes);
28894
29875
  return promise;
29876
+ exception:
29877
+ JS_FreeValue(ctx, attributes_obj);
29878
+ err = JS_GetException(ctx);
29879
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
29880
+ 1, (JSValueConst *)&err);
29881
+ JS_FreeValue(ctx, ret);
29882
+ JS_FreeValue(ctx, err);
29883
+ goto done;
28895
29884
  }
28896
29885
 
28897
29886
  static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m)
@@ -28968,6 +29957,14 @@ static int exec_module_list_cmp(const void *p1, const void *p2, void *opaque)
28968
29957
  static int js_execute_async_module(JSContext *ctx, JSModuleDef *m);
28969
29958
  static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
28970
29959
  JSValue *pvalue);
29960
+ #ifdef DUMP_MODULE_EXEC
29961
+ static void js_dump_module(JSContext *ctx, const char *str, JSModuleDef *m)
29962
+ {
29963
+ char buf1[ATOM_GET_STR_BUF_SIZE];
29964
+ static const char *module_status_str[] = { "unlinked", "linking", "linked", "evaluating", "evaluating_async", "evaluated" };
29965
+ printf("%s: %s status=%s\n", str, JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name), module_status_str[m->status]);
29966
+ }
29967
+ #endif
28971
29968
 
28972
29969
  static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val,
28973
29970
  int argc, JSValueConst *argv, int magic, JSValue *func_data)
@@ -28976,6 +29973,9 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
28976
29973
  JSValueConst error = argv[0];
28977
29974
  int i;
28978
29975
 
29976
+ #ifdef DUMP_MODULE_EXEC
29977
+ js_dump_module(ctx, __func__, module);
29978
+ #endif
28979
29979
  if (js_check_stack_overflow(ctx->rt, 0))
28980
29980
  return JS_ThrowStackOverflow(ctx);
28981
29981
 
@@ -28991,6 +29991,7 @@ static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
28991
29991
  module->eval_has_exception = TRUE;
28992
29992
  module->eval_exception = JS_DupValue(ctx, error);
28993
29993
  module->status = JS_MODULE_STATUS_EVALUATED;
29994
+ module->async_evaluation = FALSE;
28994
29995
 
28995
29996
  for(i = 0; i < module->async_parent_modules_count; i++) {
28996
29997
  JSModuleDef *m = module->async_parent_modules[i];
@@ -29017,6 +30018,9 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
29017
30018
  ExecModuleList exec_list_s, *exec_list = &exec_list_s;
29018
30019
  int i;
29019
30020
 
30021
+ #ifdef DUMP_MODULE_EXEC
30022
+ js_dump_module(ctx, __func__, module);
30023
+ #endif
29020
30024
  if (module->status == JS_MODULE_STATUS_EVALUATED) {
29021
30025
  assert(module->eval_has_exception);
29022
30026
  return JS_UNDEFINED;
@@ -29042,6 +30046,9 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
29042
30046
 
29043
30047
  for(i = 0; i < exec_list->count; i++) {
29044
30048
  JSModuleDef *m = exec_list->tab[i];
30049
+ #ifdef DUMP_MODULE_EXEC
30050
+ printf(" %d/%d", i, exec_list->count); js_dump_module(ctx, "", m);
30051
+ #endif
29045
30052
  if (m->status == JS_MODULE_STATUS_EVALUATED) {
29046
30053
  assert(m->eval_has_exception);
29047
30054
  } else if (m->has_tla) {
@@ -29056,6 +30063,7 @@ static JSValue js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
29056
30063
  JS_FreeValue(ctx, m_obj);
29057
30064
  JS_FreeValue(ctx, error);
29058
30065
  } else {
30066
+ m->async_evaluation = FALSE;
29059
30067
  js_set_module_evaluated(ctx, m);
29060
30068
  }
29061
30069
  }
@@ -29068,6 +30076,9 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m)
29068
30076
  {
29069
30077
  JSValue promise, m_obj;
29070
30078
  JSValue resolve_funcs[2], ret_val;
30079
+ #ifdef DUMP_MODULE_EXEC
30080
+ js_dump_module(ctx, __func__, m);
30081
+ #endif
29071
30082
  promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 0);
29072
30083
  if (JS_IsException(promise))
29073
30084
  return -1;
@@ -29087,6 +30098,9 @@ static int js_execute_async_module(JSContext *ctx, JSModuleDef *m)
29087
30098
  static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
29088
30099
  JSValue *pvalue)
29089
30100
  {
30101
+ #ifdef DUMP_MODULE_EXEC
30102
+ js_dump_module(ctx, __func__, m);
30103
+ #endif
29090
30104
  if (m->init_func) {
29091
30105
  /* C module init : no asynchronous execution */
29092
30106
  if (m->init_func(ctx, m) < 0)
@@ -29126,19 +30140,16 @@ static int js_inner_module_evaluation(JSContext *ctx, JSModuleDef *m,
29126
30140
  JSModuleDef *m1;
29127
30141
  int i;
29128
30142
 
30143
+ #ifdef DUMP_MODULE_EXEC
30144
+ js_dump_module(ctx, __func__, m);
30145
+ #endif
30146
+
29129
30147
  if (js_check_stack_overflow(ctx->rt, 0)) {
29130
30148
  JS_ThrowStackOverflow(ctx);
29131
30149
  *pvalue = JS_GetException(ctx);
29132
30150
  return -1;
29133
30151
  }
29134
30152
 
29135
- #ifdef DUMP_MODULE_RESOLVE
29136
- {
29137
- char buf1[ATOM_GET_STR_BUF_SIZE];
29138
- printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, sizeof(buf1), m->module_name));
29139
- }
29140
- #endif
29141
-
29142
30153
  if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
29143
30154
  m->status == JS_MODULE_STATUS_EVALUATED) {
29144
30155
  if (m->eval_has_exception) {
@@ -29239,6 +30250,9 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
29239
30250
  JSModuleDef *m1, *stack_top;
29240
30251
  JSValue ret_val, result;
29241
30252
 
30253
+ #ifdef DUMP_MODULE_EXEC
30254
+ js_dump_module(ctx, __func__, m);
30255
+ #endif
29242
30256
  assert(m->status == JS_MODULE_STATUS_LINKED ||
29243
30257
  m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
29244
30258
  m->status == JS_MODULE_STATUS_EVALUATED);
@@ -29271,6 +30285,9 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
29271
30285
  1, (JSValueConst *)&m->eval_exception);
29272
30286
  JS_FreeValue(ctx, ret_val);
29273
30287
  } else {
30288
+ #ifdef DUMP_MODULE_EXEC
30289
+ js_dump_module(ctx, " done", m);
30290
+ #endif
29274
30291
  assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
29275
30292
  m->status == JS_MODULE_STATUS_EVALUATED);
29276
30293
  assert(!m->eval_has_exception);
@@ -29287,27 +30304,109 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
29287
30304
  return JS_DupValue(ctx, m->promise);
29288
30305
  }
29289
30306
 
29290
- static __exception JSAtom js_parse_from_clause(JSParseState *s)
30307
+ static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme)
30308
+ {
30309
+ JSContext *ctx = s->ctx;
30310
+ JSAtom key;
30311
+ int ret;
30312
+ const uint8_t *key_token_ptr;
30313
+
30314
+ if (next_token(s))
30315
+ return -1;
30316
+ if (js_parse_expect(s, '{'))
30317
+ return -1;
30318
+ while (s->token.val != '}') {
30319
+ key_token_ptr = s->token.ptr;
30320
+ if (s->token.val == TOK_STRING) {
30321
+ key = JS_ValueToAtom(ctx, s->token.u.str.str);
30322
+ if (key == JS_ATOM_NULL)
30323
+ return -1;
30324
+ } else {
30325
+ if (!token_is_ident(s->token.val)) {
30326
+ js_parse_error(s, "identifier expected");
30327
+ return -1;
30328
+ }
30329
+ key = JS_DupAtom(ctx, s->token.u.ident.atom);
30330
+ }
30331
+ if (next_token(s))
30332
+ return -1;
30333
+ if (js_parse_expect(s, ':')) {
30334
+ JS_FreeAtom(ctx, key);
30335
+ return -1;
30336
+ }
30337
+ if (s->token.val != TOK_STRING) {
30338
+ js_parse_error_pos(s, key_token_ptr, "string expected");
30339
+ return -1;
30340
+ }
30341
+ if (JS_IsUndefined(rme->attributes)) {
30342
+ JSValue attributes = JS_NewObjectProto(ctx, JS_NULL);
30343
+ if (JS_IsException(attributes)) {
30344
+ JS_FreeAtom(ctx, key);
30345
+ return -1;
30346
+ }
30347
+ rme->attributes = attributes;
30348
+ }
30349
+ ret = JS_HasProperty(ctx, rme->attributes, key);
30350
+ if (ret != 0) {
30351
+ JS_FreeAtom(ctx, key);
30352
+ if (ret < 0)
30353
+ return -1;
30354
+ else
30355
+ return js_parse_error(s, "duplicate with key");
30356
+ }
30357
+ ret = JS_DefinePropertyValue(ctx, rme->attributes, key,
30358
+ JS_DupValue(ctx, s->token.u.str.str), JS_PROP_C_W_E);
30359
+ JS_FreeAtom(ctx, key);
30360
+ if (ret < 0)
30361
+ return -1;
30362
+ if (next_token(s))
30363
+ return -1;
30364
+ if (s->token.val != ',')
30365
+ break;
30366
+ if (next_token(s))
30367
+ return -1;
30368
+ }
30369
+ if (!JS_IsUndefined(rme->attributes) &&
30370
+ ctx->rt->module_check_attrs &&
30371
+ ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) {
30372
+ return -1;
30373
+ }
30374
+ return js_parse_expect(s, '}');
30375
+ }
30376
+
30377
+ /* return the module index in m->req_module_entries[] or < 0 if error */
30378
+ static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m)
29291
30379
  {
29292
30380
  JSAtom module_name;
30381
+ int idx;
30382
+
29293
30383
  if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
29294
30384
  js_parse_error(s, "from clause expected");
29295
- return JS_ATOM_NULL;
30385
+ return -1;
29296
30386
  }
29297
30387
  if (next_token(s))
29298
- return JS_ATOM_NULL;
30388
+ return -1;
29299
30389
  if (s->token.val != TOK_STRING) {
29300
30390
  js_parse_error(s, "string expected");
29301
- return JS_ATOM_NULL;
30391
+ return -1;
29302
30392
  }
29303
30393
  module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);
29304
30394
  if (module_name == JS_ATOM_NULL)
29305
- return JS_ATOM_NULL;
30395
+ return -1;
29306
30396
  if (next_token(s)) {
29307
30397
  JS_FreeAtom(s->ctx, module_name);
29308
- return JS_ATOM_NULL;
30398
+ return -1;
30399
+ }
30400
+
30401
+ idx = add_req_module_entry(s->ctx, m, module_name);
30402
+ JS_FreeAtom(s->ctx, module_name);
30403
+ if (idx < 0)
30404
+ return -1;
30405
+ if (s->token.val == TOK_WITH) {
30406
+ if (js_parse_with_clause(s, &m->req_module_entries[idx]))
30407
+ return -1;
29309
30408
  }
29310
- return module_name;
30409
+ return idx;
29311
30410
  }
29312
30411
 
29313
30412
  static __exception int js_parse_export(JSParseState *s)
@@ -29316,7 +30415,6 @@ static __exception int js_parse_export(JSParseState *s)
29316
30415
  JSModuleDef *m = s->cur_func->module;
29317
30416
  JSAtom local_name, export_name;
29318
30417
  int first_export, idx, i, tok;
29319
- JSAtom module_name;
29320
30418
  JSExportEntry *me;
29321
30419
 
29322
30420
  if (next_token(s))
@@ -29352,11 +30450,21 @@ static __exception int js_parse_export(JSParseState *s)
29352
30450
  if (token_is_pseudo_keyword(s, JS_ATOM_as)) {
29353
30451
  if (next_token(s))
29354
30452
  goto fail;
29355
- if (!token_is_ident(s->token.val)) {
29356
- js_parse_error(s, "identifier expected");
29357
- goto fail;
30453
+ if (s->token.val == TOK_STRING) {
30454
+ if (js_string_find_invalid_codepoint(JS_VALUE_GET_STRING(s->token.u.str.str)) >= 0) {
30455
+ js_parse_error(s, "contains unpaired surrogate");
30456
+ goto fail;
30457
+ }
30458
+ export_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);
30459
+ if (export_name == JS_ATOM_NULL)
30460
+ goto fail;
30461
+ } else {
30462
+ if (!token_is_ident(s->token.val)) {
30463
+ js_parse_error(s, "identifier expected");
30464
+ goto fail;
30465
+ }
30466
+ export_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29358
30467
  }
29359
- export_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29360
30468
  if (next_token(s)) {
29361
30469
  fail:
29362
30470
  JS_FreeAtom(ctx, local_name);
@@ -29381,11 +30489,7 @@ static __exception int js_parse_export(JSParseState *s)
29381
30489
  if (js_parse_expect(s, '}'))
29382
30490
  return -1;
29383
30491
  if (token_is_pseudo_keyword(s, JS_ATOM_from)) {
29384
- module_name = js_parse_from_clause(s);
29385
- if (module_name == JS_ATOM_NULL)
29386
- return -1;
29387
- idx = add_req_module_entry(ctx, m, module_name);
29388
- JS_FreeAtom(ctx, module_name);
30492
+ idx = js_parse_from_clause(s, m);
29389
30493
  if (idx < 0)
29390
30494
  return -1;
29391
30495
  for(i = first_export; i < m->export_entries_count; i++) {
@@ -29407,11 +30511,7 @@ static __exception int js_parse_export(JSParseState *s)
29407
30511
  export_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29408
30512
  if (next_token(s))
29409
30513
  goto fail1;
29410
- module_name = js_parse_from_clause(s);
29411
- if (module_name == JS_ATOM_NULL)
29412
- goto fail1;
29413
- idx = add_req_module_entry(ctx, m, module_name);
29414
- JS_FreeAtom(ctx, module_name);
30514
+ idx = js_parse_from_clause(s, m);
29415
30515
  if (idx < 0)
29416
30516
  goto fail1;
29417
30517
  me = add_export_entry(s, m, JS_ATOM__star_, export_name,
@@ -29421,11 +30521,7 @@ static __exception int js_parse_export(JSParseState *s)
29421
30521
  return -1;
29422
30522
  me->u.req_module_idx = idx;
29423
30523
  } else {
29424
- module_name = js_parse_from_clause(s);
29425
- if (module_name == JS_ATOM_NULL)
29426
- return -1;
29427
- idx = add_req_module_entry(ctx, m, module_name);
29428
- JS_FreeAtom(ctx, module_name);
30524
+ idx = js_parse_from_clause(s, m);
29429
30525
  if (idx < 0)
29430
30526
  return -1;
29431
30527
  if (add_star_export_entry(ctx, m, idx) < 0)
@@ -29479,12 +30575,11 @@ static int add_closure_var(JSContext *ctx, JSFunctionDef *s,
29479
30575
  JSVarKindEnum var_kind);
29480
30576
 
29481
30577
  static int add_import(JSParseState *s, JSModuleDef *m,
29482
- JSAtom local_name, JSAtom import_name)
30578
+ JSAtom local_name, JSAtom import_name, BOOL is_star)
29483
30579
  {
29484
30580
  JSContext *ctx = s->ctx;
29485
30581
  int i, var_idx;
29486
30582
  JSImportEntry *mi;
29487
- BOOL is_local;
29488
30583
 
29489
30584
  if (local_name == JS_ATOM_arguments || local_name == JS_ATOM_eval)
29490
30585
  return js_parse_error(s, "invalid import binding");
@@ -29496,8 +30591,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
29496
30591
  }
29497
30592
  }
29498
30593
 
29499
- is_local = (import_name == JS_ATOM__star_);
29500
- var_idx = add_closure_var(ctx, s->cur_func, is_local, FALSE,
30594
+ var_idx = add_closure_var(ctx, s->cur_func, is_star, FALSE,
29501
30595
  m->import_entries_count,
29502
30596
  local_name, TRUE, TRUE, FALSE);
29503
30597
  if (var_idx < 0)
@@ -29510,6 +30604,7 @@ static int add_import(JSParseState *s, JSModuleDef *m,
29510
30604
  mi = &m->import_entries[m->import_entries_count++];
29511
30605
  mi->import_name = JS_DupAtom(ctx, import_name);
29512
30606
  mi->var_idx = var_idx;
30607
+ mi->is_star = is_star;
29513
30608
  return 0;
29514
30609
  }
29515
30610
 
@@ -29532,6 +30627,14 @@ static __exception int js_parse_import(JSParseState *s)
29532
30627
  JS_FreeAtom(ctx, module_name);
29533
30628
  return -1;
29534
30629
  }
30630
+ idx = add_req_module_entry(ctx, m, module_name);
30631
+ JS_FreeAtom(ctx, module_name);
30632
+ if (idx < 0)
30633
+ return -1;
30634
+ if (s->token.val == TOK_WITH) {
30635
+ if (js_parse_with_clause(s, &m->req_module_entries[idx]))
30636
+ return -1;
30637
+ }
29535
30638
  } else {
29536
30639
  if (s->token.val == TOK_IDENT) {
29537
30640
  if (s->token.u.ident.is_reserved) {
@@ -29542,7 +30645,7 @@ static __exception int js_parse_import(JSParseState *s)
29542
30645
  import_name = JS_ATOM_default;
29543
30646
  if (next_token(s))
29544
30647
  goto fail;
29545
- if (add_import(s, m, local_name, import_name))
30648
+ if (add_import(s, m, local_name, import_name, FALSE))
29546
30649
  goto fail;
29547
30650
  JS_FreeAtom(ctx, local_name);
29548
30651
 
@@ -29568,7 +30671,7 @@ static __exception int js_parse_import(JSParseState *s)
29568
30671
  import_name = JS_ATOM__star_;
29569
30672
  if (next_token(s))
29570
30673
  goto fail;
29571
- if (add_import(s, m, local_name, import_name))
30674
+ if (add_import(s, m, local_name, import_name, TRUE))
29572
30675
  goto fail;
29573
30676
  JS_FreeAtom(ctx, local_name);
29574
30677
  } else if (s->token.val == '{') {
@@ -29576,11 +30679,24 @@ static __exception int js_parse_import(JSParseState *s)
29576
30679
  return -1;
29577
30680
 
29578
30681
  while (s->token.val != '}') {
29579
- if (!token_is_ident(s->token.val)) {
29580
- js_parse_error(s, "identifier expected");
29581
- return -1;
30682
+ BOOL is_string;
30683
+ if (s->token.val == TOK_STRING) {
30684
+ is_string = TRUE;
30685
+ if (js_string_find_invalid_codepoint(JS_VALUE_GET_STRING(s->token.u.str.str)) >= 0) {
30686
+ js_parse_error(s, "contains unpaired surrogate");
30687
+ return -1;
30688
+ }
30689
+ import_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);
30690
+ if (import_name == JS_ATOM_NULL)
30691
+ return -1;
30692
+ } else {
30693
+ is_string = FALSE;
30694
+ if (!token_is_ident(s->token.val)) {
30695
+ js_parse_error(s, "identifier expected");
30696
+ return -1;
30697
+ }
30698
+ import_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29582
30699
  }
29583
- import_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29584
30700
  local_name = JS_ATOM_NULL;
29585
30701
  if (next_token(s))
29586
30702
  goto fail;
@@ -29592,16 +30708,19 @@ static __exception int js_parse_import(JSParseState *s)
29592
30708
  goto fail;
29593
30709
  }
29594
30710
  local_name = JS_DupAtom(ctx, s->token.u.ident.atom);
29595
- if (next_token(s)) {
30711
+ if (next_token(s))
30712
+ goto fail;
30713
+ } else {
30714
+ if (is_string) {
30715
+ js_parse_error(s, "expecting 'as'");
29596
30716
  fail:
29597
30717
  JS_FreeAtom(ctx, local_name);
29598
30718
  JS_FreeAtom(ctx, import_name);
29599
30719
  return -1;
29600
30720
  }
29601
- } else {
29602
30721
  local_name = JS_DupAtom(ctx, import_name);
29603
30722
  }
29604
- if (add_import(s, m, local_name, import_name))
30723
+ if (add_import(s, m, local_name, import_name, FALSE))
29605
30724
  goto fail;
29606
30725
  JS_FreeAtom(ctx, local_name);
29607
30726
  JS_FreeAtom(ctx, import_name);
@@ -29614,14 +30733,10 @@ static __exception int js_parse_import(JSParseState *s)
29614
30733
  return -1;
29615
30734
  }
29616
30735
  end_import_clause:
29617
- module_name = js_parse_from_clause(s);
29618
- if (module_name == JS_ATOM_NULL)
30736
+ idx = js_parse_from_clause(s, m);
30737
+ if (idx < 0)
29619
30738
  return -1;
29620
30739
  }
29621
- idx = add_req_module_entry(ctx, m, module_name);
29622
- JS_FreeAtom(ctx, module_name);
29623
- if (idx < 0)
29624
- return -1;
29625
30740
  for(i = first_import; i < m->import_entries_count; i++)
29626
30741
  m->import_entries[i].req_module_idx = idx;
29627
30742
 
@@ -29686,7 +30801,7 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
29686
30801
 
29687
30802
  fd->is_eval = is_eval;
29688
30803
  fd->is_func_expr = is_func_expr;
29689
- js_dbuf_init(ctx, &fd->byte_code);
30804
+ js_dbuf_bytecode_init(ctx, &fd->byte_code);
29690
30805
  fd->last_opcode_pos = -1;
29691
30806
  fd->func_name = JS_ATOM_NULL;
29692
30807
  fd->var_object_idx = -1;
@@ -29744,6 +30859,8 @@ static void free_bytecode_atoms(JSRuntime *rt,
29744
30859
  case OP_FMT_atom_u16:
29745
30860
  case OP_FMT_atom_label_u8:
29746
30861
  case OP_FMT_atom_label_u16:
30862
+ if ((pos + 1 + 4) > bc_len)
30863
+ break; /* may happen if there is not enough memory when emiting bytecode */
29747
30864
  atom = get_u32(bc_buf + pos + 1);
29748
30865
  JS_FreeAtomRT(rt, atom);
29749
30866
  break;
@@ -30034,7 +31151,7 @@ static void dump_byte_code(JSContext *ctx, int pass,
30034
31151
  has_pool_idx:
30035
31152
  printf(" %u: ", idx);
30036
31153
  if (idx < cpool_count) {
30037
- JS_DumpValue(ctx, cpool[idx]);
31154
+ JS_PrintValue(ctx, js_dump_value_write, stdout, cpool[idx], NULL);
30038
31155
  }
30039
31156
  break;
30040
31157
  case OP_FMT_atom:
@@ -30533,7 +31650,13 @@ static void var_object_test(JSContext *ctx, JSFunctionDef *s,
30533
31650
  {
30534
31651
  dbuf_putc(bc, get_with_scope_opcode(op));
30535
31652
  dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
30536
- *plabel_done = new_label_fd(s, *plabel_done);
31653
+ if (*plabel_done < 0) {
31654
+ *plabel_done = new_label_fd(s);
31655
+ if (*plabel_done < 0) {
31656
+ dbuf_set_error(bc);
31657
+ return;
31658
+ }
31659
+ }
30537
31660
  dbuf_put_u32(bc, *plabel_done);
30538
31661
  dbuf_putc(bc, is_with);
30539
31662
  update_label(s, *plabel_done, 1);
@@ -31578,8 +32701,11 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
31578
32701
  evaluating the module so that the exported functions are
31579
32702
  visible if there are cyclic module references */
31580
32703
  if (s->module) {
31581
- label_next = new_label_fd(s, -1);
31582
-
32704
+ label_next = new_label_fd(s);
32705
+ if (label_next < 0) {
32706
+ dbuf_set_error(bc);
32707
+ return;
32708
+ }
31583
32709
  /* if 'this' is true, initialize the global variables and return */
31584
32710
  dbuf_putc(bc, OP_push_this);
31585
32711
  dbuf_putc(bc, OP_if_false);
@@ -31770,7 +32896,7 @@ static __exception int resolve_variables(JSContext *ctx, JSFunctionDef *s)
31770
32896
 
31771
32897
  cc.bc_buf = bc_buf = s->byte_code.buf;
31772
32898
  cc.bc_len = bc_len = s->byte_code.size;
31773
- js_dbuf_init(ctx, &bc_out);
32899
+ js_dbuf_bytecode_init(ctx, &bc_out);
31774
32900
 
31775
32901
  /* first pass for runtime checks (must be done before the
31776
32902
  variables are created) */
@@ -32390,7 +33516,7 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
32390
33516
 
32391
33517
  cc.bc_buf = bc_buf = s->byte_code.buf;
32392
33518
  cc.bc_len = bc_len = s->byte_code.size;
32393
- js_dbuf_init(ctx, &bc_out);
33519
+ js_dbuf_bytecode_init(ctx, &bc_out);
32394
33520
 
32395
33521
  #if SHORT_OPCODES
32396
33522
  if (s->jump_size) {
@@ -32868,9 +33994,8 @@ static __exception int resolve_labels(JSContext *ctx, JSFunctionDef *s)
32868
33994
  goto no_change;
32869
33995
 
32870
33996
  case OP_to_propkey:
32871
- case OP_to_propkey2:
32872
33997
  if (OPTIMIZE) {
32873
- /* remove redundant to_propkey/to_propkey2 opcodes when storing simple data */
33998
+ /* remove redundant to_propkey opcodes when storing simple data */
32874
33999
  if (code_match(&cc, pos_next, M3(OP_get_loc, OP_get_arg, OP_get_var_ref), -1, OP_put_array_el, -1)
32875
34000
  || code_match(&cc, pos_next, M3(OP_push_i32, OP_push_const, OP_push_atom_value), OP_put_array_el, -1)
32876
34001
  || code_match(&cc, pos_next, M4(OP_undefined, OP_null, OP_push_true, OP_push_false), OP_put_array_el, -1)) {
@@ -33799,7 +34924,8 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
33799
34924
  JS_AtomGetStrRT(rt, buf, sizeof(buf), b->func_name));
33800
34925
  }
33801
34926
  #endif
33802
- free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE);
34927
+ if (b->byte_code_buf)
34928
+ free_bytecode_atoms(rt, b->byte_code_buf, b->byte_code_len, TRUE);
33803
34929
 
33804
34930
  if (b->vardefs) {
33805
34931
  for(i = 0; i < b->arg_count + b->var_count; i++) {
@@ -34391,7 +35517,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
34391
35517
  push_scope(s); /* enter body scope */
34392
35518
  fd->body_scope = fd->scope_level;
34393
35519
 
34394
- if (s->token.val == TOK_ARROW) {
35520
+ if (s->token.val == TOK_ARROW && func_type == JS_PARSE_FUNC_ARROW) {
34395
35521
  if (next_token(s))
34396
35522
  goto fail;
34397
35523
 
@@ -34801,7 +35927,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
34801
35927
  fail1:
34802
35928
  /* XXX: should free all the unresolved dependencies */
34803
35929
  if (m)
34804
- js_free_module_def(ctx, m);
35930
+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
34805
35931
  return JS_EXCEPTION;
34806
35932
  }
34807
35933
 
@@ -35008,7 +36134,7 @@ typedef enum BCTagEnum {
35008
36134
  BC_TAG_OBJECT_REFERENCE,
35009
36135
  } BCTagEnum;
35010
36136
 
35011
- #define BC_VERSION 4
36137
+ #define BC_VERSION 5
35012
36138
 
35013
36139
  typedef struct BCWriterState {
35014
36140
  JSContext *ctx;
@@ -35430,6 +36556,8 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
35430
36556
  for(i = 0; i < m->req_module_entries_count; i++) {
35431
36557
  JSReqModuleEntry *rme = &m->req_module_entries[i];
35432
36558
  bc_put_atom(s, rme->module_name);
36559
+ if (JS_WriteObjectRec(s, rme->attributes))
36560
+ goto fail;
35433
36561
  }
35434
36562
 
35435
36563
  bc_put_leb128(s, m->export_entries_count);
@@ -35455,6 +36583,7 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
35455
36583
  for(i = 0; i < m->import_entries_count; i++) {
35456
36584
  JSImportEntry *mi = &m->import_entries[i];
35457
36585
  bc_put_leb128(s, mi->var_idx);
36586
+ bc_put_u8(s, mi->is_star);
35458
36587
  bc_put_atom(s, mi->import_name);
35459
36588
  bc_put_leb128(s, mi->req_module_idx);
35460
36589
  }
@@ -36428,8 +37557,13 @@ static JSValue JS_ReadModule(BCReaderState *s)
36428
37557
  goto fail;
36429
37558
  for(i = 0; i < m->req_module_entries_count; i++) {
36430
37559
  JSReqModuleEntry *rme = &m->req_module_entries[i];
37560
+ JSValue val;
36431
37561
  if (bc_get_atom(s, &rme->module_name))
36432
37562
  goto fail;
37563
+ val = JS_ReadObjectRec(s);
37564
+ if (JS_IsException(val))
37565
+ goto fail;
37566
+ rme->attributes = val;
36433
37567
  }
36434
37568
  }
36435
37569
 
@@ -36482,8 +37616,12 @@ static JSValue JS_ReadModule(BCReaderState *s)
36482
37616
  goto fail;
36483
37617
  for(i = 0; i < m->import_entries_count; i++) {
36484
37618
  JSImportEntry *mi = &m->import_entries[i];
37619
+ uint8_t v8;
36485
37620
  if (bc_get_leb128_int(s, &mi->var_idx))
36486
37621
  goto fail;
37622
+ if (bc_get_u8(s, &v8))
37623
+ goto fail;
37624
+ mi->is_star = (v8 != 0);
36487
37625
  if (bc_get_atom(s, &mi->import_name))
36488
37626
  goto fail;
36489
37627
  if (bc_get_leb128_int(s, &mi->req_module_idx))
@@ -36501,7 +37639,7 @@ static JSValue JS_ReadModule(BCReaderState *s)
36501
37639
  return obj;
36502
37640
  fail:
36503
37641
  if (m) {
36504
- js_free_module_def(ctx, m);
37642
+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
36505
37643
  }
36506
37644
  return JS_EXCEPTION;
36507
37645
  }
@@ -37093,17 +38231,22 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
37093
38231
  return 0;
37094
38232
  }
37095
38233
 
37096
- void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
37097
- const JSCFunctionListEntry *tab, int len)
38234
+ int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
38235
+ const JSCFunctionListEntry *tab, int len)
37098
38236
  {
37099
- int i;
38237
+ int i, ret;
37100
38238
 
37101
38239
  for (i = 0; i < len; i++) {
37102
38240
  const JSCFunctionListEntry *e = &tab[i];
37103
38241
  JSAtom atom = find_atom(ctx, e->name);
37104
- JS_InstantiateFunctionListItem(ctx, obj, atom, e);
38242
+ if (atom == JS_ATOM_NULL)
38243
+ return -1;
38244
+ ret = JS_InstantiateFunctionListItem(ctx, obj, atom, e);
37105
38245
  JS_FreeAtom(ctx, atom);
38246
+ if (ret)
38247
+ return -1;
37106
38248
  }
38249
+ return 0;
37107
38250
  }
37108
38251
 
37109
38252
  int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
@@ -37307,6 +38450,14 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
37307
38450
  val = JS_UNDEFINED;
37308
38451
  getter = JS_UNDEFINED;
37309
38452
  setter = JS_UNDEFINED;
38453
+ if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) {
38454
+ JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);
38455
+ if (JS_IsException(prop))
38456
+ goto fail;
38457
+ flags |= JS_PROP_HAS_ENUMERABLE;
38458
+ if (JS_ToBoolFree(ctx, prop))
38459
+ flags |= JS_PROP_ENUMERABLE;
38460
+ }
37310
38461
  if (JS_HasProperty(ctx, desc, JS_ATOM_configurable)) {
37311
38462
  JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_configurable);
37312
38463
  if (JS_IsException(prop))
@@ -37315,6 +38466,12 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
37315
38466
  if (JS_ToBoolFree(ctx, prop))
37316
38467
  flags |= JS_PROP_CONFIGURABLE;
37317
38468
  }
38469
+ if (JS_HasProperty(ctx, desc, JS_ATOM_value)) {
38470
+ flags |= JS_PROP_HAS_VALUE;
38471
+ val = JS_GetProperty(ctx, desc, JS_ATOM_value);
38472
+ if (JS_IsException(val))
38473
+ goto fail;
38474
+ }
37318
38475
  if (JS_HasProperty(ctx, desc, JS_ATOM_writable)) {
37319
38476
  JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_writable);
37320
38477
  if (JS_IsException(prop))
@@ -37323,20 +38480,6 @@ static int js_obj_to_desc(JSContext *ctx, JSPropertyDescriptor *d,
37323
38480
  if (JS_ToBoolFree(ctx, prop))
37324
38481
  flags |= JS_PROP_WRITABLE;
37325
38482
  }
37326
- if (JS_HasProperty(ctx, desc, JS_ATOM_enumerable)) {
37327
- JSValue prop = JS_GetProperty(ctx, desc, JS_ATOM_enumerable);
37328
- if (JS_IsException(prop))
37329
- goto fail;
37330
- flags |= JS_PROP_HAS_ENUMERABLE;
37331
- if (JS_ToBoolFree(ctx, prop))
37332
- flags |= JS_PROP_ENUMERABLE;
37333
- }
37334
- if (JS_HasProperty(ctx, desc, JS_ATOM_value)) {
37335
- flags |= JS_PROP_HAS_VALUE;
37336
- val = JS_GetProperty(ctx, desc, JS_ATOM_value);
37337
- if (JS_IsException(val))
37338
- goto fail;
37339
- }
37340
38483
  if (JS_HasProperty(ctx, desc, JS_ATOM_get)) {
37341
38484
  flags |= JS_PROP_HAS_GET;
37342
38485
  getter = JS_GetProperty(ctx, desc, JS_ATOM_get);
@@ -37421,7 +38564,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx,
37421
38564
  ret = 0;
37422
38565
 
37423
38566
  exception:
37424
- js_free_prop_enum(ctx, atoms, len);
38567
+ JS_FreePropertyEnum(ctx, atoms, len);
37425
38568
  JS_FreeValue(ctx, props);
37426
38569
  JS_FreeValue(ctx, desc);
37427
38570
  return ret;
@@ -37692,12 +38835,12 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst
37692
38835
  goto exception;
37693
38836
  }
37694
38837
  }
37695
- js_free_prop_enum(ctx, props, len);
38838
+ JS_FreePropertyEnum(ctx, props, len);
37696
38839
  JS_FreeValue(ctx, obj);
37697
38840
  return r;
37698
38841
 
37699
38842
  exception:
37700
- js_free_prop_enum(ctx, props, len);
38843
+ JS_FreePropertyEnum(ctx, props, len);
37701
38844
  JS_FreeValue(ctx, obj);
37702
38845
  JS_FreeValue(ctx, r);
37703
38846
  return JS_EXCEPTION;
@@ -37777,7 +38920,7 @@ exception:
37777
38920
  JS_FreeValue(ctx, r);
37778
38921
  r = JS_EXCEPTION;
37779
38922
  done:
37780
- js_free_prop_enum(ctx, atoms, len);
38923
+ JS_FreePropertyEnum(ctx, atoms, len);
37781
38924
  JS_FreeValue(ctx, obj);
37782
38925
  return r;
37783
38926
  }
@@ -38038,11 +39181,11 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
38038
39181
  JS_UNDEFINED, JS_UNDEFINED, desc_flags) < 0)
38039
39182
  goto exception;
38040
39183
  }
38041
- js_free_prop_enum(ctx, props, len);
39184
+ JS_FreePropertyEnum(ctx, props, len);
38042
39185
  return JS_DupValue(ctx, obj);
38043
39186
 
38044
39187
  exception:
38045
- js_free_prop_enum(ctx, props, len);
39188
+ JS_FreePropertyEnum(ctx, props, len);
38046
39189
  return JS_EXCEPTION;
38047
39190
  }
38048
39191
 
@@ -38084,11 +39227,11 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,
38084
39227
  return JS_EXCEPTION;
38085
39228
  res ^= 1;
38086
39229
  done:
38087
- js_free_prop_enum(ctx, props, len);
39230
+ JS_FreePropertyEnum(ctx, props, len);
38088
39231
  return JS_NewBool(ctx, res);
38089
39232
 
38090
39233
  exception:
38091
- js_free_prop_enum(ctx, props, len);
39234
+ JS_FreePropertyEnum(ctx, props, len);
38092
39235
  return JS_EXCEPTION;
38093
39236
  }
38094
39237
 
@@ -38986,6 +40129,16 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = {
38986
40129
  JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),
38987
40130
  };
38988
40131
 
40132
+ static JSValue js_error_isError(JSContext *ctx, JSValueConst this_val,
40133
+ int argc, JSValueConst *argv)
40134
+ {
40135
+ return JS_NewBool(ctx, JS_IsError(ctx, argv[0]));
40136
+ }
40137
+
40138
+ static const JSCFunctionListEntry js_error_funcs[] = {
40139
+ JS_CFUNC_DEF("isError", 1, js_error_isError),
40140
+ };
40141
+
38989
40142
  /* AggregateError */
38990
40143
 
38991
40144
  /* used by C code. */
@@ -42679,12 +43832,6 @@ static JSValue js_string_trim(JSContext *ctx, JSValueConst this_val,
42679
43832
  return ret;
42680
43833
  }
42681
43834
 
42682
- static JSValue js_string___quote(JSContext *ctx, JSValueConst this_val,
42683
- int argc, JSValueConst *argv)
42684
- {
42685
- return JS_ToQuotedString(ctx, this_val);
42686
- }
42687
-
42688
43835
  /* return 0 if before the first char */
42689
43836
  static int string_prevc(JSString *p, int *pidx)
42690
43837
  {
@@ -43172,7 +44319,6 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = {
43172
44319
  JS_ALIAS_DEF("trimLeft", "trimStart" ),
43173
44320
  JS_CFUNC_DEF("toString", 0, js_string_toString ),
43174
44321
  JS_CFUNC_DEF("valueOf", 0, js_string_toString ),
43175
- JS_CFUNC_DEF("__quote", 1, js_string___quote ),
43176
44322
  JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ),
43177
44323
  JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ),
43178
44324
  JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ),
@@ -43357,6 +44503,11 @@ static JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val,
43357
44503
  return JS_NewFloat64(ctx, r);
43358
44504
  }
43359
44505
 
44506
+ static double js_math_f16round(double a)
44507
+ {
44508
+ return fromfp16(tofp16(a));
44509
+ }
44510
+
43360
44511
  static double js_math_fround(double a)
43361
44512
  {
43362
44513
  return (float)a;
@@ -43460,6 +44611,7 @@ static const JSCFunctionListEntry js_math_funcs[] = {
43460
44611
  JS_CFUNC_SPECIAL_DEF("cbrt", 1, f_f, cbrt ),
43461
44612
  JS_CFUNC_DEF("hypot", 2, js_math_hypot ),
43462
44613
  JS_CFUNC_DEF("random", 0, js_math_random ),
44614
+ JS_CFUNC_SPECIAL_DEF("f16round", 1, f_f, js_math_f16round ),
43463
44615
  JS_CFUNC_SPECIAL_DEF("fround", 1, f_f, js_math_fround ),
43464
44616
  JS_CFUNC_DEF("imul", 2, js_math_imul ),
43465
44617
  JS_CFUNC_DEF("clz32", 1, js_math_clz32 ),
@@ -43515,9 +44667,13 @@ static int getTimezoneOffset(int64_t time)
43515
44667
  time_t gm_ti, loc_ti;
43516
44668
 
43517
44669
  tm = gmtime(&ti);
44670
+ if (!tm)
44671
+ return 0;
43518
44672
  gm_ti = mktime(tm);
43519
44673
 
43520
44674
  tm = localtime(&ti);
44675
+ if (!tm)
44676
+ return 0;
43521
44677
  loc_ti = mktime(tm);
43522
44678
 
43523
44679
  res = (gm_ti - loc_ti) / 60;
@@ -43624,6 +44780,9 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
43624
44780
  case 'u':
43625
44781
  mask = LRE_FLAG_UNICODE;
43626
44782
  break;
44783
+ case 'v':
44784
+ mask = LRE_FLAG_UNICODE_SETS;
44785
+ break;
43627
44786
  case 'y':
43628
44787
  mask = LRE_FLAG_STICKY;
43629
44788
  break;
@@ -43633,14 +44792,20 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern,
43633
44792
  if ((re_flags & mask) != 0) {
43634
44793
  bad_flags:
43635
44794
  JS_FreeCString(ctx, str);
43636
- return JS_ThrowSyntaxError(ctx, "invalid regular expression flags");
44795
+ goto bad_flags1;
43637
44796
  }
43638
44797
  re_flags |= mask;
43639
44798
  }
43640
44799
  JS_FreeCString(ctx, str);
43641
44800
  }
43642
44801
 
43643
- str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE));
44802
+ /* 'u' and 'v' cannot be both set */
44803
+ if ((re_flags & LRE_FLAG_UNICODE_SETS) && (re_flags & LRE_FLAG_UNICODE)) {
44804
+ bad_flags1:
44805
+ return JS_ThrowSyntaxError(ctx, "invalid regular expression flags");
44806
+ }
44807
+
44808
+ str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)));
43644
44809
  if (!str)
43645
44810
  return JS_EXCEPTION;
43646
44811
  re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg,
@@ -43944,49 +45109,34 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
43944
45109
  return JS_NewBool(ctx, flags & mask);
43945
45110
  }
43946
45111
 
45112
+ #define RE_FLAG_COUNT 8
45113
+
43947
45114
  static JSValue js_regexp_get_flags(JSContext *ctx, JSValueConst this_val)
43948
45115
  {
43949
- char str[8], *p = str;
43950
- int res;
43951
-
45116
+ char str[RE_FLAG_COUNT], *p = str;
45117
+ int res, i;
45118
+ static const int flag_atom[RE_FLAG_COUNT] = {
45119
+ JS_ATOM_hasIndices,
45120
+ JS_ATOM_global,
45121
+ JS_ATOM_ignoreCase,
45122
+ JS_ATOM_multiline,
45123
+ JS_ATOM_dotAll,
45124
+ JS_ATOM_unicode,
45125
+ JS_ATOM_unicodeSets,
45126
+ JS_ATOM_sticky,
45127
+ };
45128
+ static const char flag_char[RE_FLAG_COUNT] = { 'd', 'g', 'i', 'm', 's', 'u', 'v', 'y' };
45129
+
43952
45130
  if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
43953
45131
  return JS_ThrowTypeErrorNotAnObject(ctx);
43954
45132
 
43955
- res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "hasIndices"));
43956
- if (res < 0)
43957
- goto exception;
43958
- if (res)
43959
- *p++ = 'd';
43960
- res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_global));
43961
- if (res < 0)
43962
- goto exception;
43963
- if (res)
43964
- *p++ = 'g';
43965
- res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "ignoreCase"));
43966
- if (res < 0)
43967
- goto exception;
43968
- if (res)
43969
- *p++ = 'i';
43970
- res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "multiline"));
43971
- if (res < 0)
43972
- goto exception;
43973
- if (res)
43974
- *p++ = 'm';
43975
- res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "dotAll"));
43976
- if (res < 0)
43977
- goto exception;
43978
- if (res)
43979
- *p++ = 's';
43980
- res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, JS_ATOM_unicode));
43981
- if (res < 0)
43982
- goto exception;
43983
- if (res)
43984
- *p++ = 'u';
43985
- res = JS_ToBoolFree(ctx, JS_GetPropertyStr(ctx, this_val, "sticky"));
43986
- if (res < 0)
43987
- goto exception;
43988
- if (res)
43989
- *p++ = 'y';
45133
+ for(i = 0; i < RE_FLAG_COUNT; i++) {
45134
+ res = JS_ToBoolFree(ctx, JS_GetProperty(ctx, this_val, flag_atom[i]));
45135
+ if (res < 0)
45136
+ goto exception;
45137
+ if (res)
45138
+ *p++ = flag_char[i];
45139
+ }
43990
45140
  return JS_NewStringLen(ctx, str, p - str);
43991
45141
 
43992
45142
  exception:
@@ -44039,6 +45189,58 @@ void *lre_realloc(void *opaque, void *ptr, size_t size)
44039
45189
  return js_realloc_rt(ctx->rt, ptr, size);
44040
45190
  }
44041
45191
 
45192
+ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val,
45193
+ int argc, JSValueConst *argv)
45194
+ {
45195
+ JSValue str;
45196
+ StringBuffer b_s, *b = &b_s;
45197
+ JSString *p;
45198
+ uint32_t c, i;
45199
+ char s[16];
45200
+
45201
+ if (!JS_IsString(argv[0]))
45202
+ return JS_ThrowTypeError(ctx, "not a string");
45203
+ str = JS_ToString(ctx, argv[0]); /* must call it to linearlize ropes */
45204
+ if (JS_IsException(str))
45205
+ return JS_EXCEPTION;
45206
+ p = JS_VALUE_GET_STRING(str);
45207
+ string_buffer_init2(ctx, b, 0, p->is_wide_char);
45208
+ for (i = 0; i < p->len; i++) {
45209
+ c = string_get(p, i);
45210
+ if (c < 33) {
45211
+ if (c >= 9 && c <= 13) {
45212
+ string_buffer_putc8(b, '\\');
45213
+ string_buffer_putc8(b, "tnvfr"[c - 9]);
45214
+ } else {
45215
+ goto hex2;
45216
+ }
45217
+ } else if (c < 128) {
45218
+ if ((c >= '0' && c <= '9')
45219
+ || (c >= 'A' && c <= 'Z')
45220
+ || (c >= 'a' && c <= 'z')) {
45221
+ if (i == 0)
45222
+ goto hex2;
45223
+ } else if (strchr(",-=<>#&!%:;@~'`\"", c)) {
45224
+ goto hex2;
45225
+ } else if (c != '_') {
45226
+ string_buffer_putc8(b, '\\');
45227
+ }
45228
+ string_buffer_putc8(b, c);
45229
+ } else if (c < 256) {
45230
+ hex2:
45231
+ snprintf(s, sizeof(s), "\\x%02x", c);
45232
+ string_buffer_puts8(b, s);
45233
+ } else if (is_surrogate(c) || lre_is_space(c)) {
45234
+ snprintf(s, sizeof(s), "\\u%04x", c);
45235
+ string_buffer_puts8(b, s);
45236
+ } else {
45237
+ string_buffer_putc16(b, c);
45238
+ }
45239
+ }
45240
+ JS_FreeValue(ctx, str);
45241
+ return string_buffer_end(b);
45242
+ }
45243
+
44042
45244
  static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val,
44043
45245
  int argc, JSValueConst *argv)
44044
45246
  {
@@ -44419,14 +45621,12 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
44419
45621
  goto exception;
44420
45622
  p = JS_VALUE_GET_STRING(flags);
44421
45623
 
44422
- // TODO(bnoordhuis) query 'u' flag the same way?
44423
45624
  global = (-1 != string_indexof_char(p, 'g', 0));
44424
45625
  if (!global) {
44425
45626
  A = JS_RegExpExec(ctx, rx, S);
44426
45627
  } else {
44427
- fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));
44428
- if (fullUnicode < 0)
44429
- goto exception;
45628
+ fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 ||
45629
+ string_indexof_char(p, 'v', 0) >= 0);
44430
45630
 
44431
45631
  if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)
44432
45632
  goto exception;
@@ -44445,7 +45645,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
44445
45645
  if (JS_IsException(matchStr))
44446
45646
  goto exception;
44447
45647
  isEmpty = JS_IsEmptyString(matchStr);
44448
- if (JS_SetPropertyInt64(ctx, A, n++, matchStr) < 0)
45648
+ if (JS_DefinePropertyValueInt64(ctx, A, n++, matchStr, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
44449
45649
  goto exception;
44450
45650
  if (isEmpty) {
44451
45651
  int64_t thisIndex, nextIndex;
@@ -44610,7 +45810,8 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,
44610
45810
  it->iterated_string = S;
44611
45811
  strp = JS_VALUE_GET_STRING(flags);
44612
45812
  it->global = string_indexof_char(strp, 'g', 0) >= 0;
44613
- it->unicode = string_indexof_char(strp, 'u', 0) >= 0;
45813
+ it->unicode = (string_indexof_char(strp, 'u', 0) >= 0 ||
45814
+ string_indexof_char(strp, 'v', 0) >= 0);
44614
45815
  it->done = FALSE;
44615
45816
  JS_SetOpaque(iter, it);
44616
45817
 
@@ -44757,13 +45958,11 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
44757
45958
  goto exception;
44758
45959
  p = JS_VALUE_GET_STRING(flags);
44759
45960
 
44760
- // TODO(bnoordhuis) query 'u' flag the same way?
44761
45961
  fullUnicode = 0;
44762
45962
  is_global = (-1 != string_indexof_char(p, 'g', 0));
44763
45963
  if (is_global) {
44764
- fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode));
44765
- if (fullUnicode < 0)
44766
- goto exception;
45964
+ fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 ||
45965
+ string_indexof_char(p, 'v', 0) >= 0);
44767
45966
  if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, 0)) < 0)
44768
45967
  goto exception;
44769
45968
  }
@@ -44989,7 +46188,8 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val,
44989
46188
  if (JS_IsException(flags))
44990
46189
  goto exception;
44991
46190
  strp = JS_VALUE_GET_STRING(flags);
44992
- unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0;
46191
+ unicodeMatching = (string_indexof_char(strp, 'u', 0) >= 0 ||
46192
+ string_indexof_char(strp, 'v', 0) >= 0);
44993
46193
  if (string_indexof_char(strp, 'y', 0) < 0) {
44994
46194
  flags = JS_ConcatString3(ctx, "", flags, "y");
44995
46195
  if (JS_IsException(flags))
@@ -45086,6 +46286,7 @@ done:
45086
46286
  }
45087
46287
 
45088
46288
  static const JSCFunctionListEntry js_regexp_funcs[] = {
46289
+ JS_CFUNC_DEF("escape", 1, js_regexp_escape ),
45089
46290
  JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL ),
45090
46291
  //JS_CFUNC_DEF("__RegExpExec", 2, js_regexp___RegExpExec ),
45091
46292
  //JS_CFUNC_DEF("__RegExpDelete", 2, js_regexp___RegExpDelete ),
@@ -45099,6 +46300,7 @@ static const JSCFunctionListEntry js_regexp_proto_funcs[] = {
45099
46300
  JS_CGETSET_MAGIC_DEF("multiline", js_regexp_get_flag, NULL, LRE_FLAG_MULTILINE ),
45100
46301
  JS_CGETSET_MAGIC_DEF("dotAll", js_regexp_get_flag, NULL, LRE_FLAG_DOTALL ),
45101
46302
  JS_CGETSET_MAGIC_DEF("unicode", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE ),
46303
+ JS_CGETSET_MAGIC_DEF("unicodeSets", js_regexp_get_flag, NULL, LRE_FLAG_UNICODE_SETS ),
45102
46304
  JS_CGETSET_MAGIC_DEF("sticky", js_regexp_get_flag, NULL, LRE_FLAG_STICKY ),
45103
46305
  JS_CGETSET_MAGIC_DEF("hasIndices", js_regexp_get_flag, NULL, LRE_FLAG_INDICES ),
45104
46306
  JS_CFUNC_DEF("exec", 1, js_regexp_exec ),
@@ -45261,6 +46463,12 @@ static JSValue json_parse_value(JSParseState *s)
45261
46463
  val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true);
45262
46464
  } else if (s->token.u.ident.atom == JS_ATOM_null) {
45263
46465
  val = JS_NULL;
46466
+ } else if (s->token.u.ident.atom == JS_ATOM_NaN && s->ext_json) {
46467
+ /* Note: json5 identifier handling is ambiguous e.g. is
46468
+ '{ NaN: 1 }' a valid JSON5 production ? */
46469
+ val = JS_NewFloat64(s->ctx, NAN);
46470
+ } else if (s->token.u.ident.atom == JS_ATOM_Infinity && s->ext_json) {
46471
+ val = JS_NewFloat64(s->ctx, INFINITY);
45264
46472
  } else {
45265
46473
  goto def_token;
45266
46474
  }
@@ -45365,7 +46573,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
45365
46573
  goto fail;
45366
46574
  }
45367
46575
  }
45368
- js_free_prop_enum(ctx, atoms, len);
46576
+ JS_FreePropertyEnum(ctx, atoms, len);
45369
46577
  atoms = NULL;
45370
46578
  name_val = JS_AtomToValue(ctx, name);
45371
46579
  if (JS_IsException(name_val))
@@ -45377,7 +46585,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
45377
46585
  JS_FreeValue(ctx, val);
45378
46586
  return res;
45379
46587
  fail:
45380
- js_free_prop_enum(ctx, atoms, len);
46588
+ JS_FreePropertyEnum(ctx, atoms, len);
45381
46589
  JS_FreeValue(ctx, val);
45382
46590
  return JS_EXCEPTION;
45383
46591
  }
@@ -45425,10 +46633,72 @@ typedef struct JSONStringifyContext {
45425
46633
  StringBuffer *b;
45426
46634
  } JSONStringifyContext;
45427
46635
 
45428
- static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) {
45429
- JSValue r = JS_ToQuotedString(ctx, val);
46636
+ static int JS_ToQuotedString(JSContext *ctx, StringBuffer *b, JSValueConst val1)
46637
+ {
46638
+ JSValue val;
46639
+ JSString *p;
46640
+ int i;
46641
+ uint32_t c;
46642
+ char buf[16];
46643
+
46644
+ val = JS_ToStringCheckObject(ctx, val1);
46645
+ if (JS_IsException(val))
46646
+ return -1;
46647
+ p = JS_VALUE_GET_STRING(val);
46648
+
46649
+ if (string_buffer_putc8(b, '\"'))
46650
+ goto fail;
46651
+ for(i = 0; i < p->len; ) {
46652
+ c = string_getc(p, &i);
46653
+ switch(c) {
46654
+ case '\t':
46655
+ c = 't';
46656
+ goto quote;
46657
+ case '\r':
46658
+ c = 'r';
46659
+ goto quote;
46660
+ case '\n':
46661
+ c = 'n';
46662
+ goto quote;
46663
+ case '\b':
46664
+ c = 'b';
46665
+ goto quote;
46666
+ case '\f':
46667
+ c = 'f';
46668
+ goto quote;
46669
+ case '\"':
46670
+ case '\\':
46671
+ quote:
46672
+ if (string_buffer_putc8(b, '\\'))
46673
+ goto fail;
46674
+ if (string_buffer_putc8(b, c))
46675
+ goto fail;
46676
+ break;
46677
+ default:
46678
+ if (c < 32 || is_surrogate(c)) {
46679
+ snprintf(buf, sizeof(buf), "\\u%04x", c);
46680
+ if (string_buffer_puts8(b, buf))
46681
+ goto fail;
46682
+ } else {
46683
+ if (string_buffer_putc(b, c))
46684
+ goto fail;
46685
+ }
46686
+ break;
46687
+ }
46688
+ }
46689
+ if (string_buffer_putc8(b, '\"'))
46690
+ goto fail;
45430
46691
  JS_FreeValue(ctx, val);
45431
- return r;
46692
+ return 0;
46693
+ fail:
46694
+ JS_FreeValue(ctx, val);
46695
+ return -1;
46696
+ }
46697
+
46698
+ static int JS_ToQuotedStringFree(JSContext *ctx, StringBuffer *b, JSValue val) {
46699
+ int ret = JS_ToQuotedString(ctx, b, val);
46700
+ JS_FreeValue(ctx, val);
46701
+ return ret;
45432
46702
  }
45433
46703
 
45434
46704
  static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
@@ -45611,13 +46881,11 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
45611
46881
  if (!JS_IsUndefined(v)) {
45612
46882
  if (has_content)
45613
46883
  string_buffer_putc8(jsc->b, ',');
45614
- prop = JS_ToQuotedStringFree(ctx, prop);
45615
- if (JS_IsException(prop)) {
46884
+ string_buffer_concat_value(jsc->b, sep);
46885
+ if (JS_ToQuotedString(ctx, jsc->b, prop)) {
45616
46886
  JS_FreeValue(ctx, v);
45617
46887
  goto exception;
45618
46888
  }
45619
- string_buffer_concat_value(jsc->b, sep);
45620
- string_buffer_concat_value(jsc->b, prop);
45621
46889
  string_buffer_putc8(jsc->b, ':');
45622
46890
  string_buffer_concat_value(jsc->b, sep1);
45623
46891
  if (js_json_to_str(ctx, jsc, val, v, indent1))
@@ -45645,10 +46913,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
45645
46913
  switch (JS_VALUE_GET_NORM_TAG(val)) {
45646
46914
  case JS_TAG_STRING:
45647
46915
  case JS_TAG_STRING_ROPE:
45648
- val = JS_ToQuotedStringFree(ctx, val);
45649
- if (JS_IsException(val))
45650
- goto exception;
45651
- goto concat_value;
46916
+ return JS_ToQuotedStringFree(ctx, jsc->b, val);
45652
46917
  case JS_TAG_FLOAT64:
45653
46918
  if (!isfinite(JS_VALUE_GET_FLOAT64(val))) {
45654
46919
  val = JS_NULL;
@@ -46087,7 +47352,7 @@ static JSValue js_proxy_get_prototype(JSContext *ctx, JSValueConst obj)
46087
47352
  JS_FreeValue(ctx, ret);
46088
47353
  return JS_EXCEPTION;
46089
47354
  }
46090
- if (JS_VALUE_GET_OBJ(proto1) != JS_VALUE_GET_OBJ(ret)) {
47355
+ if (!js_same_value(ctx, proto1, ret)) {
46091
47356
  JS_FreeValue(ctx, proto1);
46092
47357
  fail:
46093
47358
  JS_FreeValue(ctx, ret);
@@ -46127,7 +47392,7 @@ static int js_proxy_set_prototype(JSContext *ctx, JSValueConst obj,
46127
47392
  proto1 = JS_GetPrototype(ctx, s->target);
46128
47393
  if (JS_IsException(proto1))
46129
47394
  return -1;
46130
- if (JS_VALUE_GET_OBJ(proto_val) != JS_VALUE_GET_OBJ(proto1)) {
47395
+ if (!js_same_value(ctx, proto_val, proto1)) {
46131
47396
  JS_FreeValue(ctx, proto1);
46132
47397
  JS_ThrowTypeError(ctx, "proxy: inconsistent prototype");
46133
47398
  return -1;
@@ -46751,14 +48016,14 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
46751
48016
  }
46752
48017
  }
46753
48018
 
46754
- js_free_prop_enum(ctx, tab2, len2);
48019
+ JS_FreePropertyEnum(ctx, tab2, len2);
46755
48020
  JS_FreeValue(ctx, prop_array);
46756
48021
  *ptab = tab;
46757
48022
  *plen = len;
46758
48023
  return 0;
46759
48024
  fail:
46760
- js_free_prop_enum(ctx, tab2, len2);
46761
- js_free_prop_enum(ctx, tab, len);
48025
+ JS_FreePropertyEnum(ctx, tab2, len2);
48026
+ JS_FreePropertyEnum(ctx, tab, len);
46762
48027
  JS_FreeValue(ctx, prop_array);
46763
48028
  return -1;
46764
48029
  }
@@ -47094,27 +48359,6 @@ static const JSCFunctionListEntry js_symbol_funcs[] = {
47094
48359
 
47095
48360
  /* Set/Map/WeakSet/WeakMap */
47096
48361
 
47097
- typedef struct JSMapRecord {
47098
- int ref_count; /* used during enumeration to avoid freeing the record */
47099
- BOOL empty : 8; /* TRUE if the record is deleted */
47100
- struct list_head link;
47101
- struct JSMapRecord *hash_next;
47102
- JSValue key;
47103
- JSValue value;
47104
- } JSMapRecord;
47105
-
47106
- typedef struct JSMapState {
47107
- BOOL is_weak; /* TRUE if WeakSet/WeakMap */
47108
- struct list_head records; /* list of JSMapRecord.link */
47109
- uint32_t record_count;
47110
- JSMapRecord **hash_table;
47111
- int hash_bits;
47112
- uint32_t hash_size; /* = 2 ^ hash_bits */
47113
- uint32_t record_count_threshold; /* count at which a hash table
47114
- resize is needed */
47115
- JSWeakRefHeader weakref_header; /* only used if is_weak = TRUE */
47116
- } JSMapState;
47117
-
47118
48362
  static BOOL js_weakref_is_target(JSValueConst val)
47119
48363
  {
47120
48364
  switch (JS_VALUE_GET_TAG(val)) {
@@ -48395,8 +49639,8 @@ static JSValue js_promise_resolve_function_call(JSContext *ctx,
48395
49639
  else
48396
49640
  resolution = JS_UNDEFINED;
48397
49641
  #ifdef DUMP_PROMISE
48398
- printf("js_promise_resolving_function_call: is_reject=%d resolution=", is_reject);
48399
- JS_DumpValue(ctx, resolution);
49642
+ printf("js_promise_resolving_function_call: is_reject=%d ", is_reject);
49643
+ JS_DumpValue(ctx, "resolution", resolution);
48400
49644
  printf("\n");
48401
49645
  #endif
48402
49646
  if (is_reject || !JS_IsObject(resolution)) {
@@ -48636,6 +49880,34 @@ static JSValue js_promise_withResolvers(JSContext *ctx,
48636
49880
  return obj;
48637
49881
  }
48638
49882
 
49883
+ static JSValue js_promise_try(JSContext *ctx, JSValueConst this_val,
49884
+ int argc, JSValueConst *argv)
49885
+ {
49886
+ JSValue result_promise, resolving_funcs[2], ret, ret2;
49887
+ BOOL is_reject = 0;
49888
+
49889
+ if (!JS_IsObject(this_val))
49890
+ return JS_ThrowTypeErrorNotAnObject(ctx);
49891
+ result_promise = js_new_promise_capability(ctx, resolving_funcs, this_val);
49892
+ if (JS_IsException(result_promise))
49893
+ return result_promise;
49894
+ ret = JS_Call(ctx, argv[0], JS_UNDEFINED, argc - 1, argv + 1);
49895
+ if (JS_IsException(ret)) {
49896
+ is_reject = 1;
49897
+ ret = JS_GetException(ctx);
49898
+ }
49899
+ ret2 = JS_Call(ctx, resolving_funcs[is_reject], JS_UNDEFINED, 1, (JSValueConst *)&ret);
49900
+ JS_FreeValue(ctx, resolving_funcs[0]);
49901
+ JS_FreeValue(ctx, resolving_funcs[1]);
49902
+ JS_FreeValue(ctx, ret);
49903
+ if (JS_IsException(ret2)) {
49904
+ JS_FreeValue(ctx, result_promise);
49905
+ return ret2;
49906
+ }
49907
+ JS_FreeValue(ctx, ret2);
49908
+ return result_promise;
49909
+ }
49910
+
48639
49911
  static __exception int remainingElementsCount_add(JSContext *ctx,
48640
49912
  JSValueConst resolve_element_env,
48641
49913
  int addend)
@@ -49123,6 +50395,7 @@ static const JSCFunctionListEntry js_promise_funcs[] = {
49123
50395
  JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ),
49124
50396
  JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),
49125
50397
  JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),
50398
+ JS_CFUNC_DEF("try", 1, js_promise_try ),
49126
50399
  JS_CFUNC_DEF("race", 1, js_promise_race ),
49127
50400
  JS_CFUNC_DEF("withResolvers", 0, js_promise_withResolvers ),
49128
50401
  JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),
@@ -49392,6 +50665,7 @@ void JS_AddIntrinsicPromise(JSContext *ctx)
49392
50665
  {
49393
50666
  JSRuntime *rt = ctx->rt;
49394
50667
  JSValue obj1;
50668
+ JSCFunctionType ft;
49395
50669
 
49396
50670
  if (!JS_IsRegisteredClass(rt, JS_CLASS_PROMISE)) {
49397
50671
  init_class_range(rt, js_async_class_def, JS_CLASS_PROMISE,
@@ -49420,7 +50694,8 @@ void JS_AddIntrinsicPromise(JSContext *ctx)
49420
50694
 
49421
50695
  /* AsyncFunction */
49422
50696
  ctx->class_proto[JS_CLASS_ASYNC_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);
49423
- obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,
50697
+ ft.generic_magic = js_function_constructor;
50698
+ obj1 = JS_NewCFunction3(ctx, ft.generic,
49424
50699
  "AsyncFunction", 1,
49425
50700
  JS_CFUNC_constructor_or_func_magic, JS_FUNC_ASYNC,
49426
50701
  ctx->function_ctor);
@@ -49456,7 +50731,8 @@ void JS_AddIntrinsicPromise(JSContext *ctx)
49456
50731
  /* AsyncGeneratorFunction */
49457
50732
  ctx->class_proto[JS_CLASS_ASYNC_GENERATOR_FUNCTION] =
49458
50733
  JS_NewObjectProto(ctx, ctx->function_proto);
49459
- obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,
50734
+ ft.generic_magic = js_function_constructor;
50735
+ obj1 = JS_NewCFunction3(ctx, ft.generic,
49460
50736
  "AsyncGeneratorFunction", 1,
49461
50737
  JS_CFUNC_constructor_or_func_magic,
49462
50738
  JS_FUNC_ASYNC_GENERATOR,
@@ -51125,6 +52401,8 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx)
51125
52401
  int i;
51126
52402
 
51127
52403
  ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL);
52404
+ JS_SetImmutablePrototype(ctx, ctx->class_proto[JS_CLASS_OBJECT]);
52405
+
51128
52406
  ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0,
51129
52407
  JS_CFUNC_generic, 0,
51130
52408
  ctx->class_proto[JS_CLASS_OBJECT]);
@@ -51178,6 +52456,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
51178
52456
  int i;
51179
52457
  JSValueConst obj, number_obj;
51180
52458
  JSValue obj1;
52459
+ JSCFunctionType ft;
51181
52460
 
51182
52461
  ctx->throw_type_error = JS_NewCFunction(ctx, js_throw_type_error, NULL, 0);
51183
52462
 
@@ -51215,9 +52494,10 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
51215
52494
  "Error", 1, JS_CFUNC_constructor_or_func_magic, -1);
51216
52495
  JS_NewGlobalCConstructor2(ctx, obj1,
51217
52496
  "Error", ctx->class_proto[JS_CLASS_ERROR]);
52497
+ JS_SetPropertyFunctionList(ctx, obj1, js_error_funcs, countof(js_error_funcs));
51218
52498
 
51219
52499
  /* Used to squelch a -Wcast-function-type warning. */
51220
- JSCFunctionType ft = { .generic_magic = js_error_constructor };
52500
+ ft.generic_magic = js_error_constructor;
51221
52501
  for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
51222
52502
  JSValue func_obj;
51223
52503
  int n_args;
@@ -51360,7 +52640,8 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
51360
52640
  countof(js_generator_proto_funcs));
51361
52641
 
51362
52642
  ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION] = JS_NewObjectProto(ctx, ctx->function_proto);
51363
- obj1 = JS_NewCFunction3(ctx, (JSCFunction *)js_function_constructor,
52643
+ ft.generic_magic = js_function_constructor;
52644
+ obj1 = JS_NewCFunction3(ctx, ft.generic,
51364
52645
  "GeneratorFunction", 1,
51365
52646
  JS_CFUNC_constructor_or_func_magic, JS_FUNC_GENERATOR,
51366
52647
  ctx->function_ctor);
@@ -51393,8 +52674,8 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
51393
52674
 
51394
52675
  static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = {
51395
52676
  0, 0, 0, 1, 1, 2, 2,
51396
- 3, 3, /* BigInt64Array, BigUint64Array */
51397
- 2, 3
52677
+ 3, 3, // BigInt64Array, BigUint64Array
52678
+ 1, 2, 3 // Float16Array, Float32Array, Float64Array
51398
52679
  };
51399
52680
 
51400
52681
  static JSValue js_array_buffer_constructor3(JSContext *ctx,
@@ -52327,7 +53608,9 @@ static JSValue js_typed_array_fill(JSContext *ctx, JSValueConst this_val,
52327
53608
  double d;
52328
53609
  if (JS_ToFloat64(ctx, &d, argv[0]))
52329
53610
  return JS_EXCEPTION;
52330
- if (p->class_id == JS_CLASS_FLOAT32_ARRAY) {
53611
+ if (p->class_id == JS_CLASS_FLOAT16_ARRAY) {
53612
+ v64 = tofp16(d);
53613
+ } else if (p->class_id == JS_CLASS_FLOAT32_ARRAY) {
52331
53614
  union {
52332
53615
  float f;
52333
53616
  uint32_t u32;
@@ -52458,6 +53741,7 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
52458
53741
  int64_t v64;
52459
53742
  double d;
52460
53743
  float f;
53744
+ uint16_t hf;
52461
53745
 
52462
53746
  len = js_typed_array_get_length_internal(ctx, this_val);
52463
53747
  if (len < 0)
@@ -52468,22 +53752,12 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
52468
53752
  if (special == special_lastIndexOf) {
52469
53753
  k = len - 1;
52470
53754
  if (argc > 1) {
52471
- if (JS_ToFloat64(ctx, &d, argv[1]))
53755
+ int64_t k1;
53756
+ if (JS_ToInt64Clamp(ctx, &k1, argv[1], -1, len - 1, len))
52472
53757
  goto exception;
52473
- if (isnan(d)) {
52474
- k = 0;
52475
- } else {
52476
- if (d >= 0) {
52477
- if (d < k) {
52478
- k = d;
52479
- }
52480
- } else {
52481
- d += len;
52482
- if (d < 0)
52483
- goto done;
52484
- k = d;
52485
- }
52486
- }
53758
+ k = k1;
53759
+ if (k < 0)
53760
+ goto done;
52487
53761
  }
52488
53762
  stop = -1;
52489
53763
  inc = -1;
@@ -52620,6 +53894,39 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val,
52620
53894
  }
52621
53895
  }
52622
53896
  break;
53897
+ case JS_CLASS_FLOAT16_ARRAY:
53898
+ if (is_bigint)
53899
+ break;
53900
+ if (isnan(d)) {
53901
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
53902
+ /* special case: indexOf returns -1, includes finds NaN */
53903
+ if (special != special_includes)
53904
+ goto done;
53905
+ for (; k != stop; k += inc) {
53906
+ if (isfp16nan(pv[k])) {
53907
+ res = k;
53908
+ break;
53909
+ }
53910
+ }
53911
+ } else if (d == 0) {
53912
+ // special case: includes also finds negative zero
53913
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
53914
+ for (; k != stop; k += inc) {
53915
+ if (isfp16zero(pv[k])) {
53916
+ res = k;
53917
+ break;
53918
+ }
53919
+ }
53920
+ } else if (hf = tofp16(d), d == fromfp16(hf)) {
53921
+ const uint16_t *pv = p->u.array.u.fp16_ptr;
53922
+ for (; k != stop; k += inc) {
53923
+ if (pv[k] == hf) {
53924
+ res = k;
53925
+ break;
53926
+ }
53927
+ }
53928
+ }
53929
+ break;
52623
53930
  case JS_CLASS_FLOAT32_ARRAY:
52624
53931
  if (is_bigint)
52625
53932
  break;
@@ -52919,7 +54226,8 @@ static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val,
52919
54226
  int argc, JSValueConst *argv)
52920
54227
  {
52921
54228
  JSValueConst args[4];
52922
- JSValue arr, byteOffset, ta_buffer;
54229
+ JSValue arr, ta_buffer;
54230
+ JSTypedArray *ta;
52923
54231
  JSObject *p;
52924
54232
  int len, start, final, count, shift, offset;
52925
54233
 
@@ -52930,18 +54238,17 @@ static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val,
52930
54238
  if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len))
52931
54239
  goto exception;
52932
54240
 
54241
+ shift = typed_array_size_log2(p->class_id);
54242
+ ta = p->u.typed_array;
54243
+ /* Read byteOffset (ta->offset) even if detached */
54244
+ offset = ta->offset + (start << shift);
54245
+
52933
54246
  final = len;
52934
54247
  if (!JS_IsUndefined(argv[1])) {
52935
54248
  if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len))
52936
54249
  goto exception;
52937
54250
  }
52938
54251
  count = max_int(final - start, 0);
52939
- byteOffset = js_typed_array_get_byteOffset(ctx, this_val, 0);
52940
- if (JS_IsException(byteOffset))
52941
- goto exception;
52942
- shift = typed_array_size_log2(p->class_id);
52943
- offset = JS_VALUE_GET_INT(byteOffset) + (start << shift);
52944
- JS_FreeValue(ctx, byteOffset);
52945
54252
  ta_buffer = js_typed_array_get_buffer(ctx, this_val, 0);
52946
54253
  if (JS_IsException(ta_buffer))
52947
54254
  goto exception;
@@ -53010,6 +54317,11 @@ static int js_TA_cmp_uint64(const void *a, const void *b, void *opaque) {
53010
54317
  return (y < x) - (y > x);
53011
54318
  }
53012
54319
 
54320
+ static int js_TA_cmp_float16(const void *a, const void *b, void *opaque) {
54321
+ return js_cmp_doubles(fromfp16(*(const uint16_t *)a),
54322
+ fromfp16(*(const uint16_t *)b));
54323
+ }
54324
+
53013
54325
  static int js_TA_cmp_float32(const void *a, const void *b, void *opaque) {
53014
54326
  return js_cmp_doubles(*(const float *)a, *(const float *)b);
53015
54327
  }
@@ -53050,6 +54362,10 @@ static JSValue js_TA_get_uint64(JSContext *ctx, const void *a) {
53050
54362
  return JS_NewBigUint64(ctx, *(uint64_t *)a);
53051
54363
  }
53052
54364
 
54365
+ static JSValue js_TA_get_float16(JSContext *ctx, const void *a) {
54366
+ return __JS_NewFloat64(ctx, fromfp16(*(const uint16_t *)a));
54367
+ }
54368
+
53053
54369
  static JSValue js_TA_get_float32(JSContext *ctx, const void *a) {
53054
54370
  return __JS_NewFloat64(ctx, *(const float *)a);
53055
54371
  }
@@ -53175,6 +54491,10 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val,
53175
54491
  tsc.getfun = js_TA_get_uint64;
53176
54492
  cmpfun = js_TA_cmp_uint64;
53177
54493
  break;
54494
+ case JS_CLASS_FLOAT16_ARRAY:
54495
+ tsc.getfun = js_TA_get_float16;
54496
+ cmpfun = js_TA_cmp_float16;
54497
+ break;
53178
54498
  case JS_CLASS_FLOAT32_ARRAY:
53179
54499
  tsc.getfun = js_TA_get_float32;
53180
54500
  cmpfun = js_TA_cmp_float32;
@@ -53730,6 +55050,14 @@ static JSValue js_dataview_getValue(JSContext *ctx,
53730
55050
  return JS_NewBigUint64(ctx, v);
53731
55051
  }
53732
55052
  break;
55053
+ case JS_CLASS_FLOAT16_ARRAY:
55054
+ {
55055
+ uint16_t v;
55056
+ v = get_u16(ptr);
55057
+ if (is_swap)
55058
+ v = bswap16(v);
55059
+ return __JS_NewFloat64(ctx, fromfp16(v));
55060
+ }
53733
55061
  case JS_CLASS_FLOAT32_ARRAY:
53734
55062
  {
53735
55063
  union {
@@ -53791,7 +55119,9 @@ static JSValue js_dataview_setValue(JSContext *ctx,
53791
55119
  double d;
53792
55120
  if (JS_ToFloat64(ctx, &d, val))
53793
55121
  return JS_EXCEPTION;
53794
- if (class_id == JS_CLASS_FLOAT32_ARRAY) {
55122
+ if (class_id == JS_CLASS_FLOAT16_ARRAY) {
55123
+ v = tofp16(d);
55124
+ } else if (class_id == JS_CLASS_FLOAT32_ARRAY) {
53795
55125
  union {
53796
55126
  float f;
53797
55127
  uint32_t i;
@@ -53820,6 +55150,7 @@ static JSValue js_dataview_setValue(JSContext *ctx,
53820
55150
  break;
53821
55151
  case JS_CLASS_INT16_ARRAY:
53822
55152
  case JS_CLASS_UINT16_ARRAY:
55153
+ case JS_CLASS_FLOAT16_ARRAY:
53823
55154
  if (is_swap)
53824
55155
  v = bswap16(v);
53825
55156
  put_u16(ptr, v);
@@ -53856,6 +55187,7 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
53856
55187
  JS_CFUNC_MAGIC_DEF("getUint32", 1, js_dataview_getValue, JS_CLASS_UINT32_ARRAY ),
53857
55188
  JS_CFUNC_MAGIC_DEF("getBigInt64", 1, js_dataview_getValue, JS_CLASS_BIG_INT64_ARRAY ),
53858
55189
  JS_CFUNC_MAGIC_DEF("getBigUint64", 1, js_dataview_getValue, JS_CLASS_BIG_UINT64_ARRAY ),
55190
+ JS_CFUNC_MAGIC_DEF("getFloat16", 1, js_dataview_getValue, JS_CLASS_FLOAT16_ARRAY ),
53859
55191
  JS_CFUNC_MAGIC_DEF("getFloat32", 1, js_dataview_getValue, JS_CLASS_FLOAT32_ARRAY ),
53860
55192
  JS_CFUNC_MAGIC_DEF("getFloat64", 1, js_dataview_getValue, JS_CLASS_FLOAT64_ARRAY ),
53861
55193
  JS_CFUNC_MAGIC_DEF("setInt8", 2, js_dataview_setValue, JS_CLASS_INT8_ARRAY ),
@@ -53866,6 +55198,7 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = {
53866
55198
  JS_CFUNC_MAGIC_DEF("setUint32", 2, js_dataview_setValue, JS_CLASS_UINT32_ARRAY ),
53867
55199
  JS_CFUNC_MAGIC_DEF("setBigInt64", 2, js_dataview_setValue, JS_CLASS_BIG_INT64_ARRAY ),
53868
55200
  JS_CFUNC_MAGIC_DEF("setBigUint64", 2, js_dataview_setValue, JS_CLASS_BIG_UINT64_ARRAY ),
55201
+ JS_CFUNC_MAGIC_DEF("setFloat16", 2, js_dataview_setValue, JS_CLASS_FLOAT16_ARRAY ),
53869
55202
  JS_CFUNC_MAGIC_DEF("setFloat32", 2, js_dataview_setValue, JS_CLASS_FLOAT32_ARRAY ),
53870
55203
  JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ),
53871
55204
  JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ),
@@ -54499,7 +55832,7 @@ typedef struct JSFinRecEntry {
54499
55832
  typedef struct JSFinalizationRegistryData {
54500
55833
  JSWeakRefHeader weakref_header;
54501
55834
  struct list_head entries; /* list of JSFinRecEntry.link */
54502
- JSContext *ctx;
55835
+ JSContext *realm;
54503
55836
  JSValue cb;
54504
55837
  } JSFinalizationRegistryData;
54505
55838
 
@@ -54516,6 +55849,7 @@ static void js_finrec_finalizer(JSRuntime *rt, JSValue val)
54516
55849
  js_free_rt(rt, fre);
54517
55850
  }
54518
55851
  JS_FreeValueRT(rt, frd->cb);
55852
+ JS_FreeContext(frd->realm);
54519
55853
  list_del(&frd->weakref_header.link);
54520
55854
  js_free_rt(rt, frd);
54521
55855
  }
@@ -54532,6 +55866,7 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst val,
54532
55866
  JS_MarkValue(rt, fre->held_val, mark_func);
54533
55867
  }
54534
55868
  JS_MarkValue(rt, frd->cb, mark_func);
55869
+ mark_func(rt, &frd->realm->header);
54535
55870
  }
54536
55871
  }
54537
55872
 
@@ -54557,7 +55892,7 @@ static void finrec_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh)
54557
55892
  JSValueConst args[2];
54558
55893
  args[0] = frd->cb;
54559
55894
  args[1] = fre->held_val;
54560
- JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args);
55895
+ JS_EnqueueJob(frd->realm, js_finrec_job, 2, args);
54561
55896
 
54562
55897
  js_weakref_free(rt, fre->target);
54563
55898
  js_weakref_free(rt, fre->token);
@@ -54592,7 +55927,7 @@ static JSValue js_finrec_constructor(JSContext *ctx, JSValueConst new_target,
54592
55927
  frd->weakref_header.weakref_type = JS_WEAKREF_TYPE_FINREC;
54593
55928
  list_add_tail(&frd->weakref_header.link, &ctx->rt->weakref_list);
54594
55929
  init_list_head(&frd->entries);
54595
- frd->ctx = ctx; /* XXX: JS_DupContext() ? */
55930
+ frd->realm = JS_DupContext(ctx);
54596
55931
  frd->cb = JS_DupValue(ctx, cb);
54597
55932
  JS_SetOpaque(obj, frd);
54598
55933
  return obj;