This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f0158126 QuickJS Update
8f0158126 is described below

commit 8f0158126a0774d2213454fb51e5d93d11e3b41b
Author: Nick Vatamaniuc <[email protected]>
AuthorDate: Mon Aug 25 15:39:02 2025 -0400

    QuickJS Update
    
     * TypedArray.prototype.subarray: fixed the step at which '[[ByteOffset]]' 
is
     read
     
https://github.com/bellard/quickjs/commit/c942978927a2a806517598a22a07c50766b3e125
     * Fixed buffer overflow in `js_bigint_from_string()`
     
https://github.com/bellard/quickjs/commit/e1c18befb8ef661d9ee8a34ebc54e545a0214df9
     * Fixed crash in OP_add_loc if the variable is modified in
     `JS_ToPrimitiveFree()`
     
https://github.com/bellard/quickjs/commit/1168c215d1daf2765a24d950079b1d5538305417
     * Fixed buffer overflow in `js_bigint_to_string1()`
     
https://github.com/bellard/quickjs/commit/9ce544289fe86acdb8fb33e6a425da151438be05
     * Fixed buffer overflow in `TypedArray.prototype.lastIndexOf()`
     
https://github.com/bellard/quickjs/commit/c927eca49a326326181a5db12627ffb48f191fe2
     * Avoid side effects in `JS_PrintValue()` which may lead to crashes in
     `print()` and `js_std_promise_rejection_check()`
     
https://github.com/bellard/quickjs/commit/4e0d0b7f807816097cd4e15996c5296984dc531b
     * Limit function and regexp bytecode to 1G to avoid buffer overflows (the
     bytecode generators assume that bytecode offsets can fit a 32 bit signed
     integer
     
https://github.com/bellard/quickjs/commit/d9ec8f102eb211f0b230a5ec3bf5da59f333e697
     * Adjust lastIndex to leading surrogate when inside a surrogate pair in
     unicode RegExp
     
https://github.com/bellard/quickjs/commit/a4ac84d993128ec4cfe2cadcbb0893a2c2565988
---
 .../patches/01-spidermonkey-185-mode.patch         |   6 +-
 .../patches/02-test262-makefile.patch              |   8 +-
 src/couch_quickjs/patches/03-test262-yield.patch   |   4 +-
 src/couch_quickjs/patches/04-test262-errors.patch  |   8 +-
 src/couch_quickjs/quickjs/Makefile                 |   4 +-
 src/couch_quickjs/quickjs/libregexp.c              |  25 +-
 src/couch_quickjs/quickjs/quickjs-libc.c           |  14 +-
 src/couch_quickjs/quickjs/quickjs.c                | 428 ++++++++++++++-------
 src/couch_quickjs/quickjs/run-test262.c            |  11 +-
 src/couch_quickjs/quickjs/test262.conf             |   2 +
 src/couch_quickjs/quickjs/test262_errors.txt       |  20 +-
 src/couch_quickjs/quickjs/tests/test262.patch      |  23 +-
 12 files changed, 370 insertions(+), 183 deletions(-)

diff --git a/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch 
b/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch
index d4a85a5a0..20ac3172e 100644
--- a/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch
+++ b/src/couch_quickjs/patches/01-spidermonkey-185-mode.patch
@@ -1,6 +1,6 @@
---- quickjs-master/quickjs.c   2025-06-14 05:51:48
-+++ quickjs/quickjs.c  2025-06-20 13:56:52
-@@ -30599,10 +30599,24 @@
+--- quickjs-master/quickjs.c   2025-08-25 12:20:58
++++ quickjs/quickjs.c  2025-08-25 15:10:50
+@@ -30776,10 +30776,24 @@
      if (s->token.val == TOK_FUNCTION ||
          (token_is_pseudo_keyword(s, JS_ATOM_async) &&
           peek_token(s, TRUE) == TOK_FUNCTION)) {
diff --git a/src/couch_quickjs/patches/02-test262-makefile.patch 
b/src/couch_quickjs/patches/02-test262-makefile.patch
index 1bfc17640..a4fb9b4b1 100644
--- a/src/couch_quickjs/patches/02-test262-makefile.patch
+++ b/src/couch_quickjs/patches/02-test262-makefile.patch
@@ -1,13 +1,13 @@
---- quickjs-master/Makefile    2025-06-14 05:51:48
-+++ quickjs/Makefile   2025-06-20 18:03:41
+--- quickjs-master/Makefile    2025-08-25 12:20:58
++++ quickjs/Makefile   2025-08-25 15:27:47
 @@ -53,6 +53,10 @@
  #CONFIG_MSAN=y
  # use UB sanitizer
  #CONFIG_UBSAN=y
 +
 +# TEST262 bootstrap config: commit id and shallow "since" parameter
-+TEST262_COMMIT?=3316c0aaf676d657f5a6b33364fa7e579c78ac7f
-+TEST262_SINCE?=2025-05-21
++TEST262_COMMIT?=04eaeb99080ceb60d7b86ea0c4bed6355ef4cdcb
++TEST262_SINCE?=2025-08-20
  
  OBJDIR=.obj
  
diff --git a/src/couch_quickjs/patches/03-test262-yield.patch 
b/src/couch_quickjs/patches/03-test262-yield.patch
index e4dc4c5be..419e609c3 100644
--- a/src/couch_quickjs/patches/03-test262-yield.patch
+++ b/src/couch_quickjs/patches/03-test262-yield.patch
@@ -1,5 +1,5 @@
---- quickjs-master/tests/test262.patch 2025-06-14 05:51:48
-+++ quickjs/tests/test262.patch        2025-06-20 18:03:41
+--- quickjs-master/tests/test262.patch 2025-08-25 12:20:58
++++ quickjs/tests/test262.patch        2025-08-25 15:10:50
 @@ -14,9 +14,9 @@
  +//  small: 200,
  +//  long: 1000,
diff --git a/src/couch_quickjs/patches/04-test262-errors.patch 
b/src/couch_quickjs/patches/04-test262-errors.patch
index 3de2591e6..d37155640 100644
--- a/src/couch_quickjs/patches/04-test262-errors.patch
+++ b/src/couch_quickjs/patches/04-test262-errors.patch
@@ -1,9 +1,9 @@
---- quickjs-master/test262_errors.txt  2025-06-14 05:51:48
-+++ quickjs/test262_errors.txt 2025-06-20 18:03:41
-@@ -1,6 +1,8 @@
+--- quickjs-master/test262_errors.txt  2025-08-25 12:20:58
++++ quickjs/test262_errors.txt 2025-08-25 15:13:35
+@@ -7,6 +7,8 @@
+ 
test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20:
 SyntaxError: invalid assignment left-hand side
  
test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34:
 TypeError: ArrayBuffer is detached
  
test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34:
 strict mode: TypeError: ArrayBuffer is detached
- 
test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10:
 TypeError: $DONE() not called
 +test262/test/language/statements/expression/S12.4_A1.js:15: unexpected error 
type: Test262: This statement should not be evaluated.
 +test262/test/language/statements/expression/S12.4_A1.js:15: strict mode: 
unexpected error type: Test262: This statement should not be evaluated.
  test262/test/staging/sm/Date/UTC-convert-all-arguments.js:75: Test262Error: 
index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't 
throw», «42») to be true
diff --git a/src/couch_quickjs/quickjs/Makefile 
b/src/couch_quickjs/quickjs/Makefile
index fd74c7be2..6ee5d4367 100644
--- a/src/couch_quickjs/quickjs/Makefile
+++ b/src/couch_quickjs/quickjs/Makefile
@@ -55,8 +55,8 @@ PREFIX?=/usr/local
 #CONFIG_UBSAN=y
 
 # TEST262 bootstrap config: commit id and shallow "since" parameter
-TEST262_COMMIT?=3316c0aaf676d657f5a6b33364fa7e579c78ac7f
-TEST262_SINCE?=2025-05-21
+TEST262_COMMIT?=04eaeb99080ceb60d7b86ea0c4bed6355ef4cdcb
+TEST262_SINCE?=2025-08-20
 
 OBJDIR=.obj
 
diff --git a/src/couch_quickjs/quickjs/libregexp.c 
b/src/couch_quickjs/quickjs/libregexp.c
index 2b33c8695..0cf9a1261 100644
--- a/src/couch_quickjs/quickjs/libregexp.c
+++ b/src/couch_quickjs/quickjs/libregexp.c
@@ -2433,6 +2433,17 @@ static int compute_stack_size(const uint8_t *bc_buf, int 
bc_buf_len)
     return stack_size_max;
 }
 
+static void *lre_bytecode_realloc(void *opaque, void *ptr, size_t size)
+{
+    if (size > (INT32_MAX / 2)) {
+        /* the bytecode cannot be larger than 2G. Leave some slack to 
+           avoid some overflows. */
+        return NULL;
+    } else {
+        return lre_realloc(opaque, ptr, size);
+    }
+}
+
 /* 'buf' must be a zero terminated UTF-8 string of length buf_len.
    Return NULL if error and allocate an error message in *perror_msg,
    otherwise the compiled bytecode and its length in plen.
@@ -2461,7 +2472,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int 
error_msg_size,
     s->total_capture_count = -1;
     s->has_named_captures = -1;
 
-    dbuf_init2(&s->byte_code, opaque, lre_realloc);
+    dbuf_init2(&s->byte_code, opaque, lre_bytecode_realloc);
     dbuf_init2(&s->group_names, opaque, lre_realloc);
 
     dbuf_put_u16(&s->byte_code, re_flags); /* first element is the flags */
@@ -3152,6 +3163,7 @@ int lre_exec(uint8_t **capture,
     REExecContext s_s, *s = &s_s;
     int re_flags, i, alloca_size, ret;
     StackInt *stack_buf;
+    const uint8_t *cptr;
 
     re_flags = lre_get_flags(bc_buf);
     s->is_unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 
0;
@@ -3176,8 +3188,17 @@ int lre_exec(uint8_t **capture,
         capture[i] = NULL;
     alloca_size = s->stack_size_max * sizeof(stack_buf[0]);
     stack_buf = alloca(alloca_size);
+
+    cptr = cbuf + (cindex << cbuf_type);
+    if (0 < cindex && cindex < clen && s->cbuf_type == 2) {
+        const uint16_t *p = (const uint16_t *)cptr;
+        if (is_lo_surrogate(*p) && is_hi_surrogate(p[-1])) {
+            cptr = (const uint8_t *)(p - 1);
+        }
+    }
+
     ret = lre_exec_backtrack(s, capture, stack_buf, 0, bc_buf + RE_HEADER_LEN,
-                             cbuf + (cindex << cbuf_type), FALSE);
+                             cptr, FALSE);
     lre_realloc(s->opaque, s->state_stack, 0);
     return ret;
 }
diff --git a/src/couch_quickjs/quickjs/quickjs-libc.c 
b/src/couch_quickjs/quickjs/quickjs-libc.c
index 10a7d00cc..54a7a15bd 100644
--- a/src/couch_quickjs/quickjs/quickjs-libc.c
+++ b/src/couch_quickjs/quickjs/quickjs-libc.c
@@ -4230,17 +4230,15 @@ static void js_std_promise_rejection_check(JSContext 
*ctx)
 /* main loop which calls the user JS callbacks */
 void js_std_loop(JSContext *ctx)
 {
-    JSContext *ctx1;
     int err;
 
     for(;;) {
         /* execute the pending jobs */
         for(;;) {
-            err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
+            err = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL);
             if (err <= 0) {
-                if (err < 0) {
-                    js_std_dump_error(ctx1);
-                }
+                if (err < 0)
+                    js_std_dump_error(ctx);
                 break;
             }
         }
@@ -4271,11 +4269,10 @@ JSValue js_std_await(JSContext *ctx, JSValue obj)
             JS_FreeValue(ctx, obj);
             break;
         } else if (state == JS_PROMISE_PENDING) {
-            JSContext *ctx1;
             int err;
-            err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
+            err = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL);
             if (err < 0) {
-                js_std_dump_error(ctx1);
+                js_std_dump_error(ctx);
             }
             if (err == 0) {
                 js_std_promise_rejection_check(ctx);
@@ -4303,6 +4300,7 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t 
*buf, size_t buf_len,
         if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {
             js_module_set_import_meta(ctx, obj, FALSE, FALSE);
         }
+        JS_FreeValue(ctx, obj);
     } else {
         if (JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE) {
             if (JS_ResolveModule(ctx, obj) < 0) {
diff --git a/src/couch_quickjs/quickjs/quickjs.c 
b/src/couch_quickjs/quickjs/quickjs.c
index 10d28d6f1..2f1291702 100644
--- a/src/couch_quickjs/quickjs/quickjs.c
+++ b/src/couch_quickjs/quickjs/quickjs.c
@@ -103,6 +103,7 @@
 //#define DUMP_ATOMS      /* dump atoms in JS_FreeContext */
 //#define DUMP_SHAPES     /* dump shapes in JS_FreeContext */
 //#define DUMP_MODULE_RESOLVE
+//#define DUMP_MODULE_EXEC
 //#define DUMP_PROMISE
 //#define DUMP_READ_OBJECT
 //#define DUMP_ROPE_REBALANCE
@@ -340,6 +341,7 @@ typedef enum {
     JS_GC_OBJ_TYPE_VAR_REF,
     JS_GC_OBJ_TYPE_ASYNC_FUNCTION,
     JS_GC_OBJ_TYPE_JS_CONTEXT,
+    JS_GC_OBJ_TYPE_MODULE,
 } JSGCObjectTypeEnum;
 
 /* header for GC objects. GC objects are C data structures with a
@@ -804,7 +806,7 @@ typedef enum {
 } JSModuleStatus;
 
 struct JSModuleDef {
-    JSRefCountHeader header; /* must come first, 32-bit */
+    JSGCObjectHeader header; /* must come first */
     JSAtom module_name;
     struct list_head link;
 
@@ -839,7 +841,8 @@ struct JSModuleDef {
     int async_parent_modules_count;
     int async_parent_modules_size;
     int pending_async_dependencies;
-    BOOL async_evaluation;
+    BOOL async_evaluation; /* true: async_evaluation_timestamp corresponds to 
[[AsyncEvaluationOrder]] 
+                              false: [[AsyncEvaluationOrder]] is UNSET or DONE 
*/
     int64_t async_evaluation_timestamp;
     JSModuleDef *cycle_root;
     JSValue promise; /* corresponds to spec field: capability */
@@ -855,7 +858,7 @@ struct JSModuleDef {
 
 typedef struct JSJobEntry {
     struct list_head link;
-    JSContext *ctx;
+    JSContext *realm;
     JSJobFunc *job_func;
     int argc;
     JSValue argv[0];
@@ -1220,7 +1223,7 @@ static void js_async_function_resolve_mark(JSRuntime *rt, 
JSValueConst val,
 static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
                                const char *input, size_t input_len,
                                const char *filename, int flags, int scope_idx);
-static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
+static void js_free_module_def(JSRuntime *rt, JSModuleDef *m);
 static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
                                JS_MarkFunc *mark_func);
 static JSValue js_import_meta(JSContext *ctx);
@@ -1467,6 +1470,23 @@ static inline void js_dbuf_init(JSContext *ctx, DynBuf 
*s)
     dbuf_init2(s, ctx->rt, (DynBufReallocFunc *)js_realloc_rt);
 }
 
+static void *js_realloc_bytecode_rt(void *opaque, void *ptr, size_t size)
+{
+    JSRuntime *rt = opaque;
+    if (size > (INT32_MAX / 2)) {
+        /* the bytecode cannot be larger than 2G. Leave some slack to 
+           avoid some overflows. */
+        return NULL;
+    } else {
+        return rt->mf.js_realloc(&rt->malloc_state, ptr, size);
+    }
+}
+
+static inline void js_dbuf_bytecode_init(JSContext *ctx, DynBuf *s)
+{
+    dbuf_init2(s, ctx->rt, js_realloc_bytecode_rt);
+}
+
 static inline int is_digit(int c) {
     return c >= '0' && c <= '9';
 }
@@ -1780,7 +1800,7 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
     e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));
     if (!e)
         return -1;
-    e->ctx = ctx;
+    e->realm = JS_DupContext(ctx);
     e->job_func = job_func;
     e->argc = argc;
     for(i = 0; i < argc; i++) {
@@ -1796,7 +1816,10 @@ BOOL JS_IsJobPending(JSRuntime *rt)
 }
 
 /* return < 0 if exception, 0 if no job pending, 1 if a job was
-   executed successfully. the context of the job is stored in '*pctx' */
+   executed successfully. The context of the job is stored in '*pctx'
+   if pctx != NULL. It may be NULL if the context was already
+   destroyed or if no job was pending. The 'pctx' parameter is now
+   absolete. */
 int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
 {
     JSContext *ctx;
@@ -1805,15 +1828,16 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext 
**pctx)
     int i, ret;
 
     if (list_empty(&rt->job_list)) {
-        *pctx = NULL;
+        if (pctx)
+            *pctx = NULL;
         return 0;
     }
 
     /* get the first pending job and execute it */
     e = list_entry(rt->job_list.next, JSJobEntry, link);
     list_del(&e->link);
-    ctx = e->ctx;
-    res = e->job_func(e->ctx, e->argc, (JSValueConst *)e->argv);
+    ctx = e->realm;
+    res = e->job_func(ctx, e->argc, (JSValueConst *)e->argv);
     for(i = 0; i < e->argc; i++)
         JS_FreeValue(ctx, e->argv[i]);
     if (JS_IsException(res))
@@ -1822,7 +1846,13 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
         ret = 1;
     JS_FreeValue(ctx, res);
     js_free(ctx, e);
-    *pctx = ctx;
+    if (pctx) {
+        if (ctx->header.ref_count > 1)
+            *pctx = ctx;
+        else
+            *pctx = NULL;
+    }
+    JS_FreeContext(ctx);
     return ret;
 }
 
@@ -1903,6 +1933,7 @@ void JS_FreeRuntime(JSRuntime *rt)
         JSJobEntry *e = list_entry(el, JSJobEntry, link);
         for(i = 0; i < e->argc; i++)
             JS_FreeValueRT(rt, e->argv[i]);
+        JS_FreeContext(e->realm);
         js_free_rt(rt, e);
     }
     init_list_head(&rt->job_list);
@@ -2178,7 +2209,13 @@ static void js_free_modules(JSContext *ctx, 
JSFreeModuleEnum flag)
         JSModuleDef *m = list_entry(el, JSModuleDef, link);
         if (flag == JS_FREE_MODULE_ALL ||
             (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) {
-            js_free_module_def(ctx, m);
+            /* warning: the module may be referenced elsewhere. It
+               could be simpler to use an array instead of a list for
+               'ctx->loaded_modules' */
+            list_del(&m->link);
+            m->link.prev = NULL;
+            m->link.next = NULL;
+            JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
         }
     }
 }
@@ -2196,11 +2233,9 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,
     int i;
     struct list_head *el;
 
-    /* modules are not seen by the GC, so we directly mark the objects
-       referenced by each module */
     list_for_each(el, &ctx->loaded_modules) {
         JSModuleDef *m = list_entry(el, JSModuleDef, link);
-        js_mark_module_def(rt, m, mark_func);
+        JS_MarkValue(rt, JS_MKPTR(JS_TAG_MODULE, m), mark_func);
     }
 
     JS_MarkValue(rt, ctx->global_obj, mark_func);
@@ -5781,6 +5816,9 @@ static void free_gc_object(JSRuntime *rt, 
JSGCObjectHeader *gp)
     case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
         __async_func_free(rt, (JSAsyncFunctionState *)gp);
         break;
+    case JS_GC_OBJ_TYPE_MODULE:
+        js_free_module_def(rt, (JSModuleDef *)gp);
+        break;
     default:
         abort();
     }
@@ -5845,6 +5883,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
         break;
     case JS_TAG_OBJECT:
     case JS_TAG_FUNCTION_BYTECODE:
+    case JS_TAG_MODULE:
         {
             JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);
             if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
@@ -5857,9 +5896,6 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
             }
         }
         break;
-    case JS_TAG_MODULE:
-        abort(); /* never freed here */
-        break;
     case JS_TAG_BIG_INT:
         {
             JSBigInt *p = JS_VALUE_GET_PTR(v);
@@ -5933,6 +5969,7 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, 
JS_MarkFunc *mark_func)
         switch(JS_VALUE_GET_TAG(val)) {
         case JS_TAG_OBJECT:
         case JS_TAG_FUNCTION_BYTECODE:
+        case JS_TAG_MODULE:
             mark_func(rt, JS_VALUE_GET_PTR(val));
             break;
         default:
@@ -6045,6 +6082,12 @@ static void mark_children(JSRuntime *rt, 
JSGCObjectHeader *gp,
             JS_MarkContext(rt, ctx, mark_func);
         }
         break;
+    case JS_GC_OBJ_TYPE_MODULE:
+        {
+            JSModuleDef *m = (JSModuleDef *)gp;
+            js_mark_module_def(rt, m, mark_func);
+        }
+        break;
     default:
         abort();
     }
@@ -6141,6 +6184,7 @@ static void gc_free_cycles(JSRuntime *rt)
         case JS_GC_OBJ_TYPE_JS_OBJECT:
         case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
         case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
+        case JS_GC_OBJ_TYPE_MODULE:
 #ifdef DUMP_GC_FREE
             if (!header_done) {
                 printf("Freeing cycles:\n");
@@ -6163,7 +6207,8 @@ static void gc_free_cycles(JSRuntime *rt)
         p = list_entry(el, JSGCObjectHeader, link);
         assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
                p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
-               p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
+               p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION ||
+               p->gc_obj_type == JS_GC_OBJ_TYPE_MODULE);
         if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT &&
             ((JSObject *)p)->weakref_count != 0) {
             /* keep the object because there are weak references to it */
@@ -6849,20 +6894,30 @@ static int find_line_num(JSContext *ctx, 
JSFunctionBytecode *b,
     return 0;
 }
 
-/* in order to avoid executing arbitrary code during the stack trace
-   generation, we only look at simple 'name' properties containing a
-   string. */
-static const char *get_func_name(JSContext *ctx, JSValueConst func)
+/* return a string property without executing arbitrary JS code (used
+   when dumping the stack trace or in debug print). */
+static const char *get_prop_string(JSContext *ctx, JSValueConst obj, JSAtom 
prop)
 {
+    JSObject *p;
     JSProperty *pr;
     JSShapeProperty *prs;
     JSValueConst val;
 
-    if (JS_VALUE_GET_TAG(func) != JS_TAG_OBJECT)
-        return NULL;
-    prs = find_own_property(&pr, JS_VALUE_GET_OBJ(func), JS_ATOM_name);
-    if (!prs)
+    if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)
         return NULL;
+    p = JS_VALUE_GET_OBJ(obj);
+    prs = find_own_property(&pr, p, prop);
+    if (!prs) {
+        /* we look at one level in the prototype to handle the 'name'
+           field of the Error objects */
+        p = p->shape->proto;
+        if (!p)
+            return NULL;
+        prs = find_own_property(&pr, p, prop);
+        if (!prs)
+            return NULL;
+    }
+    
     if ((prs->flags & JS_PROP_TMASK) != JS_PROP_NORMAL)
         return NULL;
     val = pr->u.value;
@@ -6915,7 +6970,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst 
error_obj,
             backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
             continue;
         }
-        func_name_str = get_func_name(ctx, sf->cur_func);
+        func_name_str = get_prop_string(ctx, sf->cur_func, JS_ATOM_name);
         if (!func_name_str || func_name_str[0] == '\0')
             str1 = "<anonymous>";
         else
@@ -11717,6 +11772,7 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx,
                                        const char *str, int radix)
 {
     const char *p = str;
+    size_t n_digits1;
     int is_neg, n_digits, n_limbs, len, log2_radix, n_bits, i;
     JSBigInt *r;
     js_limb_t v, c, h;
@@ -11728,10 +11784,16 @@ static JSBigInt *js_bigint_from_string(JSContext *ctx,
     }
     while (*p == '0')
         p++;
-    n_digits = strlen(p);
+    n_digits1 = strlen(p);
+    /* the real check for overflox is done js_bigint_new(). Here
+       we just avoid integer overflow */
+    if (n_digits1 > JS_BIGINT_MAX_SIZE * JS_LIMB_BITS) {
+        JS_ThrowRangeError(ctx, "BigInt is too large to allocate");
+        return NULL;
+    }
+    n_digits = n_digits1;
     log2_radix = 32 - clz32(radix - 1); /* ceil(log2(radix)) */
     /* compute the maximum number of limbs */
-    /* XXX: overflow */
     if (radix == 10) {
         n_bits = (n_digits * 27 + 7) / 8; /* >= ceil(n_digits * log2(10)) */
     } else {
@@ -11962,11 +12024,10 @@ static JSValue js_bigint_to_string1(JSContext *ctx, 
JSValueConst val, int radix)
                 bit_pos = i * log2_radix;
                 pos = bit_pos / JS_LIMB_BITS;
                 shift = bit_pos % JS_LIMB_BITS;
-                if (likely((shift + log2_radix) <= JS_LIMB_BITS)) {
-                    c = r->tab[pos] >> shift;
-                } else {
-                    c = (r->tab[pos] >> shift) |
-                        (r->tab[pos + 1] << (JS_LIMB_BITS - shift));
+                c = r->tab[pos] >> shift;
+                if ((shift + log2_radix) > JS_LIMB_BITS &&
+                    (pos + 1) < r->len) {
+                    c |= r->tab[pos + 1] << (JS_LIMB_BITS - shift);
                 }
                 c &= (radix - 1);
                 *--q = digits[c];
@@ -12179,8 +12240,10 @@ static JSValue js_atof(JSContext *ctx, const char 
*str, const char **pp,
             if (has_legacy_octal || is_float)
                 goto fail;
             r = js_bigint_from_string(ctx, buf, radix);
-            if (!r)
-                goto mem_error;
+            if (!r) {
+                val = JS_EXCEPTION;
+                goto done;
+            }
             val = JS_CompactBigInt(ctx, r);
         }
         break;
@@ -13118,24 +13181,17 @@ static void js_print_string(JSPrintValueState *s, 
JSValueConst val)
     }
 }
 
-static void js_print_raw_string2(JSPrintValueState *s, JSValueConst val, BOOL 
remove_last_lf)
+static void js_print_raw_string(JSPrintValueState *s, JSValueConst val)
 {
     const char *cstr;
     size_t len;
     cstr = JS_ToCStringLen(s->ctx, &len, val);
     if (cstr) {
-        if (remove_last_lf && len > 0 && cstr[len - 1] == '\n')
-            len--;
         s->write_func(s->write_opaque, cstr, len);
         JS_FreeCString(s->ctx, cstr);
     }
 }
 
-static void js_print_raw_string(JSPrintValueState *s, JSValueConst val)
-{
-    js_print_raw_string2(s, val, FALSE);
-}
-
 static BOOL is_ascii_ident(const JSString *p)
 {
     int i, c;
@@ -13221,6 +13277,104 @@ static void js_print_more_items(JSPrintValueState *s, 
int *pcomma_state,
     js_printf(s, "... %u more item%s", n, n > 1 ? "s" : "");
 }
 
+/* similar to js_regexp_toString() but without side effect */
+static void js_print_regexp(JSPrintValueState *s, JSObject *p1)
+{
+    JSRegExp *re = &p1->u.regexp;
+    JSString *p;
+    int i, n, c, c2, bra, flags;
+    static const char regexp_flags[] = { 'g', 'i', 'm', 's', 'u', 'y', 'd', 
'v' };
+
+    p = re->pattern;
+    js_putc(s, '/');
+    if (p->len == 0) {
+        js_puts(s, "(?:)");
+    } else {
+        bra = 0;
+        for (i = 0, n = p->len; i < n;) {
+            c2 = -1;
+            switch (c = string_get(p, i++)) {
+            case '\\':
+                if (i < n)
+                    c2 = string_get(p, i++);
+                break;
+            case ']':
+                bra = 0;
+                break;
+            case '[':
+                if (!bra) {
+                    if (i < n && string_get(p, i) == ']')
+                        c2 = string_get(p, i++);
+                    bra = 1;
+                }
+                break;
+            case '\n':
+                c = '\\';
+                c2 = 'n';
+                break;
+            case '\r':
+                c = '\\';
+                c2 = 'r';
+                break;
+            case '/':
+                if (!bra) {
+                    c = '\\';
+                    c2 = '/';
+                }
+                break;
+            }
+            js_putc(s, c);
+            if (c2 >= 0)
+                js_putc(s, c2);
+        }
+    }
+    js_putc(s, '/');
+
+    flags = lre_get_flags(re->bytecode->u.str8);
+    for(i = 0; i < countof(regexp_flags); i++) {
+        if ((flags >> i) & 1) {
+            js_putc(s, regexp_flags[i]);
+        }
+    }
+}
+
+/* similar to js_error_toString() but without side effect */
+static void js_print_error(JSPrintValueState *s, JSObject *p)
+{
+    const char *str;
+    size_t len;
+
+    str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_name);
+    if (!str) {
+        js_puts(s, "Error");
+    } else {
+        js_puts(s, str);
+        JS_FreeCString(s->ctx, str);
+    }
+    
+    str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_message);
+    if (str && str[0] != '\0') {
+        js_puts(s, ": ");
+        js_puts(s, str);
+    }
+    JS_FreeCString(s->ctx, str);
+
+    /* dump the stack if present */
+    str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), JS_ATOM_stack);
+    if (str) {
+        js_putc(s, '\n');
+        
+        /* XXX: should remove the last '\n' in stack as
+           v8. SpiderMonkey does not do it */
+        len = strlen(str);
+        if (len > 0 && str[len - 1] == '\n')
+            len--;
+        s->write_func(s->write_opaque, str, len);
+        
+        JS_FreeCString(s->ctx, str);
+    }
+}
+
 static void js_print_object(JSPrintValueState *s, JSObject *p)
 {
     JSRuntime *rt = s->rt;
@@ -13316,7 +13470,7 @@ static void js_print_object(JSPrintValueState *s, 
JSObject *p)
         if (!s->options.raw_dump && s->ctx) {
             const char *func_name_str;
             js_putc(s, ' ');
-            func_name_str = get_func_name(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p));
+            func_name_str = get_prop_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, 
p), JS_ATOM_name);
             if (!func_name_str || func_name_str[0] == '\0')
                 js_puts(s, "(anonymous)");
             else
@@ -13350,35 +13504,19 @@ static void js_print_object(JSPrintValueState *s, 
JSObject *p)
         }
         if (i < ms->record_count)
             js_print_more_items(s, &comma_state, ms->record_count - i);
-    } else if (p->class_id == JS_CLASS_REGEXP && s->ctx && 
!s->options.raw_dump) {
-        JSValue str = js_regexp_toString(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 
0, NULL);
-        if (JS_IsException(str))
-            goto default_obj;
-        js_print_raw_string(s, str);
-        JS_FreeValueRT(s->rt, str);
+    } else if (p->class_id == JS_CLASS_REGEXP && s->ctx) {
+        js_print_regexp(s, p);
         comma_state = 2;
-    } else if (p->class_id == JS_CLASS_DATE && s->ctx && !s->options.raw_dump) 
{
+    } else if (p->class_id == JS_CLASS_DATE && s->ctx) {
+        /* get_date_string() has no side effect */
         JSValue str = get_date_string(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 0, 
NULL, 0x23); /* toISOString() */
         if (JS_IsException(str))
             goto default_obj;
         js_print_raw_string(s, str);
         JS_FreeValueRT(s->rt, str);
         comma_state = 2;
-    } else if (p->class_id == JS_CLASS_ERROR && s->ctx && 
!s->options.raw_dump) {
-        JSValue str = js_error_toString(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 0, 
NULL);
-        if (JS_IsException(str))
-            goto default_obj;
-        js_print_raw_string(s, str);
-        JS_FreeValueRT(s->rt, str);
-        /* dump the stack if present */
-        str = JS_GetProperty(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 
JS_ATOM_stack);
-        if (JS_IsString(str)) {
-            js_putc(s, '\n');
-            /* XXX: should remove the last '\n' in stack as
-               v8. SpiderMonkey does not do it */
-            js_print_raw_string2(s, str, TRUE);
-        }
-        JS_FreeValueRT(s->rt, str);
+    } else if (p->class_id == JS_CLASS_ERROR && s->ctx) {
+        js_print_error(s, p);
         comma_state = 2;
     } else {
         default_obj:
@@ -13745,6 +13883,9 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime 
*rt, JSGCObjectHeader *p)
         case JS_GC_OBJ_TYPE_JS_CONTEXT:
             printf("[js_context]");
             break;
+        case JS_GC_OBJ_TYPE_MODULE:
+            printf("[module]");
+            break;
         default:
             printf("[unknown %d]", p->gc_obj_type);
             break;
@@ -18606,12 +18747,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, 
JSValueConst func_obj,
                     *pv = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(*pv) +
                                                JS_VALUE_GET_FLOAT64(op2));
                     sp--;
-                } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING) {
+                } else if (JS_VALUE_GET_TAG(*pv) == JS_TAG_STRING &&
+                           JS_VALUE_GET_TAG(op2) == JS_TAG_STRING) {
                     sp--;
                     sf->cur_pc = pc;
-                    op2 = JS_ToPrimitiveFree(ctx, op2, HINT_NONE);
-                    if (JS_IsException(op2))
-                        goto exception;
                     if (JS_ConcatStringInPlace(ctx, JS_VALUE_GET_STRING(*pv), 
op2)) {
                         JS_FreeValue(ctx, op2);
                     } else {
@@ -28214,7 +28353,7 @@ fail:
     return -1;
 }
 
-/* 'name' is freed */
+/* 'name' is freed. The module is referenced by 'ctx->loaded_modules' */
 static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
 {
     JSModuleDef *m;
@@ -28224,6 +28363,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, 
JSAtom name)
         return NULL;
     }
     m->header.ref_count = 1;
+    add_gc_object(ctx->rt, &m->header, JS_GC_OBJ_TYPE_MODULE);
     m->module_name = name;
     m->module_ns = JS_UNDEFINED;
     m->func_obj = JS_UNDEFINED;
@@ -28265,47 +28405,56 @@ static void js_mark_module_def(JSRuntime *rt, 
JSModuleDef *m,
     JS_MarkValue(rt, m->private_value, mark_func);
 }
 
-static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
+static void js_free_module_def(JSRuntime *rt, JSModuleDef *m)
 {
     int i;
 
-    JS_FreeAtom(ctx, m->module_name);
+    JS_FreeAtomRT(rt, m->module_name);
 
     for(i = 0; i < m->req_module_entries_count; i++) {
         JSReqModuleEntry *rme = &m->req_module_entries[i];
-        JS_FreeAtom(ctx, rme->module_name);
-        JS_FreeValue(ctx, rme->attributes);
+        JS_FreeAtomRT(rt, rme->module_name);
+        JS_FreeValueRT(rt, rme->attributes);
     }
-    js_free(ctx, m->req_module_entries);
+    js_free_rt(rt, m->req_module_entries);
 
     for(i = 0; i < m->export_entries_count; i++) {
         JSExportEntry *me = &m->export_entries[i];
         if (me->export_type == JS_EXPORT_TYPE_LOCAL)
-            free_var_ref(ctx->rt, me->u.local.var_ref);
-        JS_FreeAtom(ctx, me->export_name);
-        JS_FreeAtom(ctx, me->local_name);
+            free_var_ref(rt, me->u.local.var_ref);
+        JS_FreeAtomRT(rt, me->export_name);
+        JS_FreeAtomRT(rt, me->local_name);
     }
-    js_free(ctx, m->export_entries);
+    js_free_rt(rt, m->export_entries);
 
-    js_free(ctx, m->star_export_entries);
+    js_free_rt(rt, m->star_export_entries);
 
     for(i = 0; i < m->import_entries_count; i++) {
         JSImportEntry *mi = &m->import_entries[i];
-        JS_FreeAtom(ctx, mi->import_name);
+        JS_FreeAtomRT(rt, mi->import_name);
     }
-    js_free(ctx, m->import_entries);
-    js_free(ctx, m->async_parent_modules);
+    js_free_rt(rt, m->import_entries);
+    js_free_rt(rt, m->async_parent_modules);
 
-    JS_FreeValue(ctx, m->module_ns);
-    JS_FreeValue(ctx, m->func_obj);
-    JS_FreeValue(ctx, m->eval_exception);
-    JS_FreeValue(ctx, m->meta_obj);
-    JS_FreeValue(ctx, m->promise);
-    JS_FreeValue(ctx, m->resolving_funcs[0]);
-    JS_FreeValue(ctx, m->resolving_funcs[1]);
-    JS_FreeValue(ctx, m->private_value);
-    list_del(&m->link);
-    js_free(ctx, m);
+    JS_FreeValueRT(rt, m->module_ns);
+    JS_FreeValueRT(rt, m->func_obj);
+    JS_FreeValueRT(rt, m->eval_exception);
+    JS_FreeValueRT(rt, m->meta_obj);
+    JS_FreeValueRT(rt, m->promise);
+    JS_FreeValueRT(rt, m->resolving_funcs[0]);
+    JS_FreeValueRT(rt, m->resolving_funcs[1]);
+    JS_FreeValueRT(rt, m->private_value);
+    /* during the GC the finalizers are called in an arbitrary
+       order so the module may no longer be referenced by the JSContext list */
+    if (m->link.next) {
+        list_del(&m->link);
+    }
+    remove_gc_object(&m->header);
+    if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && m->header.ref_count != 0) 
{
+        list_add_tail(&m->header.link, &rt->gc_zero_ref_count_list);
+    } else {
+        js_free_rt(rt, m);
+    }
 }
 
 static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
@@ -29833,6 +29982,14 @@ static int exec_module_list_cmp(const void *p1, const 
void *p2, void *opaque)
 static int js_execute_async_module(JSContext *ctx, JSModuleDef *m);
 static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
                                   JSValue *pvalue);
+#ifdef DUMP_MODULE_EXEC
+static void js_dump_module(JSContext *ctx, const char *str, JSModuleDef *m)
+{
+    char buf1[ATOM_GET_STR_BUF_SIZE];
+    static const char *module_status_str[] = { "unlinked", "linking", 
"linked", "evaluating", "evaluating_async", "evaluated" };
+    printf("%s: %s status=%s\n", str, JS_AtomGetStr(ctx, buf1, sizeof(buf1), 
m->module_name), module_status_str[m->status]);
+}
+#endif
 
 static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst 
this_val,
                                                   int argc, JSValueConst 
*argv, int magic, JSValue *func_data)
@@ -29841,6 +29998,9 @@ static JSValue 
js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
     JSValueConst error = argv[0];
     int i;
 
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, module);
+#endif
     if (js_check_stack_overflow(ctx->rt, 0))
         return JS_ThrowStackOverflow(ctx);
 
@@ -29856,6 +30016,7 @@ static JSValue 
js_async_module_execution_rejected(JSContext *ctx, JSValueConst t
     module->eval_has_exception = TRUE;
     module->eval_exception = JS_DupValue(ctx, error);
     module->status = JS_MODULE_STATUS_EVALUATED;
+    module->async_evaluation = FALSE;
 
     for(i = 0; i < module->async_parent_modules_count; i++) {
         JSModuleDef *m = module->async_parent_modules[i];
@@ -29882,6 +30043,9 @@ static JSValue 
js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
     ExecModuleList exec_list_s, *exec_list = &exec_list_s;
     int i;
 
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, module);
+#endif
     if (module->status == JS_MODULE_STATUS_EVALUATED) {
         assert(module->eval_has_exception);
         return JS_UNDEFINED;
@@ -29907,6 +30071,9 @@ static JSValue 
js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
 
     for(i = 0; i < exec_list->count; i++) {
         JSModuleDef *m = exec_list->tab[i];
+#ifdef DUMP_MODULE_EXEC
+        printf("  %d/%d", i, exec_list->count); js_dump_module(ctx, "", m);
+#endif
         if (m->status == JS_MODULE_STATUS_EVALUATED) {
             assert(m->eval_has_exception);
         } else if (m->has_tla) {
@@ -29921,6 +30088,7 @@ static JSValue 
js_async_module_execution_fulfilled(JSContext *ctx, JSValueConst
                 JS_FreeValue(ctx, m_obj);
                 JS_FreeValue(ctx, error);
             } else {
+                m->async_evaluation = FALSE;
                 js_set_module_evaluated(ctx, m);
             }
         }
@@ -29933,6 +30101,9 @@ static int js_execute_async_module(JSContext *ctx, 
JSModuleDef *m)
 {
     JSValue promise, m_obj;
     JSValue resolve_funcs[2], ret_val;
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, m);
+#endif
     promise = js_async_function_call(ctx, m->func_obj, JS_UNDEFINED, 0, NULL, 
0);
     if (JS_IsException(promise))
         return -1;
@@ -29952,6 +30123,9 @@ static int js_execute_async_module(JSContext *ctx, 
JSModuleDef *m)
 static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m,
                                   JSValue *pvalue)
 {
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, m);
+#endif
     if (m->init_func) {
         /* C module init : no asynchronous execution */
         if (m->init_func(ctx, m) < 0)
@@ -29991,19 +30165,16 @@ static int js_inner_module_evaluation(JSContext *ctx, 
JSModuleDef *m,
     JSModuleDef *m1;
     int i;
 
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, m);
+#endif
+
     if (js_check_stack_overflow(ctx->rt, 0)) {
         JS_ThrowStackOverflow(ctx);
         *pvalue = JS_GetException(ctx);
         return -1;
     }
 
-#ifdef DUMP_MODULE_RESOLVE
-    {
-        char buf1[ATOM_GET_STR_BUF_SIZE];
-        printf("js_inner_module_evaluation '%s':\n", JS_AtomGetStr(ctx, buf1, 
sizeof(buf1), m->module_name));
-    }
-#endif
-
     if (m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
         m->status == JS_MODULE_STATUS_EVALUATED) {
         if (m->eval_has_exception) {
@@ -30104,6 +30275,9 @@ static JSValue js_evaluate_module(JSContext *ctx, 
JSModuleDef *m)
     JSModuleDef *m1, *stack_top;
     JSValue ret_val, result;
 
+#ifdef DUMP_MODULE_EXEC
+    js_dump_module(ctx, __func__, m);
+#endif
     assert(m->status == JS_MODULE_STATUS_LINKED ||
            m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
            m->status == JS_MODULE_STATUS_EVALUATED);
@@ -30136,6 +30310,9 @@ static JSValue js_evaluate_module(JSContext *ctx, 
JSModuleDef *m)
                           1, (JSValueConst *)&m->eval_exception);
         JS_FreeValue(ctx, ret_val);
     } else {
+#ifdef DUMP_MODULE_EXEC
+        js_dump_module(ctx, "  done", m);
+#endif
         assert(m->status == JS_MODULE_STATUS_EVALUATING_ASYNC ||
                m->status == JS_MODULE_STATUS_EVALUATED);
         assert(!m->eval_has_exception);
@@ -30663,7 +30840,7 @@ static JSFunctionDef *js_new_function_def(JSContext 
*ctx,
 
     fd->is_eval = is_eval;
     fd->is_func_expr = is_func_expr;
-    js_dbuf_init(ctx, &fd->byte_code);
+    js_dbuf_bytecode_init(ctx, &fd->byte_code);
     fd->last_opcode_pos = -1;
     fd->func_name = JS_ATOM_NULL;
     fd->var_object_idx = -1;
@@ -32758,7 +32935,7 @@ static __exception int resolve_variables(JSContext 
*ctx, JSFunctionDef *s)
 
     cc.bc_buf = bc_buf = s->byte_code.buf;
     cc.bc_len = bc_len = s->byte_code.size;
-    js_dbuf_init(ctx, &bc_out);
+    js_dbuf_bytecode_init(ctx, &bc_out);
 
     /* first pass for runtime checks (must be done before the
        variables are created) */
@@ -33378,7 +33555,7 @@ static __exception int resolve_labels(JSContext *ctx, 
JSFunctionDef *s)
 
     cc.bc_buf = bc_buf = s->byte_code.buf;
     cc.bc_len = bc_len = s->byte_code.size;
-    js_dbuf_init(ctx, &bc_out);
+    js_dbuf_bytecode_init(ctx, &bc_out);
 
 #if SHORT_OPCODES
     if (s->jump_size) {
@@ -35788,7 +35965,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, 
JSValueConst this_obj,
  fail1:
     /* XXX: should free all the unresolved dependencies */
     if (m)
-        js_free_module_def(ctx, m);
+        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
     return JS_EXCEPTION;
 }
 
@@ -37500,7 +37677,7 @@ static JSValue JS_ReadModule(BCReaderState *s)
     return obj;
  fail:
     if (m) {
-        js_free_module_def(ctx, m);
+        JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
     }
     return JS_EXCEPTION;
 }
@@ -53558,22 +53735,12 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, 
JSValueConst this_val,
     if (special == special_lastIndexOf) {
         k = len - 1;
         if (argc > 1) {
-            if (JS_ToFloat64(ctx, &d, argv[1]))
+            int64_t k1;
+            if (JS_ToInt64Clamp(ctx, &k1, argv[1], -1, len - 1, len))
                 goto exception;
-            if (isnan(d)) {
-                k = 0;
-            } else {
-                if (d >= 0) {
-                    if (d < k) {
-                        k = d;
-                    }
-                } else {
-                    d += len;
-                    if (d < 0)
-                        goto done;
-                    k = d;
-                }
-            }
+            k = k1;
+            if (k < 0)
+                goto done;
         }
         stop = -1;
         inc = -1;
@@ -54054,16 +54221,17 @@ static JSValue js_typed_array_subarray(JSContext 
*ctx, JSValueConst this_val,
     if (JS_ToInt32Clamp(ctx, &start, argv[0], 0, len, len))
         goto exception;
 
+    shift = typed_array_size_log2(p->class_id);
+    ta = p->u.typed_array;
+    /* Read byteOffset (ta->offset) even if detached */
+    offset = ta->offset + (start << shift);
+
     final = len;
     if (!JS_IsUndefined(argv[1])) {
         if (JS_ToInt32Clamp(ctx, &final, argv[1], 0, len, len))
             goto exception;
     }
     count = max_int(final - start, 0);
-    shift = typed_array_size_log2(p->class_id);
-    ta = p->u.typed_array;
-    /* Read byteOffset (ta->offset) even if detached */
-    offset = ta->offset + (start << shift);
     ta_buffer = js_typed_array_get_buffer(ctx, this_val, 0);
     if (JS_IsException(ta_buffer))
         goto exception;
@@ -55647,7 +55815,7 @@ typedef struct JSFinRecEntry {
 typedef struct JSFinalizationRegistryData {
     JSWeakRefHeader weakref_header;
     struct list_head entries; /* list of JSFinRecEntry.link */
-    JSContext *ctx;
+    JSContext *realm;
     JSValue cb;
 } JSFinalizationRegistryData;
 
@@ -55664,6 +55832,7 @@ static void js_finrec_finalizer(JSRuntime *rt, JSValue 
val)
             js_free_rt(rt, fre);
         }
         JS_FreeValueRT(rt, frd->cb);
+        JS_FreeContext(frd->realm);
         list_del(&frd->weakref_header.link);
         js_free_rt(rt, frd);
     }
@@ -55680,6 +55849,7 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst 
val,
             JS_MarkValue(rt, fre->held_val, mark_func);
         }
         JS_MarkValue(rt, frd->cb, mark_func);
+        mark_func(rt, &frd->realm->header);
     }
 }
 
@@ -55705,7 +55875,7 @@ static void finrec_delete_weakref(JSRuntime *rt, 
JSWeakRefHeader *wh)
             JSValueConst args[2];
             args[0] = frd->cb;
             args[1] = fre->held_val;
-            JS_EnqueueJob(frd->ctx, js_finrec_job, 2, args);
+            JS_EnqueueJob(frd->realm, js_finrec_job, 2, args);
                 
             js_weakref_free(rt, fre->target);
             js_weakref_free(rt, fre->token);
@@ -55740,7 +55910,7 @@ static JSValue js_finrec_constructor(JSContext *ctx, 
JSValueConst new_target,
     frd->weakref_header.weakref_type = JS_WEAKREF_TYPE_FINREC;
     list_add_tail(&frd->weakref_header.link, &ctx->rt->weakref_list);
     init_list_head(&frd->entries);
-    frd->ctx = ctx; /* XXX: JS_DupContext() ? */
+    frd->realm = JS_DupContext(ctx);
     frd->cb = JS_DupValue(ctx, cb);
     JS_SetOpaque(obj, frd);
     return obj;
diff --git a/src/couch_quickjs/quickjs/run-test262.c 
b/src/couch_quickjs/quickjs/run-test262.c
index 03b37c6e1..ef16025ae 100644
--- a/src/couch_quickjs/quickjs/run-test262.c
+++ b/src/couch_quickjs/quickjs/run-test262.c
@@ -496,8 +496,7 @@ static void *agent_start(void *arg)
     JS_FreeValue(ctx, ret_val);
 
     for(;;) {
-        JSContext *ctx1;
-        ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
+        ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL);
         if (ret < 0) {
             js_std_dump_error(ctx);
             break;
@@ -1270,8 +1269,7 @@ static int eval_buf(JSContext *ctx, const char *buf, 
size_t buf_len,
             JS_FreeValue(ctx, res_val);
         }
         for(;;) {
-            JSContext *ctx1;
-            ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
+            ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL);
             if (ret < 0) {
                 res_val = JS_EXCEPTION;
                 break;
@@ -1938,10 +1936,9 @@ int run_test262_harness_test(const char *filename, BOOL 
is_module)
             JS_FreeValue(ctx, res_val);
         }
         for(;;) {
-            JSContext *ctx1;
-            ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
+            ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), NULL);
             if (ret < 0) {
-                js_std_dump_error(ctx1);
+                js_std_dump_error(ctx);
                 ret_code = 1;
             } else if (ret == 0) {
                 break;
diff --git a/src/couch_quickjs/quickjs/test262.conf 
b/src/couch_quickjs/quickjs/test262.conf
index 327759454..c099f2fe6 100644
--- a/src/couch_quickjs/quickjs/test262.conf
+++ b/src/couch_quickjs/quickjs/test262.conf
@@ -337,6 +337,8 @@ test262/test/staging/sm/RegExp/source.js
 test262/test/staging/sm/RegExp/escape.js
 # source directives are not standard yet
 test262/test/staging/sm/syntax/syntax-parsed-arrow-then-directive.js
+# returning "bound fn" as initialName for a function is permitted by the spec
+test262/test/staging/sm/Function/function-toString-builtin.js
 
 [tests]
 # list test files or use config.testdir
diff --git a/src/couch_quickjs/quickjs/test262_errors.txt 
b/src/couch_quickjs/quickjs/test262_errors.txt
index a252d6ec3..c565fa242 100644
--- a/src/couch_quickjs/quickjs/test262_errors.txt
+++ b/src/couch_quickjs/quickjs/test262_errors.txt
@@ -1,6 +1,12 @@
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js:27:
 SyntaxError: invalid for in/of left hand-side
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js:27:
 SyntaxError: invalid for in/of left hand-side
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js:33:
 SyntaxError: invalid assignment left-hand side
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js:27:
 SyntaxError: invalid increment/decrement operand
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27:
 SyntaxError: invalid increment/decrement operand
+test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33:
 SyntaxError: invalid assignment left-hand side
+test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20:
 SyntaxError: invalid assignment left-hand side
 
test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34:
 TypeError: ArrayBuffer is detached
 
test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34:
 strict mode: TypeError: ArrayBuffer is detached
-test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10:
 TypeError: $DONE() not called
 test262/test/language/statements/expression/S12.4_A1.js:15: unexpected error 
type: Test262: This statement should not be evaluated.
 test262/test/language/statements/expression/S12.4_A1.js:15: strict mode: 
unexpected error type: Test262: This statement should not be evaluated.
 test262/test/staging/sm/Date/UTC-convert-all-arguments.js:75: Test262Error: 
index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't 
throw», «42») to be true
@@ -11,15 +17,15 @@ 
test262/test/staging/sm/Function/arguments-parameter-shadowing.js:15: Test262Err
 test262/test/staging/sm/Function/constructor-binding.js:12: Test262Error: 
Expected SameValue(«"function"», «"undefined"») to be true
 test262/test/staging/sm/Function/function-bind.js:14: Test262Error: Conforms 
to NativeFunction Syntax: "function bound unbound() {\n    [native code]\n}"
 test262/test/staging/sm/Function/function-name-for.js:12: Test262Error: 
Expected SameValue(«""», «"forInHead"») to be true
-test262/test/staging/sm/Function/function-toString-builtin.js:14: 
Test262Error: Expected match to 
'/^\s*function\s*(get|set)?\s*(\w+|(?:'[^']*')|(?:"[^"]*")|\d+|(?:\[[^\]]+\]))?\s*\(\s*\)\s*\{\s*\[native
 code\]\s*\}\s*$/', Actual value 'function bound fn() {
-    [native code]
-}' Expected SameValue(«null», «null») to be false
 test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:13: 
Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
 test262/test/staging/sm/Function/invalid-parameter-list.js:35: Error: 
Assertion failed: expected exception SyntaxError, no exception thrown
 test262/test/staging/sm/RegExp/constructor-ordering-2.js:15: Test262Error: 
Expected SameValue(«false», «true») to be true
-test262/test/staging/sm/RegExp/regress-613820-1.js:13: Test262Error: Expected 
SameValue(«"aaa"», «"aa"») to be true
-test262/test/staging/sm/RegExp/regress-613820-2.js:13: Test262Error: Expected 
SameValue(«"f"», «undefined») to be true
-test262/test/staging/sm/RegExp/regress-613820-3.js:13: Test262Error: Expected 
SameValue(«"aab"», «"aa"») to be true
+test262/test/staging/sm/RegExp/regress-613820-1.js:12: Test262Error: Actual 
[aaa, aa, a] and expected [aa, a, a] should have the same contents. 
+test262/test/staging/sm/RegExp/regress-613820-1.js:12: strict mode: 
Test262Error: Actual [aaa, aa, a] and expected [aa, a, a] should have the same 
contents. 
+test262/test/staging/sm/RegExp/regress-613820-2.js:12: Test262Error: Actual 
[foobar, f, o, o, b, a, r] and expected [foobar, undefined, undefined, 
undefined, b, a, r] should have the same contents. 
+test262/test/staging/sm/RegExp/regress-613820-2.js:12: strict mode: 
Test262Error: Actual [foobar, f, o, o, b, a, r] and expected [foobar, 
undefined, undefined, undefined, b, a, r] should have the same contents. 
+test262/test/staging/sm/RegExp/regress-613820-3.js:12: Test262Error: Actual 
[aab, a, undefined, ab] and expected [aa, undefined, a, undefined] should have 
the same contents. 
+test262/test/staging/sm/RegExp/regress-613820-3.js:12: strict mode: 
Test262Error: Actual [aab, a, undefined, ab] and expected [aa, undefined, a, 
undefined] should have the same contents. 
 test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:73: Error: 
Assertion failed: expected exception ExpectedError, got Error: Poisoned Value
 test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: 
Test262Error: Expected SameValue(«2», «6») to be true
 test262/test/staging/sm/TypedArray/set-detached-bigint.js:27: Error: Assertion 
failed: expected exception SyntaxError, got RangeError: invalid array length
diff --git a/src/couch_quickjs/quickjs/tests/test262.patch 
b/src/couch_quickjs/quickjs/tests/test262.patch
index c8885e658..e488df829 100644
--- a/src/couch_quickjs/quickjs/tests/test262.patch
+++ b/src/couch_quickjs/quickjs/tests/test262.patch
@@ -71,10 +71,10 @@ index b397be0..c197ddc 100644
    return result;
  }
 diff --git a/harness/sm/non262.js b/harness/sm/non262.js
-index c1829e3..3a3ee27 100644
+index 89df923..79ded15 100644
 --- a/harness/sm/non262.js
 +++ b/harness/sm/non262.js
-@@ -41,8 +41,6 @@ globalThis.createNewGlobal = function() {
+@@ -34,8 +34,6 @@ globalThis.createNewGlobal = function() {
    return $262.createRealm().global
  }
  
@@ -83,15 +83,8 @@ index c1829e3..3a3ee27 100644
  function assertEq(...args) {
    assert.sameValue(...args)
  }
-@@ -71,4 +69,4 @@ if (globalThis.createExternalArrayBuffer === undefined) {
- if (globalThis.enableGeckoProfilingWithSlowAssertions === undefined) {
-   globalThis.enableGeckoProfilingWithSlowAssertions = 
globalThis.enableGeckoProfiling =
-     globalThis.disableGeckoProfiling = () => {}
--}
-\ No newline at end of file
-+}
 diff --git a/test/staging/sm/extensions/regress-469625-01.js 
b/test/staging/sm/extensions/regress-469625-01.js
-index 5b62aeb..da07aae 100644
+index 81f84fc..4652002 100644
 --- a/test/staging/sm/extensions/regress-469625-01.js
 +++ b/test/staging/sm/extensions/regress-469625-01.js
 @@ -14,8 +14,7 @@ esid: pending
@@ -104,17 +97,17 @@ index 5b62aeb..da07aae 100644
  
  
  
//-----------------------------------------------------------------------------
-@@ -27,9 +26,6 @@ function test()
-   printBugNumber(BUGNUMBER);
-   printStatus (summary);
-  
+@@ -24,9 +23,6 @@ test();
+ 
+ function test()
+ {
 -  expect = 'TypeError: [].__proto__ is not a function';
 -
 -
    Array.prototype.__proto__ = function () { return 3; };
  
    try
-@@ -38,8 +34,10 @@ function test()
+@@ -35,8 +31,10 @@ function test()
    }
    catch(ex)
    {

Reply via email to