]> git.kaiwu.me - quickjs.git/commitdiff
2020-04-12 release
authorbellard <6490144+bellard@users.noreply.github.com>
Sun, 6 Sep 2020 17:04:20 +0000 (19:04 +0200)
committerbellard <6490144+bellard@users.noreply.github.com>
Sun, 6 Sep 2020 17:04:20 +0000 (19:04 +0200)
14 files changed:
Changelog
TODO
VERSION
doc/quickjs.html
doc/quickjs.pdf
doc/quickjs.texi
libbf.c
quickjs-libc.c
quickjs.c
quickjs.h
run-test262.c
test262.conf
test262_errors.txt
tests/test_std.js

index 435b39fbe7cc9aee06f4a0bfa6c63f86ee3e4c83..0f447dbe50290a9ee67cfa585c73fe4812070d6e 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,10 @@
+2020-04-12:
+
+- added cross realm support
+- added AggregateError and Promise.any
+- added env, uid and gid options in os.exec()
+- misc bug fixes
+
 2020-03-16:
 
 - reworked error handling in std and os libraries: suppressed I/O
diff --git a/TODO b/TODO
index 2f6133897c38562b66782ab289b2906dd36000bb..8cfe0bebba2531cb03323b7f5dc7607850d39fe4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -73,6 +73,6 @@ REPL:
 Test262o:   0/11262 errors, 463 excluded
 Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
 
-Test262:   22/70040 errors, 860 excluded, 581 skipped
-test262 commit: 25c9e334d301944537215caba1d7f44319f3e0da
+Test262: 28/70829 errors, 877 excluded, 425 skipped
+Test262 commit: 4a8e49b3ca7f9f74a4cafe6621ff9ba548ccc353
 
diff --git a/VERSION b/VERSION
index 81b7bb9c01c2180fd1b6cbbb6a35ae79fa8b7819..69f162a403d2335d5632e66858c543c3d3f2e2cb 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2020-03-16
+2020-04-12
index b5c9287ce3ca8aea4f7d252829f8bf456cf7cbd9..550d2a687aa8cf083b57aaf9939760dafab756d6 100644 (file)
@@ -72,7 +72,7 @@ ul.no-bullet {list-style: none}
 <ul class="no-bullet">
   <li><a name="toc-Language-support" href="#Language-support">3.1 Language support</a>
   <ul class="no-bullet">
-    <li><a name="toc-ES2019-support" href="#ES2019-support">3.1.1 ES2019 support</a></li>
+    <li><a name="toc-ES2020-support" href="#ES2020-support">3.1.1 ES2020 support</a></li>
     <li><a name="toc-JSON" href="#JSON">3.1.2 JSON</a></li>
     <li><a name="toc-ECMA402" href="#ECMA402">3.1.3 ECMA402</a></li>
     <li><a name="toc-Extensions" href="#Extensions">3.1.4 Extensions</a></li>
@@ -130,7 +130,7 @@ ul.no-bullet {list-style: none}
 <h2 class="chapter">1 Introduction</h2>
 
 <p>QuickJS is a small and embeddable Javascript engine. It supports the
-upcoming ES2020 specification
+ES2020 specification
 <a name="DOCF1" href="#FOOT1"><sup>1</sup></a>
 including modules, asynchronous generators, proxies and BigInt.
 </p>
@@ -146,12 +146,12 @@ and operator overloading.
 
 </li><li> Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite<a name="DOCF2" href="#FOOT2"><sup>2</sup></a> in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
 
-</li><li> Almost complete ES2019 support including modules, asynchronous
+</li><li> Almost complete ES2020 support including modules, asynchronous
 generators and full Annex B support (legacy web compatibility). Many
-features from the upcoming ES2020 specification
+features from the upcoming ES2021 specification
 <a name="DOCF3" href="#FOOT3"><sup>3</sup></a> are also supported.
 
-</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
+</li><li> Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
 
 </li><li> Compile Javascript sources to executables with no external dependency.
 
@@ -394,18 +394,16 @@ about 100 seconds).
 <a name="Language-support"></a>
 <h3 class="section">3.1 Language support</h3>
 
-<a name="ES2019-support"></a>
-<h4 class="subsection">3.1.1 ES2019 support</h4>
+<a name="ES2020-support"></a>
+<h4 class="subsection">3.1.1 ES2020 support</h4>
 
-<p>The ES2019 specification is almost fully supported including the Annex
+<p>The ES2020 specification is almost fully supported including the Annex
 B (legacy web compatibility) and the Unicode related features.
 </p>
 <p>The following features are not supported yet:
 </p>
 <ul>
-<li> Realms (although the C API supports different runtimes and contexts)
-
-</li><li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
+<li> Tail calls<a name="DOCF6" href="#FOOT6"><sup>6</sup></a>
 
 </li></ul>
 
@@ -916,7 +914,21 @@ object containing optional parameters:
 <dt><code>stdout</code></dt>
 <dt><code>stderr</code></dt>
 <dd><p>If present, set the handle in the child for stdin, stdout or stderr.
-</p> 
+</p>
+</dd>
+<dt><code>env</code></dt>
+<dd><p>Object. If present, set the process environment from the object
+  key-value pairs. Otherwise use the same environment as the current
+  process.
+</p>
+</dd>
+<dt><code>uid</code></dt>
+<dd><p>Integer. If present, the process uid with <code>setuid</code>.
+</p>
+</dd>
+<dt><code>gid</code></dt>
+<dd><p>Integer. If present, the process gid with <code>setgid</code>.
+</p>
 </dd>
 </dl>
 
@@ -1266,7 +1278,7 @@ Bellard and Charlie Gordon.
 <h4 class="footnotes-heading">Footnotes</h4>
 
 <h3><a name="FOOT1" href="#DOCF1">(1)</a></h3>
-<p><a href="https://www.ecma-international.org/ecma-262/10.0">https://www.ecma-international.org/ecma-262/10.0</a></p>
+<p><a href="https://tc39.es/ecma262/">https://tc39.es/ecma262/</a></p>
 <h3><a name="FOOT2" href="#DOCF2">(2)</a></h3>
 <p><a href="https://github.com/tc39/test262">https://github.com/tc39/test262</a></p>
 <h3><a name="FOOT3" href="#DOCF3">(3)</a></h3>
index c0e4f4f1c9abc16de8dea66c188155d925a27c15..1cba4744cc40587e2c4b8c23b9aea02607095aa3 100644 (file)
Binary files a/doc/quickjs.pdf and b/doc/quickjs.pdf differ
index 10152bce20dc39ea088c8459b0204c33049d2b96..04156afb60599b2d7373ccd87c88c26719567c4b 100644 (file)
@@ -20,8 +20,8 @@
 @chapter Introduction
 
 QuickJS is a small and embeddable Javascript engine. It supports the
-upcoming ES2020 specification
-@footnote{@url{https://www.ecma-international.org/ecma-262/10.0}}
+ES2020 specification
+@footnote{@url{https://tc39.es/ecma262/}}
 including modules, asynchronous generators, proxies and BigInt.
 
 It supports mathematical extensions such as big decimal float float
@@ -36,12 +36,12 @@ and operator overloading.
 
 @item Fast interpreter with very low startup time: runs the 69000 tests of the ECMAScript Test Suite@footnote{@url{https://github.com/tc39/test262}} in about 95 seconds on a single core of a desktop PC. The complete life cycle of a runtime instance completes in less than 300 microseconds.
 
-@item Almost complete ES2019 support including modules, asynchronous
+@item Almost complete ES2020 support including modules, asynchronous
 generators and full Annex B support (legacy web compatibility). Many
-features from the upcoming ES2020 specification
+features from the upcoming ES2021 specification
 @footnote{@url{https://tc39.github.io/ecma262/}} are also supported.
 
-@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2019 features.
+@item Passes nearly 100% of the ECMAScript Test Suite tests when selecting the ES2020 features.
 
 @item Compile Javascript sources to executables with no external dependency.
 
@@ -259,17 +259,15 @@ about 100 seconds).
 
 @section Language support
 
-@subsection ES2019 support
+@subsection ES2020 support
 
-The ES2019 specification is almost fully supported including the Annex
+The ES2020 specification is almost fully supported including the Annex
 B (legacy web compatibility) and the Unicode related features.
 
 The following features are not supported yet:
 
 @itemize
 
-@item Realms (although the C API supports different runtimes and contexts)
-
 @item Tail calls@footnote{We believe the current specification of tails calls is too complicated and presents limited practical interests.}
 
 @end itemize
@@ -704,7 +702,18 @@ object containing optional parameters:
   @item stdout
   @item stderr
   If present, set the handle in the child for stdin, stdout or stderr.
+
+  @item env
+  Object. If present, set the process environment from the object
+  key-value pairs. Otherwise use the same environment as the current
+  process.
+
+  @item uid
+  Integer. If present, the process uid with @code{setuid}.
+
+  @item gid 
+  Integer. If present, the process gid with @code{setgid}.
+
   @end table
 
 @item waitpid(pid, options)
diff --git a/libbf.c b/libbf.c
index 14aff8f7fd0cd961a77b29affe8152d4eeb9be22..2ef51042dae320cd33ea6e8d881d0dc7ce7f1b10 100644 (file)
--- a/libbf.c
+++ b/libbf.c
@@ -1701,10 +1701,12 @@ static int __bf_div(bf_t *r, const bf_t *a, const bf_t *b, limb_t prec,
         memset(taba, 0, d * sizeof(limb_t));
         memcpy(taba + d, a->tab, a->len * sizeof(limb_t));
         if (bf_resize(r, n + 1))
+            goto fail1;
+        if (mp_divnorm(s, r->tab, taba, na, b->tab, nb)) {
+        fail1:
+            bf_free(s, taba);
             goto fail;
-        if (mp_divnorm(s, r->tab, taba, na, b->tab, nb))
-            goto fail;
-        
+        }
         /* see if non zero remainder */
         if (mp_scan_nz(taba, nb))
             r->tab[0] |= 1;
index 3ff5168a79223c0e6b63be200097f498293af6bc..4e6d221525781b434a300fa001ccf724eb495e35 100644 (file)
@@ -239,6 +239,7 @@ static JSValue js_printf_internal(JSContext *ctx,
                 case 's':
                     if (i >= argc)
                         goto missing;
+                    /* XXX: handle strings containing null characters */
                     string_arg = JS_ToCString(ctx, argv[i++]);
                     if (!string_arg)
                         goto fail;
@@ -843,6 +844,7 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val,
     FILE *f;
     int i;
     const char *str;
+    size_t len;
 
     if (magic == 0) {
         f = stdout;
@@ -853,10 +855,10 @@ static JSValue js_std_file_puts(JSContext *ctx, JSValueConst this_val,
     }
     
     for(i = 0; i < argc; i++) {
-        str = JS_ToCString(ctx, argv[i]);
+        str = JS_ToCStringLen(ctx, &len, argv[i]);
         if (!str)
             return JS_EXCEPTION;
-        fputs(str, f);
+        fwrite(str, 1, len, f);
         JS_FreeCString(ctx, str);
     }
     return JS_UNDEFINED;
@@ -2325,6 +2327,121 @@ static JSValue js_os_utimes(JSContext *ctx, JSValueConst this_val,
     return JS_NewInt32(ctx, ret);
 }
 
+static char **build_envp(JSContext *ctx, JSValueConst obj)
+{
+    uint32_t len, i;
+    JSPropertyEnum *tab;
+    char **envp, *pair;
+    const char *key, *str;
+    JSValue val;
+    size_t key_len, str_len;
+    
+    if (JS_GetOwnPropertyNames(ctx, &tab, &len, obj,
+                               JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0)
+        return NULL;
+    envp = js_mallocz(ctx, sizeof(envp[0]) * ((size_t)len + 1));
+    if (!envp)
+        goto fail;
+    for(i = 0; i < len; i++) {
+        val = JS_GetProperty(ctx, obj, tab[i].atom);
+        if (JS_IsException(val))
+            goto fail;
+        str = JS_ToCString(ctx, val);
+        JS_FreeValue(ctx, val);
+        if (!str)
+            goto fail;
+        key = JS_AtomToCString(ctx, tab[i].atom);
+        if (!key) {
+            JS_FreeCString(ctx, str);
+            goto fail;
+        }
+        key_len = strlen(key);
+        str_len = strlen(str);
+        pair = js_malloc(ctx, key_len + str_len + 2);
+        if (!pair) {
+            JS_FreeCString(ctx, key);
+            JS_FreeCString(ctx, str);
+            goto fail;
+        }
+        memcpy(pair, key, key_len);
+        pair[key_len] = '=';
+        memcpy(pair + key_len + 1, str, str_len);
+        pair[key_len + 1 + str_len] = '\0';
+        envp[i] = pair;
+        JS_FreeCString(ctx, key);
+        JS_FreeCString(ctx, str);
+    }
+ done:
+    for(i = 0; i < len; i++)
+        JS_FreeAtom(ctx, tab[i].atom);
+    js_free(ctx, tab);
+    return envp;
+ fail:
+    if (envp) {
+        for(i = 0; i < len; i++)
+            js_free(ctx, envp[i]);
+        js_free(ctx, envp);
+        envp = NULL;
+    }
+    goto done;
+}
+
+/* execvpe is not available on non GNU systems */
+static int my_execvpe(const char *filename, char **argv, char **envp)
+{
+    char *path, *p, *p_next, *p1;
+    char buf[PATH_MAX];
+    size_t filename_len, path_len;
+    BOOL eacces_error;
+    
+    filename_len = strlen(filename);
+    if (filename_len == 0) {
+        errno = ENOENT;
+        return -1;
+    }
+    if (strchr(filename, '/'))
+        return execve(filename, argv, envp);
+    
+    path = getenv("PATH");
+    if (!path)
+        path = "/bin:/usr/bin";
+    eacces_error = FALSE;
+    p = path;
+    for(p = path; p != NULL; p = p_next) {
+        p1 = strchr(p, ':');
+        if (!p1) {
+            p_next = NULL;
+            path_len = strlen(p);
+        } else {
+            p_next = p1 + 1;
+            path_len = p1 - p;
+        }
+        /* path too long */
+        if ((path_len + 1 + filename_len + 1) > PATH_MAX)
+            continue;
+        memcpy(buf, p, path_len);
+        buf[path_len] = '/';
+        memcpy(buf + path_len + 1, filename, filename_len);
+        buf[path_len + 1 + filename_len] = '\0';
+        
+        execve(buf, argv, envp);
+
+        switch(errno) {
+        case EACCES:
+            eacces_error = TRUE;
+            break;
+        case ENOENT:
+        case ENOTDIR:
+            break;
+        default:
+            return -1;
+        }
+    }
+    if (eacces_error)
+        errno = EACCES;
+    return -1;
+}
+
 /* exec(args[, options]) -> exitcode */
 static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
                           int argc, JSValueConst *argv)
@@ -2332,11 +2449,13 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
     JSValueConst options, args = argv[0];
     JSValue val, ret_val;
     const char **exec_argv, *file = NULL, *str, *cwd = NULL;
+    char **envp = environ;
     uint32_t exec_argc, i;
     int ret, pid, status;
     BOOL block_flag = TRUE, use_path = TRUE;
     static const char *std_name[3] = { "stdin", "stdout", "stderr" };
     int std_fds[3];
+    uint32_t uid = -1, gid = -1;
     
     val = JS_GetPropertyStr(ctx, args, "length");
     if (JS_IsException(val))
@@ -2410,6 +2529,36 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
                 std_fds[i] = fd;
             }
         }
+
+        val = JS_GetPropertyStr(ctx, options, "env");
+        if (JS_IsException(val))
+            goto exception;
+        if (!JS_IsUndefined(val)) {
+            envp = build_envp(ctx, val);
+            JS_FreeValue(ctx, val);
+            if (!envp)
+                goto exception;
+        }
+        
+        val = JS_GetPropertyStr(ctx, options, "uid");
+        if (JS_IsException(val))
+            goto exception;
+        if (!JS_IsUndefined(val)) {
+            ret = JS_ToUint32(ctx, &uid, val);
+            JS_FreeValue(ctx, val);
+            if (ret)
+                goto exception;
+        }
+
+        val = JS_GetPropertyStr(ctx, options, "gid");
+        if (JS_IsException(val))
+            goto exception;
+        if (!JS_IsUndefined(val)) {
+            ret = JS_ToUint32(ctx, &gid, val);
+            JS_FreeValue(ctx, val);
+            if (ret)
+                goto exception;
+        }
     }
 
     pid = fork();
@@ -2435,12 +2584,21 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
             if (chdir(cwd) < 0)
                 _exit(127);
         }
+        if (uid != -1) {
+            if (setuid(uid) < 0)
+                _exit(127);
+        }
+        if (gid != -1) {
+            if (setgid(gid) < 0)
+                _exit(127);
+        }
+
         if (!file)
             file = exec_argv[0];
         if (use_path)
-            ret = execvp(file, (char **)exec_argv);
+            ret = my_execvpe(file, (char **)exec_argv, envp);
         else
-            ret = execv(file, (char **)exec_argv);
+            ret = execve(file, (char **)exec_argv, envp);
         _exit(127);
     }
     /* parent */
@@ -2467,6 +2625,15 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val,
     for(i = 0; i < exec_argc; i++)
         JS_FreeCString(ctx, exec_argv[i]);
     js_free(ctx, exec_argv);
+    if (envp != environ) {
+        char **p;
+        p = envp;
+        while (*p != NULL) {
+            js_free(ctx, *p);
+            p++;
+        }
+        js_free(ctx, envp);
+    }
     return ret_val;
  exception:
     ret_val = JS_EXCEPTION;
@@ -2700,14 +2867,15 @@ static JSValue js_print(JSContext *ctx, JSValueConst this_val,
 {
     int i;
     const char *str;
+    size_t len;
 
     for(i = 0; i < argc; i++) {
         if (i != 0)
             putchar(' ');
-        str = JS_ToCString(ctx, argv[i]);
+        str = JS_ToCStringLen(ctx, &len, argv[i]);
         if (!str)
             return JS_EXCEPTION;
-        fputs(str, stdout);
+        fwrite(str, 1, len, stdout);
         JS_FreeCString(ctx, str);
     }
     putchar('\n');
index cabb82b084608a3bf963b38b999164f7c91c1a01..7da72531b1b0eff81cdb38715eadfb2c2ba90f90 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -187,7 +187,8 @@ typedef enum JSErrorEnum {
     JS_TYPE_ERROR,
     JS_URI_ERROR,
     JS_INTERNAL_ERROR,
-
+    JS_AGGREGATE_ERROR,
+    
     JS_NATIVE_ERROR_COUNT, /* number of different NativeError objects */
 } JSErrorEnum;
 
@@ -257,6 +258,15 @@ struct JSRuntime {
 #ifdef DUMP_LEAKS
     struct list_head string_list; /* list of JSString.link */
 #endif
+    /* stack limitation */
+    const uint8_t *stack_top;
+    size_t stack_size; /* in bytes */
+
+    JSValue current_exception;
+    /* true if inside an out of memory error, to avoid recursing */
+    BOOL in_out_of_memory : 8;
+
+    struct JSStackFrame *current_stack_frame;
 
     JSInterruptHandler *interrupt_handler;
     void *interrupt_opaque;
@@ -322,6 +332,7 @@ typedef enum {
     JS_GC_OBJ_TYPE_SHAPE,
     JS_GC_OBJ_TYPE_VAR_REF,
     JS_GC_OBJ_TYPE_ASYNC_FUNCTION,
+    JS_GC_OBJ_TYPE_JS_CONTEXT,
 } JSGCObjectTypeEnum;
 
 /* header for GC objects. GC objects are C data structures with a
@@ -378,29 +389,30 @@ typedef struct JSBigDecimal {
 } JSBigDecimal;
 #endif
 
+typedef enum {
+    JS_AUTOINIT_ID_PROTOTYPE,
+    JS_AUTOINIT_ID_MODULE_NS,
+    JS_AUTOINIT_ID_PROP, /* must be last */
+} JSAutoInitIDEnum;
+
 /* must be large enough to have a negligible runtime cost and small
    enough to call the interrupt callback often. */
 #define JS_INTERRUPT_COUNTER_INIT 10000
 
 struct JSContext {
+    JSGCObjectHeader header; /* must come first */
     JSRuntime *rt;
     struct list_head link;
-    const uint8_t *stack_top;
-    size_t stack_size; /* in bytes */
 
-    JSValue current_exception;
-    /* true if inside an out of memory error, to avoid recursing */
-    BOOL in_out_of_memory : 8;
     uint16_t binary_object_count;
     int binary_object_size;
 
     JSShape *array_shape;   /* initial shape for Array objects */
 
-    JSStackFrame *current_stack_frame;
-
     JSValue *class_proto;
     JSValue function_proto;
     JSValue function_ctor;
+    JSValue array_ctor;
     JSValue regexp_ctor;
     JSValue promise_ctor;
     JSValue native_error_proto[JS_NATIVE_ERROR_COUNT];
@@ -570,6 +582,7 @@ typedef struct JSFunctionBytecode {
     uint16_t var_count;
     uint16_t defined_arg_count; /* for length function property */
     uint16_t stack_size; /* maximum stack size */
+    JSContext *realm; /* function realm */
     JSValue *cpool; /* constant pool (self pointer) */
     int cpool_count;
     int closure_var_count;
@@ -784,8 +797,12 @@ typedef struct JSProperty {
         } getset;
         JSVarRef *var_ref;  /* JS_PROP_VARREF */
         struct {            /* JS_PROP_AUTOINIT */
-            int (*init_func)(JSContext *ctx, JSObject *obj,
-                             JSAtom prop, void *opaque);
+            /* in order to use only 2 pointers, we compress the realm
+               and the init function pointer */
+            union {
+                JSContext *realm; /* for JS_AUTOINIT_ID_PROP */
+                uintptr_t init_id; /* JS_AUTOINIT_ID_x */
+            } u;
             void *opaque;
         } init;
     } u;
@@ -872,7 +889,8 @@ struct JSObject {
             JSVarRef **var_refs;
             JSObject *home_object; /* for 'super' access */
         } func;
-        struct { /* JS_CLASS_C_FUNCTION: 8/12 bytes */
+        struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */
+            JSContext *realm;
             JSCFunctionType c_function;
             uint8_t length;
             uint8_t cproto;
@@ -999,6 +1017,9 @@ static void js_array_mark(JSRuntime *rt, JSValueConst val,
 static void js_object_data_finalizer(JSRuntime *rt, JSValue val);
 static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
                                 JS_MarkFunc *mark_func);
+static void js_c_function_finalizer(JSRuntime *rt, JSValue val);
+static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
+                               JS_MarkFunc *mark_func);
 static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val);
 static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val,
                                 JS_MarkFunc *mark_func);
@@ -1131,6 +1152,8 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
                                const char *input, size_t input_len,
                                const char *filename, int flags, int scope_idx);
 static void js_free_module_def(JSContext *ctx, JSModuleDef *m);
+static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
+                               JS_MarkFunc *mark_func);
 static JSValue js_import_meta(JSContext *ctx);
 static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier);
 static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
@@ -1184,6 +1207,11 @@ static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h,
                           JSGCObjectTypeEnum type);
 static void remove_gc_object(JSGCObjectHeader *h);
 static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s);
+static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, void *opaque);
+static int js_module_ns_autoinit(JSContext *ctx, JSObject *p, JSAtom atom,
+                                 void *opaque);
+static int JS_InstantiateFunctionListItem(JSContext *ctx, JSObject *p,
+                                          JSAtom atom, void *opaque);
 
 static const JSClassExoticMethods js_arguments_exotic_methods;
 static const JSClassExoticMethods js_string_exotic_methods;
@@ -1351,7 +1379,7 @@ typedef struct JSClassShortDef {
 static JSClassShortDef const js_std_class_def[] = {
     { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_OBJECT */
     { JS_ATOM_Array, js_array_finalizer, js_array_mark },       /* JS_CLASS_ARRAY */
-    { JS_ATOM_Error, NULL, NULL },                              /* JS_CLASS_ERROR */
+    { JS_ATOM_Error, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_ERROR */
     { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */
     { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */
     { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */
@@ -1360,7 +1388,7 @@ static JSClassShortDef const js_std_class_def[] = {
     { JS_ATOM_Arguments, NULL, NULL },                          /* JS_CLASS_MAPPED_ARGUMENTS */
     { JS_ATOM_Date, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_DATE */
     { JS_ATOM_Object, NULL, NULL },                             /* JS_CLASS_MODULE_NS */
-    { JS_ATOM_Function, NULL, NULL },                           /* JS_CLASS_C_FUNCTION */
+    { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */
     { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */
     { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */
     { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */
@@ -1477,6 +1505,32 @@ static void set_dummy_numeric_ops(JSNumericOperations *ops)
 
 #endif /* CONFIG_BIGNUM */
 
+#if defined(EMSCRIPTEN)
+/* currently no stack limitation */
+static inline uint8_t *js_get_stack_pointer(void)
+{
+    return NULL;
+}
+
+static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
+{
+    return FALSE;
+}
+#else
+/* Note: OS and CPU dependent */
+static inline uint8_t *js_get_stack_pointer(void)
+{
+    return __builtin_frame_address(0);
+}
+
+static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size)
+{
+    size_t size;
+    size = rt->stack_top - js_get_stack_pointer();
+    return unlikely((size + alloca_size) > rt->stack_size);
+}
+#endif
+
 JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
 {
     JSRuntime *rt;
@@ -1532,6 +1586,11 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
     rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_generator_function_call;
     if (init_shape_hash(rt))
         goto fail;
+
+    rt->stack_top = js_get_stack_pointer();
+    rt->stack_size = JS_DEFAULT_STACK_SIZE;
+    rt->current_exception = JS_NULL;
+
     return rt;
  fail:
     JS_FreeRuntime(rt);
@@ -1798,10 +1857,7 @@ void JS_FreeRuntime(JSRuntime *rt)
     struct list_head *el, *el1;
     int i;
 
-    list_for_each_safe(el, el1, &rt->context_list) {
-        JSContext *ctx = list_entry(el, JSContext, link);
-        JS_FreeContext(ctx);
-    }
+    JS_FreeValueRT(rt, rt->current_exception);
 
     list_for_each_safe(el, el1, &rt->job_list) {
         JSJobEntry *e = list_entry(el, JSJobEntry, link);
@@ -1984,32 +2040,6 @@ void JS_FreeRuntime(JSRuntime *rt)
     }
 }
 
-#if defined(EMSCRIPTEN)
-/* currently no stack limitation */
-static inline uint8_t *js_get_stack_pointer(void)
-{
-    return NULL;
-}
-
-static inline BOOL js_check_stack_overflow(JSContext *ctx, size_t alloca_size)
-{
-    return FALSE;
-}
-#else
-/* Note: OS and CPU dependent */
-static inline uint8_t *js_get_stack_pointer(void)
-{
-    return __builtin_frame_address(0);
-}
-
-static inline BOOL js_check_stack_overflow(JSContext *ctx, size_t alloca_size)
-{
-    size_t size;
-    size = ctx->stack_top - js_get_stack_pointer();
-    return unlikely((size + alloca_size) > ctx->stack_size);
-}
-#endif
-
 JSContext *JS_NewContextRaw(JSRuntime *rt)
 {
     JSContext *ctx;
@@ -2018,6 +2048,9 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
     ctx = js_mallocz_rt(rt, sizeof(JSContext));
     if (!ctx)
         return NULL;
+    ctx->header.ref_count = 1;
+    add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT);
+
     ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) *
                                     rt->class_count);
     if (!ctx->class_proto) {
@@ -2026,9 +2059,6 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
     }
     ctx->rt = rt;
     list_add_tail(&ctx->link, &rt->context_list);
-    ctx->stack_top = js_get_stack_pointer();
-    ctx->stack_size = JS_DEFAULT_STACK_SIZE;
-    ctx->current_exception = JS_NULL;
 #ifdef CONFIG_BIGNUM
     ctx->bf_ctx = &rt->bf_ctx;
     ctx->fp_env.prec = 113;
@@ -2036,6 +2066,7 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
 #endif
     for(i = 0; i < rt->class_count; i++)
         ctx->class_proto[i] = JS_NULL;
+    ctx->array_ctor = JS_NULL;
     ctx->regexp_ctor = JS_NULL;
     ctx->promise_ctor = JS_NULL;
     init_list_head(&ctx->loaded_modules);
@@ -2122,11 +2153,60 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
     }
 }
 
+JSContext *JS_DupContext(JSContext *ctx)
+{
+    ctx->header.ref_count++;
+    return ctx;
+}
+
+/* used by the GC */
+static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,
+                           JS_MarkFunc *mark_func)
+{
+    int i;
+    struct list_head *el;
+
+    /* modules are not seen by the GC, so we directly mark the objects
+       referenced by each module */
+    list_for_each(el, &ctx->loaded_modules) {
+        JSModuleDef *m = list_entry(el, JSModuleDef, link);
+        js_mark_module_def(rt, m, mark_func);
+    }
+
+    JS_MarkValue(rt, ctx->global_obj, mark_func);
+    JS_MarkValue(rt, ctx->global_var_obj, mark_func);
+
+    JS_MarkValue(rt, ctx->throw_type_error, mark_func);
+    JS_MarkValue(rt, ctx->eval_obj, mark_func);
+
+    JS_MarkValue(rt, ctx->array_proto_values, mark_func);
+    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
+        JS_MarkValue(rt, ctx->native_error_proto[i], mark_func);
+    }
+    for(i = 0; i < rt->class_count; i++) {
+        JS_MarkValue(rt, ctx->class_proto[i], mark_func);
+    }
+    JS_MarkValue(rt, ctx->iterator_proto, mark_func);
+    JS_MarkValue(rt, ctx->async_iterator_proto, mark_func);
+    JS_MarkValue(rt, ctx->promise_ctor, mark_func);
+    JS_MarkValue(rt, ctx->array_ctor, mark_func);
+    JS_MarkValue(rt, ctx->regexp_ctor, mark_func);
+    JS_MarkValue(rt, ctx->function_ctor, mark_func);
+    JS_MarkValue(rt, ctx->function_proto, mark_func);
+
+    if (ctx->array_shape)
+        mark_func(rt, &ctx->array_shape->header);
+}
+
 void JS_FreeContext(JSContext *ctx)
 {
     JSRuntime *rt = ctx->rt;
     int i;
 
+    if (--ctx->header.ref_count > 0)
+        return;
+    assert(ctx->header.ref_count == 0);
+    
 #ifdef DUMP_ATOMS
     JS_DumpAtoms(ctx->rt);
 #endif
@@ -2156,8 +2236,6 @@ void JS_FreeContext(JSContext *ctx)
 
     js_free_modules(ctx, JS_FREE_MODULE_ALL);
 
-    JS_FreeValue(ctx, ctx->current_exception);
-
     JS_FreeValue(ctx, ctx->global_obj);
     JS_FreeValue(ctx, ctx->global_var_obj);
 
@@ -2175,6 +2253,7 @@ void JS_FreeContext(JSContext *ctx)
     JS_FreeValue(ctx, ctx->iterator_proto);
     JS_FreeValue(ctx, ctx->async_iterator_proto);
     JS_FreeValue(ctx, ctx->promise_ctor);
+    JS_FreeValue(ctx, ctx->array_ctor);
     JS_FreeValue(ctx, ctx->regexp_ctor);
     JS_FreeValue(ctx, ctx->function_ctor);
     JS_FreeValue(ctx, ctx->function_proto);
@@ -2182,6 +2261,7 @@ void JS_FreeContext(JSContext *ctx)
     js_free_shape_null(ctx->rt, ctx->array_shape);
 
     list_del(&ctx->link);
+    remove_gc_object(&ctx->header);
     js_free_rt(ctx->rt, ctx);
 }
 
@@ -2190,21 +2270,21 @@ JSRuntime *JS_GetRuntime(JSContext *ctx)
     return ctx->rt;
 }
 
-void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size)
+void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size)
 {
-    ctx->stack_size = stack_size;
+    rt->stack_size = stack_size;
 }
 
 static inline BOOL is_strict_mode(JSContext *ctx)
 {
-    JSStackFrame *sf = ctx->current_stack_frame;
+    JSStackFrame *sf = ctx->rt->current_stack_frame;
     return (sf && (sf->js_mode & JS_MODE_STRICT));
 }
 
 #ifdef CONFIG_BIGNUM
 static inline BOOL is_math_mode(JSContext *ctx)
 {
-    JSStackFrame *sf = ctx->current_stack_frame;
+    JSStackFrame *sf = ctx->rt->current_stack_frame;
     return (sf && (sf->js_mode & JS_MODE_MATH));
 }
 #endif
@@ -4541,6 +4621,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas
         p->u.array.u.ptr = NULL;
         p->u.array.count = 0;
         break;
+    case JS_CLASS_ERROR:
     case JS_CLASS_NUMBER:
     case JS_CLASS_STRING:
     case JS_CLASS_BOOLEAN:
@@ -4775,6 +4856,7 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
     if (JS_IsException(func_obj))
         return func_obj;
     p = JS_VALUE_GET_OBJ(func_obj);
+    p->u.cfunc.realm = JS_DupContext(ctx);
     p->u.cfunc.c_function.generic = func;
     p->u.cfunc.length = length;
     p->u.cfunc.cproto = cproto;
@@ -4885,6 +4967,21 @@ JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
     return func_obj;
 }
 
+static void js_autoinit_free(JSRuntime *rt, JSProperty *pr)
+{
+    if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {
+        JS_FreeContext(pr->u.init.u.realm);
+    }
+}
+
+static void js_autoinit_mark(JSRuntime *rt, JSProperty *pr,
+                             JS_MarkFunc *mark_func)
+{
+    if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {
+        mark_func(rt, &pr->u.init.u.realm->header);
+    }
+}
+
 static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
 {
     if (unlikely(prop_flags & JS_PROP_TMASK)) {
@@ -4896,7 +4993,7 @@ static void free_property(JSRuntime *rt, JSProperty *pr, int prop_flags)
         } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
             free_var_ref(rt, pr->u.var_ref);
         } else if ((prop_flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-            /* nothing to do */
+            js_autoinit_free(rt, pr);
         }
     } else {
         JS_FreeValueRT(rt, pr->u.value);
@@ -5004,6 +5101,23 @@ static void js_object_data_mark(JSRuntime *rt, JSValueConst val,
     JS_MarkValue(rt, p->u.object_data, mark_func);
 }
 
+static void js_c_function_finalizer(JSRuntime *rt, JSValue val)
+{
+    JSObject *p = JS_VALUE_GET_OBJ(val);
+
+    if (p->u.cfunc.realm)
+        JS_FreeContext(p->u.cfunc.realm);
+}
+
+static void js_c_function_mark(JSRuntime *rt, JSValueConst val,
+                               JS_MarkFunc *mark_func)
+{
+    JSObject *p = JS_VALUE_GET_OBJ(val);
+
+    if (p->u.cfunc.realm)
+        mark_func(rt, &p->u.cfunc.realm->header);
+}
+
 static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val)
 {
     JSObject *p1, *p = JS_VALUE_GET_OBJ(val);
@@ -5315,7 +5429,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
                                 mark_func(rt, &pr->u.var_ref->header);
                             }
                         } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-                            /* nothing to do */
+                            js_autoinit_mark(rt, pr, mark_func);
                         }
                     } else {
                         JS_MarkValue(rt, pr->u.value, mark_func);
@@ -5340,6 +5454,8 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
             for(i = 0; i < b->cpool_count; i++) {
                 JS_MarkValue(rt, b->cpool[i], mark_func);
             }
+            if (b->realm)
+                mark_func(rt, &b->realm->header);
         }
         break;
     case JS_GC_OBJ_TYPE_VAR_REF:
@@ -5367,45 +5483,17 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
             }
         }
         break;
+    case JS_GC_OBJ_TYPE_JS_CONTEXT:
+        {
+            JSContext *ctx = (JSContext *)gp;
+            JS_MarkContext(rt, ctx, mark_func);
+        }
+        break;
     default:
         abort();
     }
 }
 
-#if 0
-/* not useful until realms are supported */
-static void mark_context(JSRuntime *rt, JSContext *ctx)
-{
-    int i;
-    struct list_head *el;
-
-    list_for_each(el, &ctx->loaded_modules) {
-        JSModuleDef *m = list_entry(el, JSModuleDef, link);
-        JS_MarkValue(rt, m->module_ns);
-        JS_MarkValue(rt, m->func_obj);
-    }
-
-    JS_MarkValue(rt, ctx->current_exception);
-
-    for(i = 0; i < rt->class_count; i++)
-        JS_MarkValue(rt, ctx->class_proto[i]);
-    JS_MarkValue(rt, ctx->regexp_ctor);
-    JS_MarkValue(rt, ctx->function_ctor);
-    JS_MarkValue(rt, ctx->function_proto);
-    JS_MarkValue(rt, ctx->iterator_proto);
-    JS_MarkValue(rt, ctx->async_iterator_proto);
-    JS_MarkValue(rt, ctx->array_proto_values);
-
-    for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++)
-        JS_MarkValue(rt, ctx->native_error_proto[i]);
-
-    JS_MarkValue(rt, ctx->throw_type_error);
-    JS_MarkValue(rt, ctx->eval_obj);
-    JS_MarkValue(rt, ctx->global_obj);
-    JS_MarkValue(rt, ctx->global_var_obj);
-}
-#endif
-
 static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p)
 {
     assert(p->ref_count > 0);
@@ -6056,8 +6144,9 @@ JSValue JS_GetGlobalObject(JSContext *ctx)
 /* WARNING: obj is freed */
 JSValue JS_Throw(JSContext *ctx, JSValue obj)
 {
-    JS_FreeValue(ctx, ctx->current_exception);
-    ctx->current_exception = obj;
+    JSRuntime *rt = ctx->rt;
+    JS_FreeValue(ctx, rt->current_exception);
+    rt->current_exception = obj;
     return JS_EXCEPTION;
 }
 
@@ -6065,8 +6154,9 @@ JSValue JS_Throw(JSContext *ctx, JSValue obj)
 JSValue JS_GetException(JSContext *ctx)
 {
     JSValue val;
-    val = ctx->current_exception;
-    ctx->current_exception = JS_NULL;
+    JSRuntime *rt = ctx->rt;
+    val = rt->current_exception;
+    rt->current_exception = JS_NULL;
     return val;
 }
 
@@ -6224,7 +6314,7 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
         if (backtrace_flags & JS_BACKTRACE_FLAG_SINGLE_LEVEL)
             goto done;
     }
-    for(sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
+    for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
         if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {
             backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
             continue;
@@ -6266,7 +6356,10 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
     }
  done:
     dbuf_putc(&dbuf, '\0');
-    str = JS_NewString(ctx, (char *)dbuf.buf);
+    if (dbuf_error(&dbuf))
+        str = JS_NULL;
+    else
+        str = JS_NewString(ctx, (char *)dbuf.buf);
     dbuf_free(&dbuf);
     JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, str,
                            JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
@@ -6318,12 +6411,13 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
 static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum error_num,
                              const char *fmt, va_list ap)
 {
+    JSRuntime *rt = ctx->rt;
     JSStackFrame *sf;
     BOOL add_backtrace;
 
     /* the backtrace is added later if called from a bytecode function */
-    sf = ctx->current_stack_frame;
-    add_backtrace = !ctx->in_out_of_memory &&
+    sf = rt->current_stack_frame;
+    add_backtrace = !rt->in_out_of_memory &&
         (!sf || (JS_GetFunctionBytecode(sf->cur_func) == NULL));
     return JS_ThrowError2(ctx, error_num, fmt, ap, add_backtrace);
 }
@@ -6413,10 +6507,11 @@ JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext *c
 
 JSValue JS_ThrowOutOfMemory(JSContext *ctx)
 {
-    if (!ctx->in_out_of_memory) {
-        ctx->in_out_of_memory = TRUE;
+    JSRuntime *rt = ctx->rt;
+    if (!rt->in_out_of_memory) {
+        rt->in_out_of_memory = TRUE;
         JS_ThrowInternalError(ctx, "out of memory");
-        ctx->in_out_of_memory = FALSE;
+        rt->in_out_of_memory = FALSE;
     }
     return JS_EXCEPTION;
 }
@@ -6674,7 +6769,27 @@ int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj)
 
 static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop, JSProperty *pr)
 {
-    return (*pr->u.init.init_func)(ctx, p, prop, pr->u.init.opaque);
+    int ret;
+    JSContext *realm;
+
+    if (pr->u.init.u.init_id >= JS_AUTOINIT_ID_PROP) {
+        realm = pr->u.init.u.realm;
+        ret = JS_InstantiateFunctionListItem(realm, p, prop, pr->u.init.opaque);
+        if (ret)
+            return ret;
+    } else {
+        switch(pr->u.init.u.init_id) {
+        case JS_AUTOINIT_ID_PROTOTYPE:
+            ret = js_instantiate_prototype(ctx, p, prop, pr->u.init.opaque);
+            break;
+        case JS_AUTOINIT_ID_MODULE_NS:
+            ret = js_module_ns_autoinit(ctx, p, prop, pr->u.init.opaque);
+            break;
+        default:
+            abort();
+        }
+    }
+    return ret;
 }
 
 JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
@@ -7742,6 +7857,7 @@ static int call_setter(JSContext *ctx, JSObject *setter,
         if (JS_IsException(ret))
             return -1;
         JS_FreeValue(ctx, ret);
+        return TRUE;
     } else {
         JS_FreeValue(ctx, val);
         if ((flags & JS_PROP_THROW) ||
@@ -7749,9 +7865,8 @@ static int call_setter(JSContext *ctx, JSObject *setter,
             JS_ThrowTypeError(ctx, "no setter for property");
             return -1;
         }
-        /* XXX: should return FALSE? */
+        return FALSE;
     }
-    return TRUE;
 }
 
 /* set the array length and remove the array elements if necessary. */
@@ -8626,6 +8741,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
                         /* clear property and update */
                         if (js_shape_prepare_update(ctx, p, &prs))
                             return -1;
+                        js_autoinit_free(ctx->rt, pr);
                         prs->flags &= ~JS_PROP_TMASK;
                         pr->u.value = JS_UNDEFINED;
                         goto retry;
@@ -8680,6 +8796,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
                     /* clear property and update */
                     if (js_shape_prepare_update(ctx, p, &prs))
                         return -1;
+                    js_autoinit_free(ctx->rt, pr);
                     prs->flags &= ~JS_PROP_TMASK;
                     pr->u.value = JS_UNDEFINED;
                 } else {
@@ -8835,8 +8952,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
 }
 
 static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
-                                     JSAtom prop, int (*init_func)(JSContext *ctx, JSObject *obj,
-                                                                   JSAtom prop, void *opaque),
+                                     JSAtom prop, JSAutoInitIDEnum id,
                                      void *opaque, int flags)
 {
     JSObject *p;
@@ -8857,8 +8973,11 @@ static int JS_DefineAutoInitProperty(JSContext *ctx, JSValueConst this_obj,
     pr = add_property(ctx, p, prop, (flags & JS_PROP_C_W_E) | JS_PROP_AUTOINIT);
     if (unlikely(!pr))
         return -1;
-
-    pr->u.init.init_func = init_func;
+    if (id == JS_AUTOINIT_ID_PROP) {
+        pr->u.init.u.realm = JS_DupContext(ctx);
+    } else {
+        pr->u.init.u.init_id = id;
+    }
     pr->u.init.opaque = opaque;
     return TRUE;
 }
@@ -9334,7 +9453,7 @@ void JS_SetUncatchableError(JSContext *ctx, JSValueConst val, BOOL flag)
 
 void JS_ResetUncatchableError(JSContext *ctx)
 {
-    JS_SetUncatchableError(ctx, ctx->current_exception, FALSE);
+    JS_SetUncatchableError(ctx, ctx->rt->current_exception, FALSE);
 }
 
 void JS_SetOpaque(JSValue obj, void *opaque)
@@ -11276,7 +11395,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
                 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) {
                     printf("[varref %p]", (void *)pr->u.var_ref);
                 } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_AUTOINIT) {
-                    printf("[autoinit %p %p]", (void *)pr->u.init.init_func,
+                    printf("[autoinit %p %p]", (void *)pr->u.init.u.realm,
                            (void *)pr->u.init.opaque);
                 } else {
                     JS_DumpValueShort(rt, pr->u.value);
@@ -11327,6 +11446,9 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
         case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
             printf("[async_function]");
             break;
+        case JS_GC_OBJ_TYPE_JS_CONTEXT:
+            printf("[js_context]");
+            break;
         default:
             printf("[unknown %d]", p->gc_obj_type);
             break;
@@ -14500,7 +14622,7 @@ static JSValue js_build_mapped_arguments(JSContext *ctx, int argc,
                            JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
     /* callee returns this function in non strict mode */
     JS_DefinePropertyValue(ctx, val, JS_ATOM_callee,
-                           JS_DupValue(ctx, ctx->current_stack_frame->cur_func),
+                           JS_DupValue(ctx, ctx->rt->current_stack_frame->cur_func),
                            JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
     return val;
  fail:
@@ -14822,8 +14944,8 @@ static int JS_IteratorClose(JSContext *ctx, JSValueConst enum_obj,
     int res;
 
     if (is_exception_pending) {
-        ex_obj = ctx->current_exception;
-        ctx->current_exception = JS_NULL;
+        ex_obj = ctx->rt->current_exception;
+        ctx->rt->current_exception = JS_NULL;
         res = -1;
     } else {
         ex_obj = JS_UNDEFINED;
@@ -15139,7 +15261,7 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
 /* only valid inside C functions */
 static JSValueConst JS_GetActiveFunction(JSContext *ctx)
 {
-    return ctx->current_stack_frame->cur_func;
+    return ctx->rt->current_stack_frame->cur_func;
 }
 
 static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf,
@@ -15231,6 +15353,13 @@ static int js_instantiate_prototype(JSContext *ctx, JSObject *p, JSAtom atom, vo
     return 0;
 }
 
+static const uint16_t func_kind_to_class_id[] = {
+    [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION,
+    [JS_FUNC_GENERATOR] = JS_CLASS_GENERATOR_FUNCTION,
+    [JS_FUNC_ASYNC] = JS_CLASS_ASYNC_FUNCTION,
+    [JS_FUNC_ASYNC_GENERATOR] = JS_CLASS_ASYNC_GENERATOR_FUNCTION,
+};
+
 static JSValue js_closure(JSContext *ctx, JSValue bfunc,
                           JSVarRef **cur_var_refs,
                           JSStackFrame *sf)
@@ -15238,12 +15367,6 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
     JSFunctionBytecode *b;
     JSValue func_obj;
     JSAtom name_atom;
-    static const uint16_t func_kind_to_class_id[] = {
-        [JS_FUNC_NORMAL] = JS_CLASS_BYTECODE_FUNCTION,
-        [JS_FUNC_GENERATOR] = JS_CLASS_GENERATOR_FUNCTION,
-        [JS_FUNC_ASYNC] = JS_CLASS_ASYNC_FUNCTION,
-        [JS_FUNC_ASYNC_GENERATOR] = JS_CLASS_ASYNC_GENERATOR_FUNCTION,
-    };
 
     b = JS_VALUE_GET_PTR(bfunc);
     func_obj = JS_NewObjectClass(ctx, func_kind_to_class_id[b->func_kind]);
@@ -15282,7 +15405,7 @@ static JSValue js_closure(JSContext *ctx, JSValue bfunc,
            object is created on the fly when first accessed */
         JS_SetConstructorBit(ctx, func_obj, TRUE);
         JS_DefineAutoInitProperty(ctx, func_obj, JS_ATOM_prototype,
-                                  js_instantiate_prototype, NULL,
+                                  JS_AUTOINIT_ID_PROTOTYPE, NULL,
                                   JS_PROP_WRITABLE);
     }
     return func_obj;
@@ -15435,6 +15558,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
                                   JSValueConst this_obj,
                                   int argc, JSValueConst *argv, int flags)
 {
+    JSRuntime *rt = ctx->rt;
     JSCFunctionType func;
     JSObject *p;
     JSStackFrame sf_s, *sf = &sf_s, *prev_sf;
@@ -15448,12 +15572,14 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
     arg_count = p->u.cfunc.length;
 
     /* better to always check stack overflow */
-    if (js_check_stack_overflow(ctx, sizeof(arg_buf[0]) * arg_count))
+    if (js_check_stack_overflow(rt, sizeof(arg_buf[0]) * arg_count))
         return JS_ThrowStackOverflow(ctx);
 
-    prev_sf = ctx->current_stack_frame;
+    prev_sf = rt->current_stack_frame;
     sf->prev_frame = prev_sf;
-    ctx->current_stack_frame = sf;
+    rt->current_stack_frame = sf;
+    ctx = p->u.cfunc.realm; /* change the current realm */
+    
 #ifdef CONFIG_BIGNUM
     /* we only propagate the bignum mode as some runtime functions
        test it */
@@ -15563,7 +15689,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj,
         abort();
     }
 
-    ctx->current_stack_frame = sf->prev_frame;
+    rt->current_stack_frame = sf->prev_frame;
     return ret_val;
 }
 
@@ -15579,7 +15705,7 @@ static JSValue js_call_bound_function(JSContext *ctx, JSValueConst func_obj,
     p = JS_VALUE_GET_OBJ(func_obj);
     bf = p->u.bound_function;
     arg_count = bf->argc + argc;
-    if (js_check_stack_overflow(ctx, sizeof(JSValue) * arg_count))
+    if (js_check_stack_overflow(ctx->rt, sizeof(JSValue) * arg_count))
         return JS_ThrowStackOverflow(ctx);
     arg_buf = alloca(sizeof(JSValue) * arg_count);
     for(i = 0; i < bf->argc; i++) {
@@ -15608,7 +15734,7 @@ static no_inline __exception int __js_poll_interrupts(JSContext *ctx)
         if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {
             /* XXX: should set a specific flag to avoid catching */
             JS_ThrowInternalError(ctx, "interrupted");
-            JS_SetUncatchableError(ctx, ctx->current_exception, TRUE);
+            JS_SetUncatchableError(ctx, ctx->rt->current_exception, TRUE);
             return -1;
         }
     }
@@ -15640,10 +15766,12 @@ typedef enum {
 #define FUNC_RET_YIELD_STAR 2
 
 /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
-static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
+static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
                                JSValueConst this_obj, JSValueConst new_target,
                                int argc, JSValue *argv, int flags)
 {
+    JSRuntime *rt = caller_ctx->rt;
+    JSContext *ctx;
     JSObject *p;
     JSFunctionBytecode *b;
     JSStackFrame sf_s, *sf = &sf_s;
@@ -15675,7 +15803,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
 #define BREAK           SWITCH(pc)
 #endif
 
-    if (js_poll_interrupts(ctx))
+    if (js_poll_interrupts(caller_ctx))
         return JS_EXCEPTION;
     if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) {
         if (flags & JS_CALL_FLAG_GENERATOR) {
@@ -15685,6 +15813,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             sf = &s->frame;
             p = JS_VALUE_GET_OBJ(sf->cur_func);
             b = p->u.func.function_bytecode;
+            ctx = b->realm;
             var_refs = p->u.func.var_refs;
             local_buf = arg_buf = sf->arg_buf;
             var_buf = sf->var_buf;
@@ -15692,8 +15821,8 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             sp = sf->cur_sp;
             sf->cur_sp = NULL; /* cur_sp is NULL if the function is running */
             pc = sf->cur_pc;
-            sf->prev_frame = ctx->current_stack_frame;
-            ctx->current_stack_frame = sf;
+            sf->prev_frame = rt->current_stack_frame;
+            rt->current_stack_frame = sf;
             if (s->throw_flag)
                 goto exception;
             else
@@ -15705,12 +15834,12 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
     p = JS_VALUE_GET_OBJ(func_obj);
     if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) {
         JSClassCall *call_func;
-        call_func = ctx->rt->class_array[p->class_id].call;
+        call_func = rt->class_array[p->class_id].call;
         if (!call_func) {
         not_a_function:
-            return JS_ThrowTypeError(ctx, "not a function");
+            return JS_ThrowTypeError(caller_ctx, "not a function");
         }
-        return call_func(ctx, func_obj, this_obj, argc,
+        return call_func(caller_ctx, func_obj, this_obj, argc,
                          (JSValueConst *)argv, flags);
     }
     b = p->u.func.function_bytecode;
@@ -15723,8 +15852,8 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
 
     alloca_size = sizeof(JSValue) * (arg_allocated_size + b->var_count +
                                      b->stack_size);
-    if (js_check_stack_overflow(ctx, alloca_size))
-        return JS_ThrowStackOverflow(ctx);
+    if (js_check_stack_overflow(rt, alloca_size))
+        return JS_ThrowStackOverflow(caller_ctx);
 
     sf->js_mode = b->js_mode;
     arg_buf = argv;
@@ -15738,7 +15867,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
         int n = min_int(argc, b->arg_count);
         arg_buf = local_buf;
         for(i = 0; i < n; i++)
-            arg_buf[i] = JS_DupValue(ctx, argv[i]);
+            arg_buf[i] = JS_DupValue(caller_ctx, argv[i]);
         for(; i < b->arg_count; i++)
             arg_buf[i] = JS_UNDEFINED;
         sf->arg_count = b->arg_count;
@@ -15753,8 +15882,10 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
     stack_buf = var_buf + b->var_count;
     sp = stack_buf;
     pc = b->byte_code_buf;
-    sf->prev_frame = ctx->current_stack_frame;
-    ctx->current_stack_frame = sf;
+    sf->prev_frame = rt->current_stack_frame;
+    rt->current_stack_frame = sf;
+    ctx = b->realm; /* set the current realm */
+    
  restart:
     for(;;) {
         int call_argc;
@@ -16178,7 +16309,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             /* return TRUE if 'this' should be returned */
             if (!JS_IsObject(sp[-1])) {
                 if (!JS_IsUndefined(sp[-1])) {
-                    JS_ThrowTypeError(ctx, "derived class constructor must return an object or undefined");
+                    JS_ThrowTypeError(caller_ctx, "derived class constructor must return an object or undefined");
                     goto exception;
                 }
                 sp[0] = JS_TRUE;
@@ -16189,7 +16320,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             BREAK;
         CASE(OP_check_ctor):
             if (JS_IsUndefined(new_target)) {
-                JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'");
+                JS_ThrowTypeError(caller_ctx, "class constructors must be invoked with 'new'");
                 goto exception;
             }
             BREAK;
@@ -16673,7 +16804,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
                 pr = add_property(ctx, JS_VALUE_GET_OBJ(sp[-1]), atom,
                                   JS_PROP_WRITABLE | JS_PROP_VARREF);
                 if (!pr) {
-                    free_var_ref(ctx->rt, var_ref);
+                    free_var_ref(rt, var_ref);
                     goto exception;
                 }
                 pr->u.var_ref = var_ref;
@@ -16870,6 +17001,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             BREAK;
 
         CASE(OP_iterator_close):
+            /* iter_obj next catch_offset -> */
             sp--; /* drop the catch offset to avoid getting caught by exception */
             JS_FreeValue(ctx, sp[-1]); /* drop the next method */
             sp--;
@@ -16908,24 +17040,28 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
             {
                 JSValue ret, method;
                 int ret_flag;
-                method = JS_GetProperty(ctx, sp[-3], JS_ATOM_return);
+                sp--; /* remove the catch offset */
+                method = JS_GetProperty(ctx, sp[-2], JS_ATOM_return);
                 if (JS_IsException(method))
                     goto exception;
                 if (JS_IsUndefined(method) || JS_IsNull(method)) {
                     ret = JS_UNDEFINED;
                     ret_flag = TRUE;
                 } else {
-                    ret = JS_CallFree(ctx, method, sp[-3], 0, NULL);
+                    ret = JS_CallFree(ctx, method, sp[-2], 0, NULL);
                     if (JS_IsException(ret))
                         goto exception;
+                    if (!JS_IsObject(ret)) {
+                        JS_FreeValue(ctx, ret);
+                        JS_ThrowTypeErrorNotAnObject(ctx);
+                        goto exception;
+                    }
                     ret_flag = FALSE;
                 }
-                JS_FreeValue(ctx, sp[-3]);
                 JS_FreeValue(ctx, sp[-2]);
                 JS_FreeValue(ctx, sp[-1]);
-                sp[-3] = ret;
-                sp[-2] = JS_NewBool(ctx, ret_flag);
-                sp -= 1;
+                sp[-2] = ret;
+                sp[-1] = JS_NewBool(ctx, ret_flag);
             }
             BREAK;
 
@@ -16949,6 +17085,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
                 BOOL ret_flag;
                 int flags;
                 flags = *pc++;
+                /* XXX: use another opcode such as OP_throw_var */
                 if (flags == 2) {
                     JS_ThrowTypeError(ctx, "iterator does not have a throw method");
                     goto exception;
@@ -17856,7 +17993,7 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
 
 #ifdef CONFIG_BIGNUM
         CASE(OP_mul_pow10):
-            if (ctx->rt->bigfloat_ops.mul_pow10(ctx, sp))
+            if (rt->bigfloat_ops.mul_pow10(ctx, sp))
                 goto exception;
             sp--;
             BREAK;
@@ -18101,14 +18238,14 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
         }
     }
  exception:
-    if (is_backtrace_needed(ctx, ctx->current_exception)) {
+    if (is_backtrace_needed(ctx, rt->current_exception)) {
         /* add the backtrace information now (it is not done
            before if the exception happens in a bytecode
            operation */
         sf->cur_pc = pc;
-        build_backtrace(ctx, ctx->current_exception, NULL, 0, 0);
+        build_backtrace(ctx, rt->current_exception, NULL, 0, 0);
     }
-    if (!JS_IsUncatchableError(ctx, ctx->current_exception)) {
+    if (!JS_IsUncatchableError(ctx, rt->current_exception)) {
         while (sp > stack_buf) {
             JSValue val = *--sp;
             JS_FreeValue(ctx, val);
@@ -18120,8 +18257,8 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
                     sp--;
                     JS_IteratorClose(ctx, sp[-1], TRUE);
                 } else {
-                    *sp++ = ctx->current_exception;
-                    ctx->current_exception = JS_NULL;
+                    *sp++ = rt->current_exception;
+                    rt->current_exception = JS_NULL;
                     pc = b->byte_code_buf + pos;
                     goto restart;
                 }
@@ -18140,14 +18277,14 @@ static JSValue JS_CallInternal(JSContext *ctx, JSValueConst func_obj,
     done:
         if (unlikely(!list_empty(&sf->var_ref_list))) {
             /* variable references reference the stack: must close them */
-            close_var_refs(ctx->rt, sf);
+            close_var_refs(rt, sf);
         }
         /* free the local variables and stack */
         for(pval = local_buf; pval < sp; pval++) {
             JS_FreeValue(ctx, *pval);
         }
     }
-    ctx->current_stack_frame = sf->prev_frame;
+    rt->current_stack_frame = sf->prev_frame;
     return ret_val;
 }
 
@@ -18167,24 +18304,62 @@ static JSValue JS_CallFree(JSContext *ctx, JSValue func_obj, JSValueConst this_o
     return res;
 }
 
-static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor,
-                                          JSValueConst def_proto)
+/* warning: the refcount of the context is not incremented. Return
+   NULL in case of exception (case of revoked proxy only) */
+static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj)
 {
-    JSValue proto;
-    proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);
-    if (JS_IsException(proto))
-        return proto;
-    if (!JS_IsObject(proto)) {
-        JS_FreeValue(ctx, proto);
-        proto = JS_DupValue(ctx, def_proto);
+    JSObject *p;
+    JSContext *realm;
+    
+    if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)
+        return ctx;
+    p = JS_VALUE_GET_OBJ(func_obj);
+    switch(p->class_id) {
+    case JS_CLASS_C_FUNCTION:
+        realm = p->u.cfunc.realm;
+        break;
+    case JS_CLASS_BYTECODE_FUNCTION:
+    case JS_CLASS_GENERATOR_FUNCTION:
+    case JS_CLASS_ASYNC_FUNCTION:
+    case JS_CLASS_ASYNC_GENERATOR_FUNCTION:
+        {
+            JSFunctionBytecode *b;
+            b = p->u.func.function_bytecode;
+            realm = b->realm;
+        }
+        break;
+    case JS_CLASS_PROXY:
+        {
+            JSProxyData *s = p->u.opaque;
+            if (!s)
+                return ctx;
+            if (s->is_revoked) {
+                JS_ThrowTypeErrorRevokedProxy(ctx);
+                return NULL;
+            } else {
+                realm = JS_GetFunctionRealm(ctx, s->target);
+            }
+        }
+        break;
+    case JS_CLASS_BOUND_FUNCTION:
+        {
+            JSBoundFunction *bf = p->u.bound_function;
+            realm = JS_GetFunctionRealm(ctx, bf->func_obj);
+        }
+        break;
+    default:
+        realm = ctx;
+        break;
     }
-    return proto;
+    return realm;
 }
 
 static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
                                    int class_id)
 {
     JSValue proto, obj;
+    JSContext *realm;
+    
     if (JS_IsUndefined(ctor)) {
         proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
     } else {
@@ -18193,14 +18368,10 @@ static JSValue js_create_from_ctor(JSContext *ctx, JSValueConst ctor,
             return proto;
         if (!JS_IsObject(proto)) {
             JS_FreeValue(ctx, proto);
-            /* check if revoked proxy */
-            {
-                JSProxyData *s = JS_GetOpaque(ctor, JS_CLASS_PROXY);
-                if (s && s->is_revoked)
-                    return JS_ThrowTypeErrorRevokedProxy(ctx);
-            }
-            /* XXX: should use the ctor realm instead of 'ctx' */
-            proto = JS_DupValue(ctx, ctx->class_proto[class_id]);
+            realm = JS_GetFunctionRealm(ctx, ctor);
+            if (!realm)
+                return JS_EXCEPTION;
+            proto = JS_DupValue(ctx, realm->class_proto[class_id]);
         }
     }
     obj = JS_NewObjectProtoClass(ctx, proto, class_id);
@@ -19709,7 +19880,7 @@ int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s, const
     backtrace_flags = 0;
     if (s->cur_func && s->cur_func->backtrace_barrier)
         backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
-    build_backtrace(ctx, ctx->current_exception, s->filename, s->line_num,
+    build_backtrace(ctx, ctx->rt->current_exception, s->filename, s->line_num,
                     backtrace_flags);
     return -1;
 }
@@ -20039,14 +20210,90 @@ static __exception int js_parse_regexp(JSParseState *s)
     return -1;
 }
 
+static __exception int ident_realloc(JSContext *ctx, char **pbuf, size_t *psize,
+                                     char *static_buf)
+{
+    char *buf, *new_buf;
+    size_t size, new_size;
+    
+    buf = *pbuf;
+    size = *psize;
+    if (size >= (SIZE_MAX / 3) * 2)
+        new_size = SIZE_MAX;
+    else
+        new_size = size + (size >> 1);
+    if (buf == static_buf) {
+        new_buf = js_malloc(ctx, new_size);
+        if (!new_buf)
+            return -1;
+        memcpy(new_buf, buf, size);
+    } else {
+        new_buf = js_realloc(ctx, buf, new_size);
+        if (!new_buf)
+            return -1;
+    }
+    *pbuf = new_buf;
+    *psize = new_size;
+    return 0;
+}
+
+/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
+static JSAtom parse_ident(JSParseState *s, const uint8_t **pp,
+                          BOOL *pident_has_escape, int c, BOOL is_private)
+{
+    const uint8_t *p, *p1;
+    char ident_buf[128], *buf;
+    size_t ident_size, ident_pos;
+    JSAtom atom;
+    
+    p = *pp;
+    buf = ident_buf;
+    ident_size = sizeof(ident_buf);
+    ident_pos = 0;
+    if (is_private)
+        buf[ident_pos++] = '#';
+    for(;;) {
+        p1 = p;
+        
+        if (c < 128) {
+            buf[ident_pos++] = c;
+        } else {
+            ident_pos += unicode_to_utf8((uint8_t*)buf + ident_pos, c);
+        }
+        c = *p1++;
+        if (c == '\\' && *p1 == 'u') {
+            c = lre_parse_escape(&p1, TRUE);
+            *pident_has_escape = TRUE;
+        } else if (c >= 128) {
+            c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
+        }
+        if (!lre_js_is_ident_next(c))
+            break;
+        p = p1;
+        if (unlikely(ident_pos >= ident_size - UTF8_CHAR_LEN_MAX)) {
+            if (ident_realloc(s->ctx, &buf, &ident_size, ident_buf)) {
+                atom = JS_ATOM_NULL;
+                goto done;
+            }
+        }
+    }
+    atom = JS_NewAtomLen(s->ctx, buf, ident_pos);
+ done:
+    if (unlikely(buf != ident_buf))
+        js_free(s->ctx, buf);
+    *pp = p;
+    return atom;
+}
+
+
 static __exception int next_token(JSParseState *s)
 {
     const uint8_t *p;
     int c;
-    char buf[4096], *q;
     BOOL ident_has_escape;
-
-    if (js_check_stack_overflow(s->ctx, 0)) {
+    JSAtom atom;
+    
+    if (js_check_stack_overflow(s->ctx->rt, 0)) {
         return js_parse_error(s, "stack overflow");
     }
     
@@ -20128,6 +20375,8 @@ static __exception int next_token(JSParseState *s)
                     c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
                     if (c == CP_LS || c == CP_PS) {
                         s->got_lf = TRUE; /* considered as LF for ASI */
+                    } else if (c == -1) {
+                        p++; /* skip invalid UTF-8 */
                     }
                 } else {
                     p++;
@@ -20146,8 +20395,11 @@ static __exception int next_token(JSParseState *s)
                 if (*p >= 0x80) {
                     c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
                     /* LS or PS are considered as line terminator */
-                    if (c == CP_LS || c == CP_PS)
+                    if (c == CP_LS || c == CP_PS) {
                         break;
+                    } else if (c == -1) {
+                        p++; /* skip invalid UTF-8 */
+                    }
                 } else {
                     p++;
                 }
@@ -20183,33 +20435,10 @@ static __exception int next_token(JSParseState *s)
         p++;
         ident_has_escape = FALSE;
     has_ident:
-        q = buf;
-        for(;;) {
-            const uint8_t *p1 = p;
-
-            if (c < 128) {
-                *q++ = c;
-            } else {
-                q += unicode_to_utf8((uint8_t*)q, c);
-            }
-            c = *p1++;
-            if (c == '\\' && *p1 == 'u') {
-                c = lre_parse_escape(&p1, TRUE);
-                ident_has_escape = TRUE;
-            } else if (c >= 128) {
-                c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
-            }
-            /* XXX: check if c >= 0 and c <= 0x10FFFF */
-            if (!lre_js_is_ident_next(c))
-                break;
-            p = p1;
-            if ((q - buf) >= sizeof(buf) - UTF8_CHAR_LEN_MAX) {
-                js_parse_error(s, "identifier too long");
-                goto fail;
-            }
-        }
-        *q = '\0';
-        s->token.u.ident.atom = JS_NewAtomLen(s->ctx, buf, q - buf);
+        atom = parse_ident(s, &p, &ident_has_escape, c, FALSE);
+        if (atom == JS_ATOM_NULL)
+            goto fail;
+        s->token.u.ident.atom = atom;
         s->token.u.ident.has_escape = ident_has_escape;
         s->token.u.ident.is_reserved = FALSE;
         if (s->token.u.ident.atom <= JS_ATOM_LAST_KEYWORD ||
@@ -20243,8 +20472,6 @@ static __exception int next_token(JSParseState *s)
         {
             const uint8_t *p1;
             p++;
-            q = buf;
-            *q++ = '#';
             p1 = p;
             c = *p1++;
             if (c == '\\' && *p1 == 'u') {
@@ -20257,31 +20484,11 @@ static __exception int next_token(JSParseState *s)
                 goto fail;
             }
             p = p1;
-            for(;;) {
-                if (c < 128) {
-                    *q++ = c;
-                } else {
-                    q += unicode_to_utf8((uint8_t*)q, c);
-                }
-                p1 = p;
-                c = *p1++;
-                if (c == '\\' && *p1 == 'u') {
-                    c = lre_parse_escape(&p1, TRUE);
-                    ident_has_escape = TRUE;
-                } else if (c >= 128) {
-                    c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p1);
-                }
-                /* XXX: check if c >= 0 and c <= 0x10FFFF */
-                if (!lre_js_is_ident_next(c))
-                    break;
-                p = p1;
-                if ((q - buf) >= sizeof(buf) - UTF8_CHAR_LEN_MAX) {
-                    js_parse_error(s, "private name too long");
-                    goto fail;
-                }
-            }
-            *q = '\0';
-            s->token.u.ident.atom = JS_NewAtomLen(s->ctx, buf, q - buf);
+            ident_has_escape = FALSE; /* not used */
+            atom = parse_ident(s, &p, &ident_has_escape, c, TRUE);
+            if (atom == JS_ATOM_NULL)
+                goto fail;
+            s->token.u.ident.atom = atom;
             s->token.val = TOK_PRIVATE_NAME;
         }
         break;
@@ -22175,16 +22382,25 @@ static __exception int js_parse_class(JSParseState *s, BOOL is_class_expr,
             continue;
         }
         is_static = (s->token.val == TOK_STATIC);
+        prop_type = -1;
         if (is_static) {
             if (next_token(s))
                 goto fail;
+            /* allow "static" field name */
+            if (s->token.val == ';' || s->token.val == '=') {
+                is_static = FALSE;
+                name = JS_DupAtom(ctx, JS_ATOM_static);
+                prop_type = PROP_TYPE_IDENT;
+            }
         }
         if (is_static)
             emit_op(s, OP_swap);
         start_ptr = s->token.ptr;
-        prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE);
-        if (prop_type < 0)
-            goto fail;
+        if (prop_type < 0) {
+            prop_type = js_parse_property_name(s, &name, TRUE, FALSE, TRUE);
+            if (prop_type < 0)
+                goto fail;
+        }
         is_private = prop_type & PROP_TYPE_PRIVATE;
         prop_type &= ~PROP_TYPE_PRIVATE;
         
@@ -22980,7 +23196,7 @@ duplicate:
     return js_parse_error(s, "duplicate parameter names not allowed in this context");
 }
 
-static JSAtom js_parse_destructing_var(JSParseState *s, int tok, int is_arg)
+static JSAtom js_parse_destructuring_var(JSParseState *s, int tok, int is_arg)
 {
     JSAtom name;
 
@@ -23002,7 +23218,7 @@ fail:
     return JS_ATOM_NULL;
 }
 
-static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
+static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
                                         int hasval, int has_ellipsis,
                                         BOOL allow_initializer)
 {
@@ -23055,7 +23271,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
                 if (next_token(s))
                     return -1;
                 if (tok) {
-                    var_name = js_parse_destructing_var(s, tok, is_arg);
+                    var_name = js_parse_destructuring_var(s, tok, is_arg);
                     if (var_name == JS_ATOM_NULL)
                         return -1;
                     opcode = OP_scope_get_var;
@@ -23119,7 +23335,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
                         emit_op(s, OP_get_field2);
                         emit_u32(s, prop_name);
                     }
-                    if (js_parse_destructing_element(s, tok, is_arg, TRUE, -1, TRUE))
+                    if (js_parse_destructuring_element(s, tok, is_arg, TRUE, -1, TRUE))
                         return -1;
                     if (s->token.val == '}')
                         break;
@@ -23152,7 +23368,7 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
                     emit_op(s, OP_dup);
                 }
                 if (tok) {
-                    var_name = js_parse_destructing_var(s, tok, is_arg);
+                    var_name = js_parse_destructuring_var(s, tok, is_arg);
                     if (var_name == JS_ATOM_NULL)
                         goto prop_error;
                 } else {
@@ -23316,13 +23532,13 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
                     emit_u8(s, 0);
                     emit_op(s, OP_drop);
                 }
-                if (js_parse_destructing_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, tok, is_arg, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
                     return -1;
             } else {
                 var_name = JS_ATOM_NULL;
                 enum_depth = 0;
                 if (tok) {
-                    var_name = js_parse_destructing_var(s, tok, is_arg);
+                    var_name = js_parse_destructuring_var(s, tok, is_arg);
                     if (var_name == JS_ATOM_NULL)
                         goto var_error;
                     if (js_define_var(s, var_name, tok))
@@ -23393,7 +23609,13 @@ static int js_parse_destructing_element(JSParseState *s, int tok, int is_arg,
         emit_goto(s, OP_goto, label_assign);
         emit_label(s, label_done);
     } else {
-        assert(hasval);
+        /* normally hasval is true except if
+           js_parse_skip_parens_token() was wrong in the parsing */
+        //        assert(hasval);
+        if (!hasval) {
+            js_parse_error(s, "too complicated destructuring expression");
+            return -1;
+        }
         /* remove test and decrement label ref count */
         memset(s->cur_func->byte_code.buf + start_addr, OP_nop,
                assign_addr - start_addr);
@@ -23515,7 +23737,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
                 backtrace_flags = 0;
                 if (s->cur_func && s->cur_func->backtrace_barrier)
                     backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL;
-                build_backtrace(s->ctx, s->ctx->current_exception,
+                build_backtrace(s->ctx, s->ctx->rt->current_exception,
                                 s->filename, s->token.line_num,
                                 backtrace_flags);
                 return -1;
@@ -23633,7 +23855,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, BOOL accept_lparen
         {
             int skip_bits;
             if (js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
-                if (js_parse_destructing_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, 0, 0, FALSE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
                     return -1;
             } else {
                 if (s->token.val == '{') {
@@ -24851,6 +25073,8 @@ static void emit_return(JSParseState *s, BOOL hasval)
             label_return = -1;
         }
 
+        /* XXX: if this is not initialized, should throw the
+           ReferenceError in the caller realm */
         emit_op(s, OP_scope_get_var);
         emit_atom(s, JS_ATOM_this);
         emit_u16(s, 0);
@@ -24977,7 +25201,7 @@ static __exception int js_parse_var(JSParseState *s, BOOL in_accepted, int tok,
             if ((s->token.val == '[' || s->token.val == '{')
             &&  js_parse_skip_parens_token(s, &skip_bits, FALSE) == '=') {
                 emit_op(s, OP_undefined);
-                if (js_parse_destructing_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+                if (js_parse_destructuring_element(s, tok, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
                     return -1;
             } else {
                 return js_parse_error(s, "variable name expected");
@@ -25106,7 +25330,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
 
         if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
             if (s->token.val == '[' || s->token.val == '{') {
-                if (js_parse_destructing_element(s, tok, 0, TRUE, -1, FALSE))
+                if (js_parse_destructuring_element(s, tok, 0, TRUE, -1, FALSE))
                     return -1;
                 has_destructuring = TRUE;
             } else {
@@ -25132,7 +25356,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name,
         int skip_bits;
         if ((s->token.val == '[' || s->token.val == '{')
         &&  ((tok1 = js_parse_skip_parens_token(s, &skip_bits, FALSE)) == TOK_IN || tok1 == TOK_OF)) {
-            if (js_parse_destructing_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
+            if (js_parse_destructuring_element(s, 0, 0, TRUE, skip_bits & SKIP_HAS_ELLIPSIS, TRUE))
                 return -1;
         } else {
             int lvalue_label, depth;
@@ -25815,7 +26039,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
                     if (!(s->token.val == TOK_IDENT && !s->token.u.ident.is_reserved)) {
                         if (s->token.val == '[' || s->token.val == '{') {
                             /* XXX: TOK_LET is not completely correct */
-                            if (js_parse_destructing_element(s, TOK_LET, 0, TRUE, -1, TRUE))
+                            if (js_parse_destructuring_element(s, TOK_LET, 0, TRUE, -1, TRUE))
                                 goto fail;
                         } else {
                             js_parse_error(s, "identifier expected");
@@ -26038,6 +26262,25 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
     return m;
 }
 
+static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
+                               JS_MarkFunc *mark_func)
+{
+    int i;
+
+    for(i = 0; i < m->export_entries_count; i++) {
+        JSExportEntry *me = &m->export_entries[i];
+        if (me->export_type == JS_EXPORT_TYPE_LOCAL &&
+            me->u.local.var_ref) {
+            mark_func(rt, &me->u.local.var_ref->header);
+        }
+    }
+
+    JS_MarkValue(rt, m->module_ns, mark_func);
+    JS_MarkValue(rt, m->func_obj, mark_func);
+    JS_MarkValue(rt, m->eval_exception, mark_func);
+    JS_MarkValue(rt, m->meta_obj, mark_func);
+}
+
 static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
 {
     int i;
@@ -26769,7 +27012,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m)
             /* the exported namespace must be created on demand */
             if (JS_DefineAutoInitProperty(ctx, obj,
                                           en->export_name,
-                                          js_module_ns_autoinit,
+                                          JS_AUTOINIT_ID_MODULE_NS,
                                           en->u.module, JS_PROP_ENUMERABLE | JS_PROP_WRITABLE) < 0)
                 goto fail;
             break;
@@ -27075,7 +27318,7 @@ static JSAtom js_get_script_or_module_name(JSContext *ctx)
     /* XXX: currently we just use the filename of the englobing
        function. It does not work for eval(). Need to add a
        ScriptOrModule info in JSFunctionBytecode */
-    sf = ctx->current_stack_frame;
+    sf = ctx->rt->current_stack_frame;
     assert(sf != NULL);
     assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);
     p = JS_VALUE_GET_OBJ(sf->cur_func);
@@ -27125,22 +27368,23 @@ static JSValue js_import_meta(JSContext *ctx)
     return JS_GetImportMeta(ctx, m);
 }
 
-static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
+static JSValue js_dynamic_import_job(JSContext *ctx,
+                                     int argc, JSValueConst *argv)
 {
+    JSValueConst *resolving_funcs = argv;
+    JSValueConst basename_val = argv[2];
+    JSValueConst specifier = argv[3];
     JSModuleDef *m;
-    JSAtom basename, filename;
-    JSValue promise, resolving_funcs[2];
+    JSAtom basename = JS_ATOM_NULL, filename;
     JSValue specifierString, ret, func_obj, err, ns;
-    
-    promise = JS_NewPromiseCapability(ctx, resolving_funcs);
-    if (JS_IsException(promise))
-        return promise;
-    
-    basename = js_get_script_or_module_name(ctx);
-    if (basename == JS_ATOM_NULL) {
+
+    if (!JS_IsString(basename_val)) {
         JS_ThrowTypeError(ctx, "no function filename for import()");
         goto exception;
     }
+    basename = JS_ValueToAtom(ctx, basename_val);
+    if (basename == JS_ATOM_NULL)
+        goto exception;
 
     specifierString = JS_ToString(ctx, specifier);
     if (JS_IsException(specifierString))
@@ -27177,16 +27421,47 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
                    1, (JSValueConst *)&ns);
     JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
     JS_FreeValue(ctx, ns);
-    JS_FreeValue(ctx, resolving_funcs[0]);
-    JS_FreeValue(ctx, resolving_funcs[1]);
-    return promise;
-
+    JS_FreeAtom(ctx, basename);
+    return JS_UNDEFINED;
  exception:
+
     err = JS_GetException(ctx);
     ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
                    1, (JSValueConst *)&err);
     JS_FreeValue(ctx, ret); /* XXX: what to do if exception ? */
     JS_FreeValue(ctx, err);
+    JS_FreeAtom(ctx, basename);
+    return JS_UNDEFINED;
+}
+
+static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
+{
+    JSAtom basename;
+    JSValue promise, resolving_funcs[2], basename_val;
+    JSValueConst args[4];
+
+    basename = js_get_script_or_module_name(ctx);
+    if (basename == JS_ATOM_NULL)
+        basename_val = JS_NULL;
+    else
+        basename_val = JS_AtomToValue(ctx, basename);
+    if (JS_IsException(basename_val))
+        return basename_val;
+    
+    promise = JS_NewPromiseCapability(ctx, resolving_funcs);
+    if (JS_IsException(promise)) {
+        JS_FreeValue(ctx, basename_val);
+        return promise;
+    }
+
+    args[0] = resolving_funcs[0];
+    args[1] = resolving_funcs[1];
+    args[2] = basename_val;
+    args[3] = specifier;
+    
+    JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
+
+    JS_FreeValue(ctx, basename_val);
     JS_FreeValue(ctx, resolving_funcs[0]);
     JS_FreeValue(ctx, resolving_funcs[1]);
     return promise;
@@ -27241,7 +27516,7 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
     if (JS_IsException(ret_val)) {
         /* save the thrown exception value */
         m->eval_has_exception = TRUE;
-        m->eval_exception = JS_DupValue(ctx, ctx->current_exception);
+        m->eval_exception = JS_DupValue(ctx, ctx->rt->current_exception);
     }
     m->eval_mark = FALSE;
     m->evaluated = TRUE;
@@ -27521,6 +27796,10 @@ static __exception int js_parse_import(JSParseState *s)
                 return js_parse_error(s, "expecting 'as'");
             if (next_token(s))
                 return -1;
+            if (!token_is_ident(s->token.val)) {
+                js_parse_error(s, "identifier expected");
+                return -1;
+            }
             local_name = JS_DupAtom(ctx, s->token.u.ident.atom);
             import_name = JS_ATOM__star_;
             if (next_token(s))
@@ -31469,6 +31748,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd)
     b->super_allowed = fd->super_allowed;
     b->arguments_allowed = fd->arguments_allowed;
     b->backtrace_barrier = fd->backtrace_barrier;
+    b->realm = JS_DupContext(ctx);
 
     add_gc_object(ctx->rt, &b->header, JS_GC_OBJ_TYPE_FUNCTION_BYTECODE);
     
@@ -31515,6 +31795,8 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b)
         JSClosureVar *cv = &b->closure_var[i];
         JS_FreeAtomRT(rt, cv->var_name);
     }
+    if (b->realm)
+        JS_FreeContext(b->realm);
 
     JS_FreeAtomRT(rt, b->func_name);
     if (b->has_debug) {
@@ -31910,7 +32192,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
                     emit_op(s, OP_get_arg);
                     emit_u16(s, idx);
                 }
-                if (js_parse_destructing_element(s, TOK_VAR, 1, TRUE, -1, TRUE))
+                if (js_parse_destructuring_element(s, TOK_VAR, 1, TRUE, -1, TRUE))
                     goto fail;
             } else if (s->token.val == TOK_IDENT) {
                 if (s->token.u.ident.is_reserved) {
@@ -32309,8 +32591,11 @@ static void skip_shebang(JSParseState *s)
                 break;
             } else if (*p >= 0x80) {
                 c = unicode_from_utf8(p, UTF8_CHAR_LEN_MAX, &p);
-                if (c == CP_LS || c == CP_PS)
+                if (c == CP_LS || c == CP_PS) {
                     break;
+                } else if (c == -1) {
+                    p++; /* skip invalid UTF-8 */
+                }
             } else {
                 p++;
             }
@@ -32340,7 +32625,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
     m = NULL;
     if (eval_type == JS_EVAL_TYPE_DIRECT) {
         JSObject *p;
-        sf = ctx->current_stack_frame;
+        sf = ctx->rt->current_stack_frame;
         assert(sf != NULL);
         assert(JS_VALUE_GET_TAG(sf->cur_func) == JS_TAG_OBJECT);
         p = JS_VALUE_GET_OBJ(sf->cur_func);
@@ -33907,6 +34192,7 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
                 bc_read_trace(s, "}\n");
             }
             bc_read_trace(s, "}\n");
+            b->realm = JS_DupContext(ctx);
         }
         break;
     case BC_TAG_MODULE:
@@ -34095,8 +34381,9 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
  fail:
     if (m) {
         js_free_module_def(ctx, m);
+    } else {
+        JS_FreeValue(ctx, obj);
     }
-    JS_FreeValue(ctx, obj);
     return JS_EXCEPTION;
 }
 
@@ -34336,7 +34623,7 @@ void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
         case JS_DEF_OBJECT:
             prop_flags = JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | (e->prop_flags & JS_PROP_ENUMERABLE);
             JS_DefineAutoInitProperty(ctx, obj, atom,
-                                      JS_InstantiateFunctionListItem,
+                                      JS_AUTOINIT_ID_PROP,
                                       (void *)e, prop_flags);
             break;
         case JS_DEF_PROP_INT32:
@@ -35816,15 +36103,21 @@ static JSValue js_function_constructor(JSContext *ctx, JSValueConst new_target,
         goto fail1;
     if (!JS_IsUndefined(new_target)) {
         /* set the prototype */
-        proto = js_get_prototype_from_ctor(ctx, new_target, JS_UNDEFINED);
+        proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);
         if (JS_IsException(proto))
             goto fail1;
-        if (!JS_IsUndefined(proto)) {
-            ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);
+        if (!JS_IsObject(proto)) {
+            JSContext *realm;
             JS_FreeValue(ctx, proto);
-            if (ret < 0)
+            realm = JS_GetFunctionRealm(ctx, new_target);
+            if (!realm)
                 goto fail1;
+            proto = JS_DupValue(ctx, realm->class_proto[func_kind_to_class_id[func_kind]]);
         }
+        ret = JS_SetPrototypeInternal(ctx, obj, proto, TRUE);
+        JS_FreeValue(ctx, proto);
+        if (ret < 0)
+            goto fail1;
     }
     return obj;
 
@@ -36073,29 +36366,90 @@ static const JSCFunctionListEntry js_function_proto_funcs[] = {
 
 /* Error class */
 
+static JSValue iterator_to_array(JSContext *ctx, JSValueConst items)
+{
+    JSValue iter, next_method = JS_UNDEFINED;
+    JSValue v, r = JS_UNDEFINED;
+    int64_t k;
+    BOOL done;
+    
+    iter = JS_GetIterator(ctx, items, FALSE);
+    if (JS_IsException(iter))
+        goto exception;
+    next_method = JS_GetProperty(ctx, iter, JS_ATOM_next);
+    if (JS_IsException(next_method))
+        goto exception;
+    r = JS_NewArray(ctx);
+    if (JS_IsException(r))
+        goto exception;
+    for (k = 0;; k++) {
+        v = JS_IteratorNext(ctx, iter, next_method, 0, NULL, &done);
+        if (JS_IsException(v))
+            goto exception_close;
+        if (done)
+            break;
+        if (JS_DefinePropertyValueInt64(ctx, r, k, v,
+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+            goto exception_close;
+    }
+ done:
+    JS_FreeValue(ctx, next_method);
+    JS_FreeValue(ctx, iter);
+    return r;
+ exception_close:
+    JS_IteratorClose(ctx, iter, TRUE);
+ exception:
+    JS_FreeValue(ctx, r);
+    r = JS_EXCEPTION;
+    goto done;
+}
+
 static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target,
                                     int argc, JSValueConst *argv, int magic)
 {
     JSValue obj, msg, proto;
-    JSValueConst proto1;
+    JSValueConst message;
 
     if (JS_IsUndefined(new_target))
         new_target = JS_GetActiveFunction(ctx);
-    if (magic < 0) {
-        proto1 = ctx->class_proto[JS_CLASS_ERROR];
-    } else {
-        proto1 = ctx->native_error_proto[magic];
-    }
-    proto = js_get_prototype_from_ctor(ctx, new_target, proto1);
+    proto = JS_GetProperty(ctx, new_target, JS_ATOM_prototype);
     if (JS_IsException(proto))
         return proto;
+    if (!JS_IsObject(proto)) {
+        JSContext *realm;
+        JSValueConst proto1;
+        
+        JS_FreeValue(ctx, proto);
+        realm = JS_GetFunctionRealm(ctx, new_target);
+        if (!realm)
+            return JS_EXCEPTION;
+        if (magic < 0) {
+            proto1 = realm->class_proto[JS_CLASS_ERROR];
+        } else {
+            proto1 = realm->native_error_proto[magic];
+        }
+        proto = JS_DupValue(ctx, proto1);
+    }
     obj = JS_NewObjectProtoClass(ctx, proto, JS_CLASS_ERROR);
     JS_FreeValue(ctx, proto);
     if (JS_IsException(obj))
         return obj;
-    if (!JS_IsUndefined(argv[0])) {
-        msg = JS_ToString(ctx, argv[0]);
+    if (magic == JS_AGGREGATE_ERROR) {
+        JSObject *p;
+        JSValue error_list = iterator_to_array(ctx, argv[0]);
+        if (JS_IsException(error_list))
+            goto exception;
+        p = JS_VALUE_GET_OBJ(obj);
+        p->u.object_data = error_list;
+        message = argv[1];
+    } else {
+        message = argv[0];
+    }
+
+    if (!JS_IsUndefined(message)) {
+        msg = JS_ToString(ctx, message);
         if (unlikely(JS_IsException(msg))) {
+        exception:
             JS_FreeValue(ctx, obj);
             return JS_EXCEPTION;
         }
@@ -36142,6 +36496,58 @@ static const JSCFunctionListEntry js_error_proto_funcs[] = {
     JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ),
 };
 
+/* AggregateError */
+
+/* used by C code. 'errors' must be a fast array. */
+static JSValue js_aggregate_error_constructor(JSContext *ctx,
+                                              JSValueConst errors)
+{
+    JSValue obj;
+    JSObject *p;
+    
+    obj = JS_NewObjectProtoClass(ctx,
+                                 ctx->native_error_proto[JS_AGGREGATE_ERROR],
+                                 JS_CLASS_ERROR);
+    if (JS_IsException(obj))
+        return obj;
+    p = JS_VALUE_GET_OBJ(obj);
+    p->u.object_data = JS_DupValue(ctx, errors);
+    return obj;
+}
+
+static JSValue js_aggregate_error_errors(JSContext *ctx, JSValueConst this_val)
+{
+    JSObject *p;
+    JSValue r, *arr;
+    uint32_t len, i;
+    
+    if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
+        goto invalid_type;
+    p = JS_VALUE_GET_OBJ(this_val);
+    if (p->class_id != JS_CLASS_ERROR)
+        goto invalid_type;
+    if (!js_get_fast_array(ctx, p->u.object_data, &arr, &len)) {
+    invalid_type:
+        return JS_ThrowTypeError(ctx, "not an AggregateError");
+    }
+    r = JS_NewArray(ctx);
+    if (JS_IsException(r))
+        goto exception;
+    for(i = 0; i < len; i++) {
+        if (JS_DefinePropertyValueInt64(ctx, r, i, JS_DupValue(ctx, arr[i]),
+                                        JS_PROP_C_W_E | JS_PROP_THROW) < 0)
+            goto exception;
+    }
+    return r;
+ exception:
+    JS_FreeValue(ctx, r);
+    return JS_EXCEPTION;
+}
+
+static const JSCFunctionListEntry js_aggregate_error_proto_funcs[] = {
+    JS_CGETSET_DEF("errors", js_aggregate_error_errors, NULL),
+};
+
 /* Array */
 
 static int JS_CopySubArray(JSContext *ctx,
@@ -36367,22 +36773,47 @@ static JSValue js_get_this(JSContext *ctx,
 static JSValue JS_ArraySpeciesCreate(JSContext *ctx, JSValueConst obj,
                                      JSValueConst len_val)
 {
-    JSValue ctor, ret;
+    JSValue ctor, ret, species;
     int res;
-
+    JSContext *realm;
+    
     res = JS_IsArray(ctx, obj);
     if (res < 0)
         return JS_EXCEPTION;
     if (!res)
         return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);
-    ctor = JS_SpeciesConstructor(ctx, obj, JS_UNDEFINED);
+    ctor = JS_GetProperty(ctx, obj, JS_ATOM_constructor);
     if (JS_IsException(ctor))
-        return JS_EXCEPTION;
-    if (JS_IsUndefined(ctor))
+        return ctor;
+    if (JS_IsConstructor(ctx, ctor)) {
+        /* legacy web compatibility */
+        realm = JS_GetFunctionRealm(ctx, ctor);
+        if (!realm) {
+            JS_FreeValue(ctx, ctor);
+            return JS_EXCEPTION;
+        }
+        if (realm != ctx &&
+            js_same_value(ctx, ctor, realm->array_ctor)) {
+            JS_FreeValue(ctx, ctor);
+            ctor = JS_UNDEFINED;
+        }
+    }
+    if (JS_IsObject(ctor)) {
+        species = JS_GetProperty(ctx, ctor, JS_ATOM_Symbol_species);
+        JS_FreeValue(ctx, ctor);
+        if (JS_IsException(species))
+            return species;
+        ctor = species;
+        if (JS_IsNull(ctor))
+            ctor = JS_UNDEFINED;
+    }
+    if (JS_IsUndefined(ctor)) {
         return js_array_constructor(ctx, JS_UNDEFINED, 1, &len_val);
-    ret = JS_CallConstructor(ctx, ctor, 1, &len_val);
-    JS_FreeValue(ctx, ctor);
-    return ret;
+    } else {
+        ret = JS_CallConstructor(ctx, ctor, 1, &len_val);
+        JS_FreeValue(ctx, ctor);
+        return ret;
+    }
 }
 
 static const JSCFunctionListEntry js_array_funcs[] = {
@@ -36435,7 +36866,7 @@ static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val,
         if (res) {
             if (js_get_length64(ctx, &len, e))
                 goto exception;
-            if (n + len >= MAX_SAFE_INTEGER) {
+            if (n + len > MAX_SAFE_INTEGER) {
                 JS_ThrowTypeError(ctx, "Array loo long");
                 goto exception;
             }
@@ -38221,14 +38652,31 @@ static int js_string_define_own_property(JSContext *ctx,
                                          JSValueConst setter, int flags)
 {
     uint32_t idx;
-
+    JSObject *p;
+    JSString *p1, *p2;
+    
     if (__JS_AtomIsTaggedInt(prop)) {
         idx = __JS_AtomToUInt32(prop);
-        if (idx >= js_string_obj_get_length(ctx, this_obj))
+        p = JS_VALUE_GET_OBJ(this_obj);
+        if (JS_VALUE_GET_TAG(p->u.object_data) != JS_TAG_STRING)
+            goto def;
+        p1 = JS_VALUE_GET_STRING(p->u.object_data);
+        if (idx >= p1->len)
             goto def;
         if (!check_define_prop_flags(JS_PROP_ENUMERABLE, flags))
-            return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
-        /* XXX: should check if same value is configured */
+            goto fail;
+        /* check that the same value is configured */
+        if (flags & JS_PROP_HAS_VALUE) {
+            if (JS_VALUE_GET_TAG(val) != JS_TAG_STRING)
+                goto fail;
+            p2 = JS_VALUE_GET_STRING(val);
+            if (p2->len != 1)
+                goto fail;
+            if (string_get(p1, idx) != string_get(p2, 0)) {
+            fail:
+                return JS_ThrowTypeErrorOrFalse(ctx, flags, "property is not configurable");
+            }
+        }
         return TRUE;
     } else {
     def:
@@ -38578,12 +39026,14 @@ static int string_indexof(JSString *p1, JSString *p2, int from)
     return -1;
 }
 
-static int string_advance_index(JSString *p, int index, BOOL unicode)
+static int64_t string_advance_index(JSString *p, int64_t index, BOOL unicode)
 {
-    if (!unicode || (unsigned)index >= p->len || !p->is_wide_char) {
+    if (!unicode || index >= p->len || !p->is_wide_char) {
         index++;
     } else {
-        string_getc(p, &index);
+        int index32 = (int)index;
+        string_getc(p, &index32);
+        index = index32;
     }
     return index;
 }
@@ -38930,7 +39380,7 @@ static JSValue js_string_replace(JSContext *ctx, JSValueConst this_val,
         replacer = JS_GetProperty(ctx, searchValue, JS_ATOM_Symbol_replace);
         if (JS_IsException(replacer))
             return JS_EXCEPTION;
-        if (!JS_IsUndefined(replacer)) {
+        if (!JS_IsUndefined(replacer) && !JS_IsNull(replacer)) {
             args[0] = O;
             args[1] = replaceValue;
             return JS_CallFree(ctx, replacer, searchValue, 2, args);
@@ -40162,6 +40612,20 @@ static JSValue js___date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val
         return JS_NewInt32(ctx, getTimezoneOffset((int64_t)dd));
 }
 
+static JSValue js_get_prototype_from_ctor(JSContext *ctx, JSValueConst ctor,
+                                          JSValueConst def_proto)
+{
+    JSValue proto;
+    proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);
+    if (JS_IsException(proto))
+        return proto;
+    if (!JS_IsObject(proto)) {
+        JS_FreeValue(ctx, proto);
+        proto = JS_DupValue(ctx, def_proto);
+    }
+    return proto;
+}
+
 /* create a new date object */
 static JSValue js___date_create(JSContext *ctx, JSValueConst this_val,
                                 int argc, JSValueConst *argv)
@@ -40531,13 +40995,14 @@ static JSValue js_regexp_get_flag(JSContext *ctx, JSValueConst this_val, int mas
     if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT)
         return JS_ThrowTypeErrorNotAnObject(ctx);
 
-    if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))
-        return JS_UNDEFINED;
-
-    re = js_get_regexp(ctx, this_val, TRUE);
-    if (!re)
-        return JS_EXCEPTION;
-
+    re = js_get_regexp(ctx, this_val, FALSE);
+    if (!re) {
+        if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_REGEXP]))
+            return JS_UNDEFINED;
+        else
+            return JS_ThrowTypeErrorInvalidClass(ctx, JS_CLASS_REGEXP);
+    }
+    
     flags = lre_get_flags(re->bytecode->u.str8);
     return JS_NewBool(ctx, (flags & mask) != 0);
 }
@@ -40614,7 +41079,7 @@ fail:
 BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size)
 {
     JSContext *ctx = opaque;
-    return js_check_stack_overflow(ctx, alloca_size);
+    return js_check_stack_overflow(ctx->rt, alloca_size);
 }
 
 void *lre_realloc(void *opaque, void *ptr, size_t size)
@@ -40753,7 +41218,7 @@ fail1:
     return JS_EXCEPTION;
 }
 
-/* delete partions of a string that match a given regex */
+/* delete portions of a string that match a given regex */
 static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValueConst arg)
 {
     JSRegExp *re = js_get_regexp(ctx, this_val, TRUE);
@@ -40952,9 +41417,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
                                     JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)
                     goto exception;
                 p = JS_VALUE_GET_STRING(S);
-                nextIndex = thisIndex + 1;
-                if (thisIndex < p->len)
-                    nextIndex = string_advance_index(p, thisIndex, fullUnicode);
+                nextIndex = string_advance_index(p, thisIndex, fullUnicode);
                 if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)
                     goto exception;
             }
@@ -41043,7 +41506,7 @@ static JSValue js_regexp_string_iterator_next(JSContext *ctx,
             sp = JS_VALUE_GET_STRING(S);
             nextIndex = string_advance_index(sp, thisIndex, it->unicode);
             if (JS_SetProperty(ctx, R, JS_ATOM_lastIndex,
-                               JS_NewInt32(ctx, nextIndex)) < 0)
+                               JS_NewInt64(ctx, nextIndex)) < 0)
                 goto exception;
         }
         JS_FreeValue(ctx, matchStr);
@@ -41096,7 +41559,7 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val,
                         JS_GetProperty(ctx, R, JS_ATOM_lastIndex)))
         goto exception;
     if (JS_SetProperty(ctx, matcher, JS_ATOM_lastIndex,
-                       JS_NewInt32(ctx, lastIndex)) < 0)
+                       JS_NewInt64(ctx, lastIndex)) < 0)
         goto exception;
     
     iter = JS_NewObjectClass(ctx, JS_CLASS_REGEXP_STRING_ITERATOR);
@@ -41284,7 +41747,7 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
             if (JS_ToLengthFree(ctx, &thisIndex, JS_GetProperty(ctx, rx, JS_ATOM_lastIndex)) < 0)
                 goto exception;
             nextIndex = string_advance_index(sp, thisIndex, fullUnicode);
-            if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt32(ctx, nextIndex)) < 0)
+            if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, JS_NewInt64(ctx, nextIndex)) < 0)
                 goto exception;
         }
     }
@@ -41343,14 +41806,23 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val,
             JS_FreeValue(ctx, rep_str);
             rep_str = JS_ToStringFree(ctx, js_function_apply(ctx, rep, 2, args, 0));
         } else {
+            JSValue namedCaptures1;
+            if (!JS_IsUndefined(namedCaptures)) {
+                namedCaptures1 = JS_ToObject(ctx, namedCaptures);
+                if (JS_IsException(namedCaptures1))
+                    goto exception;
+            } else {
+                namedCaptures1 = JS_UNDEFINED;
+            }
             args[0] = matched;
             args[1] = str;
             args[2] = JS_NewInt32(ctx, position);
             args[3] = tab;
-            args[4] = namedCaptures;
+            args[4] = namedCaptures1;
             args[5] = rep_val;
             JS_FreeValue(ctx, rep_str);
             rep_str = js_string___GetSubstitution(ctx, JS_UNDEFINED, 6, args);
+            JS_FreeValue(ctx, namedCaptures1);
         }
         if (JS_IsException(rep_str))
             goto exception;
@@ -41790,7 +42262,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
     JSAtom prop;
     JSPropertyEnum *atoms = NULL;
 
-    if (js_check_stack_overflow(ctx, 0)) {
+    if (js_check_stack_overflow(ctx->rt, 0)) {
         return JS_ThrowStackOverflow(ctx);
     }
 
@@ -42516,7 +42988,7 @@ static JSProxyData *get_proxy_method(JSContext *ctx, JSValue *pmethod,
     JSValue method;
 
     /* safer to test recursion in all proxy methods */
-    if (js_check_stack_overflow(ctx, 0)) {
+    if (js_check_stack_overflow(ctx->rt, 0)) {
         JS_ThrowStackOverflow(ctx);
         return NULL;
     }
@@ -43346,14 +43818,6 @@ static JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val,
     if (JS_VALUE_GET_TAG(target) != JS_TAG_OBJECT ||
         JS_VALUE_GET_TAG(handler) != JS_TAG_OBJECT)
         return JS_ThrowTypeErrorNotAnObject(ctx);
-    s = JS_GetOpaque(target, JS_CLASS_PROXY);
-    if (s && s->is_revoked)
-        goto revoked_proxy;
-    s = JS_GetOpaque(handler, JS_CLASS_PROXY);
-    if (s && s->is_revoked) {
-    revoked_proxy:
-        return JS_ThrowTypeErrorRevokedProxy(ctx);
-    }
 
     obj = JS_NewObjectProtoClass(ctx, JS_NULL, JS_CLASS_PROXY);
     if (JS_IsException(obj))
@@ -44872,14 +45336,18 @@ static __exception int remainingElementsCount_add(JSContext *ctx,
     return (remainingElementsCount == 0);
 }
 
+#define PROMISE_MAGIC_all        0
+#define PROMISE_MAGIC_allSettled 1
+#define PROMISE_MAGIC_any        2
+
 static JSValue js_promise_all_resolve_element(JSContext *ctx,
                                               JSValueConst this_val,
                                               int argc, JSValueConst *argv,
                                               int magic,
                                               JSValue *func_data)
 {
-    int is_allSettled = magic & 1;
-    int is_reject = magic & 2;
+    int resolve_type = magic & 3;
+    int is_reject = magic & 4;
     BOOL alreadyCalled = JS_ToBool(ctx, func_data[0]);
     JSValueConst values = func_data[2];
     JSValueConst resolve = func_data[3];
@@ -44893,7 +45361,7 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
         return JS_UNDEFINED;
     func_data[0] = JS_NewBool(ctx, TRUE);
 
-    if (is_allSettled) {
+    if (resolve_type == PROMISE_MAGIC_allSettled) {
         JSValue str;
         
         obj = JS_NewObject(ctx);
@@ -44925,7 +45393,16 @@ static JSValue js_promise_all_resolve_element(JSContext *ctx,
     if (is_zero < 0)
         return JS_EXCEPTION;
     if (is_zero) {
-        ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
+        if (resolve_type == PROMISE_MAGIC_any) {
+            JSValue error;
+            error = js_aggregate_error_constructor(ctx, values);
+            if (JS_IsException(error))
+                return JS_EXCEPTION;
+            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&error);
+            JS_FreeValue(ctx, error);
+        } else {
+            ret = JS_Call(ctx, resolve, JS_UNDEFINED, 1, (JSValueConst *)&values);
+        }
         if (JS_IsException(ret))
             return ret;
         JS_FreeValue(ctx, ret);
@@ -44942,8 +45419,8 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
     JSValue resolve_element_env = JS_UNDEFINED, resolve_element, reject_element;
     JSValue promise_resolve = JS_UNDEFINED;
     JSValueConst then_args[2], resolve_element_data[5];
-    BOOL done, is_allSettled = magic;
-    int index, is_zero;
+    BOOL done;
+    int index, is_zero, is_promise_any = (magic == PROMISE_MAGIC_any);
     
     if (!JS_IsObject(this_val))
         return JS_ThrowTypeErrorNotAnObject(ctx);
@@ -45002,24 +45479,30 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
             resolve_element_data[0] = JS_NewBool(ctx, FALSE);
             resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);
             resolve_element_data[2] = values;
-            resolve_element_data[3] = resolving_funcs[0];
+            resolve_element_data[3] = resolving_funcs[is_promise_any];
             resolve_element_data[4] = resolve_element_env;
             resolve_element =
                 JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,
-                                    is_allSettled, 5, resolve_element_data);
+                                    magic, 5, resolve_element_data);
             if (JS_IsException(resolve_element)) {
                 JS_FreeValue(ctx, next_promise);
                 goto fail_reject1;
             }
             
-            if (is_allSettled) {
+            if (magic == PROMISE_MAGIC_allSettled) {
                 reject_element =
                     JS_NewCFunctionData(ctx, js_promise_all_resolve_element, 1,
-                                        is_allSettled | 2, 5, resolve_element_data);
+                                        magic | 4, 5, resolve_element_data);
                 if (JS_IsException(reject_element)) {
                     JS_FreeValue(ctx, next_promise);
                     goto fail_reject1;
                 }
+            } else if (magic == PROMISE_MAGIC_any) {
+                if (JS_DefinePropertyValueUint32(ctx, values, index,
+                                                 JS_UNDEFINED, JS_PROP_C_W_E) < 0)
+                    goto fail_reject1;
+                reject_element = resolve_element;
+                resolve_element = JS_DupValue(ctx, resolving_funcs[0]);
             } else {
                 reject_element = JS_DupValue(ctx, resolving_funcs[1]);
             }
@@ -45045,7 +45528,15 @@ static JSValue js_promise_all(JSContext *ctx, JSValueConst this_val,
         if (is_zero < 0)
             goto fail_reject;
         if (is_zero) {
-            ret = JS_Call(ctx, resolving_funcs[0], JS_UNDEFINED,
+            if (magic == PROMISE_MAGIC_any) {
+                JSValue error;
+                error = js_aggregate_error_constructor(ctx, values);
+                if (JS_IsException(error))
+                    goto fail_reject;
+                JS_FreeValue(ctx, values);
+                values = error;
+            }
+            ret = JS_Call(ctx, resolving_funcs[is_promise_any], JS_UNDEFINED,
                           1, (JSValueConst *)&values);
             if (check_exception_free(ctx, ret))
                 goto fail_reject;
@@ -45323,8 +45814,9 @@ static JSValue js_promise_finally(JSContext *ctx, JSValueConst this_val,
 static const JSCFunctionListEntry js_promise_funcs[] = {
     JS_CFUNC_MAGIC_DEF("resolve", 1, js_promise_resolve, 0 ),
     JS_CFUNC_MAGIC_DEF("reject", 1, js_promise_resolve, 1 ),
-    JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, 0 ),
-    JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, 1 ),
+    JS_CFUNC_MAGIC_DEF("all", 1, js_promise_all, PROMISE_MAGIC_all ),
+    JS_CFUNC_MAGIC_DEF("allSettled", 1, js_promise_all, PROMISE_MAGIC_allSettled ),
+    JS_CFUNC_MAGIC_DEF("any", 1, js_promise_all, PROMISE_MAGIC_any ),
     JS_CFUNC_DEF("race", 1, js_promise_race ),
     //JS_CFUNC_DEF("__newPromiseCapability", 1, js_promise___newPromiseCapability ),
     JS_CGETSET_DEF("[Symbol.species]", js_get_this, NULL),
@@ -45459,7 +45951,8 @@ static JSValue js_async_from_sync_iterator_next(JSContext *ctx, JSValueConst thi
             goto done_resolve;
         }
     }
-    value = JS_IteratorNext2(ctx, s->sync_iter, method, 1, argv, &done);
+    value = JS_IteratorNext2(ctx, s->sync_iter, method,
+                             argc >= 1 ? 1 : 0, argv, &done);
     JS_FreeValue(ctx, method);
     if (JS_IsException(value))
         goto reject;
@@ -48852,7 +49345,7 @@ void JS_EnableBignumExt(JSContext *ctx, BOOL enable)
 static const char * const native_error_name[JS_NATIVE_ERROR_COUNT] = {
     "EvalError", "RangeError", "ReferenceError",
     "SyntaxError", "TypeError", "URIError",
-    "InternalError",
+    "InternalError", "AggregateError",
 };
 
 /* Minimum amount of objects to be able to compile code and display
@@ -48892,6 +49385,9 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx)
                                JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
         ctx->native_error_proto[i] = proto;
     }
+    JS_SetPropertyFunctionList(ctx, ctx->native_error_proto[JS_AGGREGATE_ERROR],
+                               js_aggregate_error_proto_funcs,
+                               countof(js_aggregate_error_proto_funcs));
 
     /* the array prototype is an array */
     ctx->class_proto[JS_CLASS_ARRAY] =
@@ -48957,9 +49453,12 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
                               "Error", ctx->class_proto[JS_CLASS_ERROR]);
 
     for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
-        JSValue func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,
-                                            native_error_name[i], 1,
-                                            JS_CFUNC_constructor_or_func_magic, i, obj1);
+        JSValue func_obj;
+        int n_args;
+        n_args = 1 + (i == JS_AGGREGATE_ERROR);
+        func_obj = JS_NewCFunction3(ctx, (JSCFunction *)js_error_constructor,
+                                    native_error_name[i], n_args,
+                                    JS_CFUNC_constructor_or_func_magic, i, obj1);
         JS_NewGlobalCConstructor2(ctx, func_obj, native_error_name[i],
                                   ctx->native_error_proto[i]);
     }
@@ -48977,6 +49476,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
 
     obj = JS_NewGlobalCConstructor(ctx, "Array", js_array_constructor, 1,
                                    ctx->class_proto[JS_CLASS_ARRAY]);
+    ctx->array_ctor = JS_DupValue(ctx, obj);
     JS_SetPropertyFunctionList(ctx, obj, js_array_funcs,
                                countof(js_array_funcs));
 
@@ -49004,6 +49504,12 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
                                js_array_iterator_proto_funcs,
                                countof(js_array_iterator_proto_funcs));
 
+    /* parseFloat and parseInteger must be defined before Number
+       because of the Number.parseFloat and Number.parseInteger
+       aliases */
+    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs,
+                               countof(js_global_funcs));
+
     /* Number */
     ctx->class_proto[JS_CLASS_NUMBER] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
                                                                JS_CLASS_NUMBER);
@@ -49093,9 +49599,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
                            JS_DupValue(ctx, ctx->eval_obj),
                            JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
 
-    JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs,
-                               countof(js_global_funcs));
-
     JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,
                            JS_DupValue(ctx, ctx->global_obj),
                            JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
index abf4d83bfcd81e348ba03d5a4282564770643fe9..f6bfdb022e420650487b4b365f1f3ebb905b20f1 100644 (file)
--- a/quickjs.h
+++ b/quickjs.h
@@ -333,6 +333,7 @@ JSRuntime *JS_NewRuntime(void);
 void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
 void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
 void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
+void JS_SetMaxStackSize(JSRuntime *rt, size_t stack_size);
 JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
 void JS_FreeRuntime(JSRuntime *rt);
 void *JS_GetRuntimeOpaque(JSRuntime *rt);
@@ -344,10 +345,10 @@ JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
 
 JSContext *JS_NewContext(JSRuntime *rt);
 void JS_FreeContext(JSContext *s);
+JSContext *JS_DupContext(JSContext *ctx);
 void *JS_GetContextOpaque(JSContext *ctx);
 void JS_SetContextOpaque(JSContext *ctx, void *opaque);
 JSRuntime *JS_GetRuntime(JSContext *ctx);
-void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size);
 void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
 JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
 
@@ -673,7 +674,7 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
 
 int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
 int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
-static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
+static inline int JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
 {
     return JS_ToInt32(ctx, (int32_t*)pres, val);
 }
index 8eeecd1f631b97c1096a6c5f487840472dc62ce0..d5b6e815be4fd0944793ce18f68069ddd49a1da3 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * ECMA Test 262 Runner for QuickJS
  * 
- * Copyright (c) 2017-2018 Fabrice Bellard
- * Copyright (c) 2017-2018 Charlie Gordon
+ * Copyright (c) 2017-2020 Fabrice Bellard
+ * Copyright (c) 2017-2020 Charlie Gordon
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -41,8 +41,6 @@
 
 /* enable test262 thread support to test SharedArrayBuffer and Atomics */
 #define CONFIG_AGENT
-/* cross-realm tests (not supported yet) */
-//#define CONFIG_REALM
 
 #define CMD_NAME "run-test262"
 
@@ -730,18 +728,20 @@ static JSValue js_new_agent(JSContext *ctx)
 }
 #endif
 
-#ifdef CONFIG_REALM
 static JSValue js_createRealm(JSContext *ctx, JSValue this_val,
                               int argc, JSValue *argv)
 {
     JSContext *ctx1;
-    /* XXX: the context is not freed, need a refcount */
+    JSValue ret;
+    
     ctx1 = JS_NewContext(JS_GetRuntime(ctx));
     if (!ctx1)
         return JS_ThrowOutOfMemory(ctx);
-    return add_helpers1(ctx1);
+    ret = add_helpers1(ctx1);
+    /* ctx1 has a refcount so it stays alive */
+    JS_FreeContext(ctx1);
+    return ret;
 }
-#endif
 
 static JSValue add_helpers1(JSContext *ctx)
 {
@@ -770,12 +770,9 @@ static JSValue add_helpers1(JSContext *ctx)
 
     JS_SetPropertyStr(ctx, obj262, "global",
                       JS_DupValue(ctx, global_obj));
-
-#ifdef CONFIG_REALM
     JS_SetPropertyStr(ctx, obj262, "createRealm",
                       JS_NewCFunction(ctx, js_createRealm,
                                       "createRealm", 0));
-#endif
 
     JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262));
     
index b6d385253f714d029b13f7331901fe55d4e9476f..4971dd8945e13c6fdff7be172492b17654159b8d 100644 (file)
@@ -48,7 +48,7 @@ testdir=test262/test
 # list the features that are included
 # skipped features are tagged as such to avoid warnings
 
-AggregateError=skip
+AggregateError
 Array.prototype.flat
 Array.prototype.flatMap
 Array.prototype.flatten
@@ -70,7 +70,7 @@ class-static-methods-private
 coalesce-expression
 computed-property-names
 const
-cross-realm=skip
+cross-realm
 DataView
 DataView.prototype.getFloat32
 DataView.prototype.getFloat64
@@ -102,6 +102,7 @@ Int8Array
 IsHTMLDDA=skip
 json-superset
 let
+logical-assignment-operators=skip
 Map
 new.target
 numeric-separator-literal
@@ -112,6 +113,7 @@ Object.is
 optional-catch-binding
 optional-chaining
 Promise.allSettled
+Promise.any
 Promise.prototype.finally
 Proxy
 proxy-missing-checks
@@ -179,5 +181,8 @@ test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
 #test262/test/built-ins/RegExp/CharacterClassEscapes/
 #test262/test/built-ins/RegExp/property-escapes/
 
+# invalid tests
+test262/test/language/module-code/verify-dfs.js
+
 [tests]
 # list test files or use config.testdir
index 41521ae1ad387d54979cb66babeca1fbc7dcd6a0..024f357d293b6406c30c3fc50792c332ab85c192 100644 (file)
@@ -1,9 +1,15 @@
+test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a ReferenceError
+test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError
+test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. 
+test262/test/built-ins/Proxy/ownKeys/trap-is-undefined-target-is-proxy.js:29: strict mode: Test262Error: Expected [0, length, foo, Symbol()] and [Symbol(), length, foo, 0] to have the same contents. 
 test262/test/language/expressions/arrow-function/eval-var-scope-syntax-err.js:47: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
 test262/test/language/expressions/async-arrow-function/eval-var-scope-syntax-err.js:49: TypeError: $DONE() not called
 test262/test/language/expressions/async-function/named-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
 test262/test/language/expressions/async-function/nameless-eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
 test262/test/language/expressions/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
 test262/test/language/expressions/async-generator/named-eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
+test262/test/language/expressions/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
+test262/test/language/expressions/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
 test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called
 test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called
 test262/test/language/expressions/function/eval-var-scope-syntax-err.js:48: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
@@ -16,7 +22,7 @@ test262/test/language/expressions/optional-chaining/optional-call-preserves-this
 test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: value has no property
 test262/test/language/statements/async-function/eval-var-scope-syntax-err.js:33: TypeError: $DONE() not called
 test262/test/language/statements/async-generator/eval-var-scope-syntax-err.js:28: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
-test262/test/language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-rtrn-close-null.js:81: TypeError: $DONE() not called
-test262/test/language/statements/for-await-of/async-gen-decl-dstr-array-elem-iter-rtrn-close-null.js:81: strict mode: TypeError: $DONE() not called
+test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: SyntaxError: expecting field name
+test262/test/language/statements/class/elements/grammar-private-field-optional-chaining.js:26: strict mode: SyntaxError: expecting field name
 test262/test/language/statements/function/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
 test262/test/language/statements/generators/eval-var-scope-syntax-err.js:49: Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all
index 94a4d2a91babd4e4bad0e2dc3c945aa1274ce60f..54917c955fae9c520f948efee8b9cf4d2de05685 100644 (file)
@@ -214,7 +214,11 @@ function test_os_exec()
     assert(ret, 1);
     
     fds = os.pipe();
-    pid = os.exec(["echo", "hello"], { stdout: fds[1], block: false } );
+    pid = os.exec(["sh", "-c", "echo $FOO"], {
+        stdout: fds[1],
+        block: false,
+        env: { FOO: "hello" },
+    } );
     assert(pid >= 0);
     os.close(fds[1]); /* close the write end (as it is only in the child)  */
     f = std.fdopen(fds[0], "r");