summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO4
-rw-r--r--doc/quickjs.texi11
-rw-r--r--examples/hello_module.js4
-rw-r--r--examples/message.json2
-rw-r--r--libunicode-table.h1
-rw-r--r--libunicode.c20
-rw-r--r--qjs.c2
-rw-r--r--qjsc.c104
-rw-r--r--quickjs-libc.c153
-rw-r--r--quickjs-libc.h8
-rw-r--r--quickjs-opcode.h2
-rw-r--r--quickjs.c553
-rw-r--r--quickjs.h26
-rw-r--r--run-test262.c52
-rw-r--r--test262.conf16
-rw-r--r--test262_errors.txt15
-rw-r--r--tests/assert.js10
-rw-r--r--tests/test262.patch37
-rw-r--r--tests/test_language.js2
-rw-r--r--tests/test_std.js16
-rw-r--r--unicode_gen.c5
21 files changed, 819 insertions, 224 deletions
diff --git a/TODO b/TODO
index 1b02bfb..acbe84a 100644
--- a/TODO
+++ b/TODO
@@ -62,5 +62,5 @@ Optimization ideas:
Test262o: 0/11262 errors, 463 excluded
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
-Result: 58/79202 errors, 1610 excluded, 6738 skipped
-Test262 commit: 27622d764767dcb3778784884022c2c7de5769b8
+Result: 47/79321 errors, 1617 excluded, 6767 skipped
+Test262 commit: 4b5d36ab6ef2f59d0a8902cd383762547a3a74c4
diff --git a/doc/quickjs.texi b/doc/quickjs.texi
index eef00b7..9130b47 100644
--- a/doc/quickjs.texi
+++ b/doc/quickjs.texi
@@ -449,17 +449,20 @@ optional properties:
@item parseExtJSON(str)
- Parse @code{str} using a superset of @code{JSON.parse}. The
- following extensions are accepted:
+ Parse @code{str} using a superset of @code{JSON.parse}. The superset
+ is very close to the JSON5 specification. The following extensions
+ are accepted:
@itemize
@item Single line and multiline comments
@item unquoted properties (ASCII-only Javascript identifiers)
@item trailing comma in array and object definitions
@item single quoted strings
+ @item @code{\v} escape and multi-line strings with trailing @code{\}
@item @code{\f} and @code{\v} are accepted as space characters
- @item leading plus in numbers
- @item octal (@code{0o} prefix) and hexadecimal (@code{0x} prefix) numbers
+ @item leading plus or decimal point in numbers
+ @item hexadecimal (@code{0x} prefix), octal (@code{0o} prefix) and binary (@code{0b} prefix) integers
+ @item @code{NaN} and @code{Infinity} are accepted as numbers
@end itemize
@end table
diff --git a/examples/hello_module.js b/examples/hello_module.js
index 463660f..5d4c78e 100644
--- a/examples/hello_module.js
+++ b/examples/hello_module.js
@@ -1,6 +1,8 @@
-/* example of JS module */
+/* example of JS and JSON modules */
import { fib } from "./fib_module.js";
+import msg from "./message.json";
console.log("Hello World");
console.log("fib(10)=", fib(10));
+console.log("msg=", msg);
diff --git a/examples/message.json b/examples/message.json
new file mode 100644
index 0000000..3b7fe48
--- /dev/null
+++ b/examples/message.json
@@ -0,0 +1,2 @@
+{ "x" : 1, "tab": [ 1, 2, 3 ] }
+
diff --git a/libunicode-table.h b/libunicode-table.h
index 0120ea9..67df6b3 100644
--- a/libunicode-table.h
+++ b/libunicode-table.h
@@ -3130,6 +3130,7 @@ typedef enum {
} UnicodeScriptEnum;
static const char unicode_script_name_table[] =
+ "Unknown,Zzzz" "\0"
"Adlam,Adlm" "\0"
"Ahom,Ahom" "\0"
"Anatolian_Hieroglyphs,Hluw" "\0"
diff --git a/libunicode.c b/libunicode.c
index b4a0206..3791523 100644
--- a/libunicode.c
+++ b/libunicode.c
@@ -1285,8 +1285,6 @@ int unicode_script(CharRange *cr,
script_idx = unicode_find_name(unicode_script_name_table, script_name);
if (script_idx < 0)
return -2;
- /* Note: we remove the "Unknown" Script */
- script_idx += UNICODE_SCRIPT_Unknown + 1;
is_common = (script_idx == UNICODE_SCRIPT_Common ||
script_idx == UNICODE_SCRIPT_Inherited);
@@ -1316,17 +1314,21 @@ int unicode_script(CharRange *cr,
n |= *p++;
n += 96 + (1 << 12);
}
- if (type == 0)
- v = 0;
- else
- v = *p++;
c1 = c + n + 1;
- if (v == script_idx) {
- if (cr_add_interval(cr1, c, c1))
- goto fail;
+ if (type != 0) {
+ v = *p++;
+ if (v == script_idx || script_idx == UNICODE_SCRIPT_Unknown) {
+ if (cr_add_interval(cr1, c, c1))
+ goto fail;
+ }
}
c = c1;
}
+ if (script_idx == UNICODE_SCRIPT_Unknown) {
+ /* Unknown is all the characters outside scripts */
+ if (cr_invert(cr1))
+ goto fail;
+ }
if (is_ext) {
/* add the script extensions */
diff --git a/qjs.c b/qjs.c
index 2eaa9ee..a88e39a 100644
--- a/qjs.c
+++ b/qjs.c
@@ -465,7 +465,7 @@ int main(int argc, char **argv)
}
/* loader for ES6 modules */
- JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
+ JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);
if (dump_unhandled_promise_rejection) {
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker,
diff --git a/qjsc.c b/qjsc.c
index f9e1928..49aa449 100644
--- a/qjsc.c
+++ b/qjsc.c
@@ -170,14 +170,24 @@ static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
fprintf(f, "\n");
}
+typedef enum {
+ CNAME_TYPE_SCRIPT,
+ CNAME_TYPE_MODULE,
+ CNAME_TYPE_JSON_MODULE,
+} CNameTypeEnum;
+
static void output_object_code(JSContext *ctx,
FILE *fo, JSValueConst obj, const char *c_name,
- BOOL load_only)
+ CNameTypeEnum c_name_type)
{
uint8_t *out_buf;
size_t out_buf_len;
int flags;
- flags = JS_WRITE_OBJ_BYTECODE;
+
+ if (c_name_type == CNAME_TYPE_JSON_MODULE)
+ flags = 0;
+ else
+ flags = JS_WRITE_OBJ_BYTECODE;
if (byte_swap)
flags |= JS_WRITE_OBJ_BSWAP;
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
@@ -186,7 +196,7 @@ static void output_object_code(JSContext *ctx,
exit(1);
}
- namelist_add(&cname_list, c_name, NULL, load_only);
+ namelist_add(&cname_list, c_name, NULL, c_name_type);
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
c_name, (unsigned int)out_buf_len);
@@ -227,7 +237,8 @@ static void find_unique_cname(char *cname, size_t cname_size)
}
JSModuleDef *jsc_module_loader(JSContext *ctx,
- const char *module_name, void *opaque)
+ const char *module_name, void *opaque,
+ JSValueConst attributes)
{
JSModuleDef *m;
namelist_entry_t *e;
@@ -249,9 +260,9 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
} else {
size_t buf_len;
uint8_t *buf;
- JSValue func_val;
char cname[1024];
-
+ int res;
+
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
@@ -259,21 +270,59 @@ JSModuleDef *jsc_module_loader(JSContext *ctx,
return NULL;
}
- /* compile the module */
- func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
- JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
- js_free(ctx, buf);
- if (JS_IsException(func_val))
- return NULL;
- get_c_name(cname, sizeof(cname), module_name);
- if (namelist_find(&cname_list, cname)) {
- find_unique_cname(cname, sizeof(cname));
- }
- output_object_code(ctx, outfile, func_val, cname, TRUE);
+ res = js_module_test_json(ctx, attributes);
+ if (has_suffix(module_name, ".json") || res > 0) {
+ /* compile as JSON or JSON5 depending on "type" */
+ JSValue val;
+ int flags;
+
+ if (res == 2)
+ flags = JS_PARSE_JSON_EXT;
+ else
+ flags = 0;
+ val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags);
+ js_free(ctx, buf);
+ if (JS_IsException(val))
+ return NULL;
+ /* create a dummy module */
+ m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
+ if (!m) {
+ JS_FreeValue(ctx, val);
+ return NULL;
+ }
+
+ get_c_name(cname, sizeof(cname), module_name);
+ if (namelist_find(&cname_list, cname)) {
+ find_unique_cname(cname, sizeof(cname));
+ }
+
+ /* output the module name */
+ fprintf(outfile, "static const uint8_t %s_module_name[] = {\n",
+ cname);
+ dump_hex(outfile, (const uint8_t *)module_name, strlen(module_name) + 1);
+ fprintf(outfile, "};\n\n");
- /* the module is already referenced, so we must free it */
- m = JS_VALUE_GET_PTR(func_val);
- JS_FreeValue(ctx, func_val);
+ output_object_code(ctx, outfile, val, cname, CNAME_TYPE_JSON_MODULE);
+ JS_FreeValue(ctx, val);
+ } else {
+ JSValue func_val;
+
+ /* compile the module */
+ func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
+ JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
+ js_free(ctx, buf);
+ if (JS_IsException(func_val))
+ return NULL;
+ get_c_name(cname, sizeof(cname), module_name);
+ if (namelist_find(&cname_list, cname)) {
+ find_unique_cname(cname, sizeof(cname));
+ }
+ output_object_code(ctx, outfile, func_val, cname, CNAME_TYPE_MODULE);
+
+ /* the module is already referenced, so we must free it */
+ m = JS_VALUE_GET_PTR(func_val);
+ JS_FreeValue(ctx, func_val);
+ }
}
return m;
}
@@ -314,7 +363,7 @@ static void compile_file(JSContext *ctx, FILE *fo,
} else {
get_c_name(c_name, sizeof(c_name), filename);
}
- output_object_code(ctx, fo, obj, c_name, FALSE);
+ output_object_code(ctx, fo, obj, c_name, CNAME_TYPE_SCRIPT);
JS_FreeValue(ctx, obj);
}
@@ -709,7 +758,7 @@ int main(int argc, char **argv)
JS_SetStripInfo(rt, strip_flags);
/* loader for ES6 modules */
- JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
+ JS_SetModuleLoaderFunc2(rt, NULL, jsc_module_loader, NULL, NULL);
fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n"
"\n"
@@ -732,7 +781,7 @@ int main(int argc, char **argv)
}
for(i = 0; i < dynamic_module_list.count; i++) {
- if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
+ if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL, JS_UNDEFINED)) {
fprintf(stderr, "Could not load dynamic module '%s'\n",
dynamic_module_list.array[i].name);
exit(1);
@@ -770,9 +819,12 @@ int main(int argc, char **argv)
}
for(i = 0; i < cname_list.count; i++) {
namelist_entry_t *e = &cname_list.array[i];
- if (e->flags) {
+ if (e->flags == CNAME_TYPE_MODULE) {
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n",
e->name, e->name);
+ } else if (e->flags == CNAME_TYPE_JSON_MODULE) {
+ fprintf(fo, " js_std_eval_binary_json_module(ctx, %s, %s_size, (const char *)%s_module_name);\n",
+ e->name, e->name, e->name);
}
}
fprintf(fo,
@@ -788,7 +840,7 @@ int main(int argc, char **argv)
/* add the module loader if necessary */
if (feature_bitmap & (1 << FE_MODULE_LOADER)) {
- fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
+ fprintf(fo, " JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);\n");
}
fprintf(fo,
@@ -797,7 +849,7 @@ int main(int argc, char **argv)
for(i = 0; i < cname_list.count; i++) {
namelist_entry_t *e = &cname_list.array[i];
- if (!e->flags) {
+ if (e->flags == CNAME_TYPE_SCRIPT) {
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
e->name, e->name);
}
diff --git a/quickjs-libc.c b/quickjs-libc.c
index 03ce012..10a7d00 100644
--- a/quickjs-libc.c
+++ b/quickjs-libc.c
@@ -591,17 +591,101 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
return 0;
}
-JSModuleDef *js_module_loader(JSContext *ctx,
- const char *module_name, void *opaque)
+static int json_module_init(JSContext *ctx, JSModuleDef *m)
+{
+ JSValue val;
+ val = JS_GetModulePrivateValue(ctx, m);
+ JS_SetModuleExport(ctx, m, "default", val);
+ return 0;
+}
+
+static JSModuleDef *create_json_module(JSContext *ctx, const char *module_name, JSValue val)
{
JSModuleDef *m;
+ m = JS_NewCModule(ctx, module_name, json_module_init);
+ if (!m) {
+ JS_FreeValue(ctx, val);
+ return NULL;
+ }
+ /* only export the "default" symbol which will contain the JSON object */
+ JS_AddModuleExport(ctx, m, "default");
+ JS_SetModulePrivateValue(ctx, m, val);
+ return m;
+}
+
+/* in order to conform with the specification, only the keys should be
+ tested and not the associated values. */
+int js_module_check_attributes(JSContext *ctx, void *opaque,
+ JSValueConst attributes)
+{
+ JSPropertyEnum *tab;
+ uint32_t i, len;
+ int ret;
+ const char *cstr;
+ size_t cstr_len;
+
+ if (JS_GetOwnPropertyNames(ctx, &tab, &len, attributes, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK))
+ return -1;
+ ret = 0;
+ for(i = 0; i < len; i++) {
+ cstr = JS_AtomToCStringLen(ctx, &cstr_len, tab[i].atom);
+ if (!cstr) {
+ ret = -1;
+ break;
+ }
+ if (!(cstr_len == 4 && !memcmp(cstr, "type", cstr_len))) {
+ JS_ThrowTypeError(ctx, "import attribute '%s' is not supported", cstr);
+ ret = -1;
+ }
+ JS_FreeCString(ctx, cstr);
+ if (ret)
+ break;
+ }
+ JS_FreePropertyEnum(ctx, tab, len);
+ return ret;
+}
+/* return > 0 if the attributes indicate a JSON module */
+int js_module_test_json(JSContext *ctx, JSValueConst attributes)
+{
+ JSValue str;
+ const char *cstr;
+ size_t len;
+ BOOL res;
+
+ if (JS_IsUndefined(attributes))
+ return FALSE;
+ str = JS_GetPropertyStr(ctx, attributes, "type");
+ if (!JS_IsString(str))
+ return FALSE;
+ cstr = JS_ToCStringLen(ctx, &len, str);
+ JS_FreeValue(ctx, str);
+ if (!cstr)
+ return FALSE;
+ /* XXX: raise an error if unknown type ? */
+ if (len == 4 && !memcmp(cstr, "json", len)) {
+ res = 1;
+ } else if (len == 5 && !memcmp(cstr, "json5", len)) {
+ res = 2;
+ } else {
+ res = 0;
+ }
+ JS_FreeCString(ctx, cstr);
+ return res;
+}
+
+JSModuleDef *js_module_loader(JSContext *ctx,
+ const char *module_name, void *opaque,
+ JSValueConst attributes)
+{
+ JSModuleDef *m;
+ int res;
+
if (has_suffix(module_name, ".so")) {
m = js_module_loader_so(ctx, module_name);
} else {
size_t buf_len;
uint8_t *buf;
- JSValue func_val;
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
@@ -609,18 +693,36 @@ JSModuleDef *js_module_loader(JSContext *ctx,
module_name);
return NULL;
}
-
- /* compile the module */
- func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
- JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
- js_free(ctx, buf);
- if (JS_IsException(func_val))
- return NULL;
- /* XXX: could propagate the exception */
- js_module_set_import_meta(ctx, func_val, TRUE, FALSE);
- /* the module is already referenced, so we must free it */
- m = JS_VALUE_GET_PTR(func_val);
- JS_FreeValue(ctx, func_val);
+ res = js_module_test_json(ctx, attributes);
+ if (has_suffix(module_name, ".json") || res > 0) {
+ /* compile as JSON or JSON5 depending on "type" */
+ JSValue val;
+ int flags;
+ if (res == 2)
+ flags = JS_PARSE_JSON_EXT;
+ else
+ flags = 0;
+ val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags);
+ js_free(ctx, buf);
+ if (JS_IsException(val))
+ return NULL;
+ m = create_json_module(ctx, module_name, val);
+ if (!m)
+ return NULL;
+ } else {
+ JSValue func_val;
+ /* compile the module */
+ func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
+ JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
+ js_free(ctx, buf);
+ if (JS_IsException(func_val))
+ return NULL;
+ /* XXX: could propagate the exception */
+ js_module_set_import_meta(ctx, func_val, TRUE, FALSE);
+ /* the module is already referenced, so we must free it */
+ m = JS_VALUE_GET_PTR(func_val);
+ JS_FreeValue(ctx, func_val);
+ }
}
return m;
}
@@ -3478,7 +3580,7 @@ static void *worker_func(void *opaque)
JS_SetStripInfo(rt, args->strip_flags);
js_std_init_handlers(rt);
- JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
+ JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);
/* set the pipe to communicate with the parent */
ts = JS_GetRuntimeOpaque(rt);
@@ -4221,3 +4323,22 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
JS_FreeValue(ctx, val);
}
}
+
+void js_std_eval_binary_json_module(JSContext *ctx,
+ const uint8_t *buf, size_t buf_len,
+ const char *module_name)
+{
+ JSValue obj;
+ JSModuleDef *m;
+
+ obj = JS_ReadObject(ctx, buf, buf_len, 0);
+ if (JS_IsException(obj))
+ goto exception;
+ m = create_json_module(ctx, module_name, obj);
+ if (!m) {
+ exception:
+ js_std_dump_error(ctx);
+ exit(1);
+ }
+}
+
diff --git a/quickjs-libc.h b/quickjs-libc.h
index 850484f..5c8301b 100644
--- a/quickjs-libc.h
+++ b/quickjs-libc.h
@@ -44,10 +44,16 @@ void js_std_dump_error(JSContext *ctx);
uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
JS_BOOL use_realpath, JS_BOOL is_main);
+int js_module_test_json(JSContext *ctx, JSValueConst attributes);
+int js_module_check_attributes(JSContext *ctx, void *opaque, JSValueConst attributes);
JSModuleDef *js_module_loader(JSContext *ctx,
- const char *module_name, void *opaque);
+ const char *module_name, void *opaque,
+ JSValueConst attributes);
void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
int flags);
+void js_std_eval_binary_json_module(JSContext *ctx,
+ const uint8_t *buf, size_t buf_len,
+ const char *module_name);
void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
JSValueConst reason,
JS_BOOL is_handled, void *opaque);
diff --git a/quickjs-opcode.h b/quickjs-opcode.h
index e721e17..814a7cb 100644
--- a/quickjs-opcode.h
+++ b/quickjs-opcode.h
@@ -121,7 +121,7 @@ DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
bytecode string */
DEF( get_super, 1, 1, 1, none)
-DEF( import, 1, 1, 1, none) /* dynamic module import */
+DEF( import, 1, 2, 1, none) /* dynamic module import */
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
diff --git a/quickjs.c b/quickjs.c
index eb94306..34346f4 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -280,7 +280,12 @@ struct JSRuntime {
struct list_head job_list; /* list of JSJobEntry.link */
JSModuleNormalizeFunc *module_normalize_func;
- JSModuleLoaderFunc *module_loader_func;
+ BOOL module_loader_has_attr;
+ union {
+ JSModuleLoaderFunc *module_loader_func;
+ JSModuleLoaderFunc2 *module_loader_func2;
+ } u;
+ JSModuleCheckSupportedImportAttributes *module_check_attrs;
void *module_loader_opaque;
/* timestamp for internal use in module evaluation */
int64_t module_async_evaluation_next_timestamp;
@@ -756,6 +761,7 @@ typedef struct {
typedef struct JSReqModuleEntry {
JSAtom module_name;
JSModuleDef *module; /* used using resolution */
+ JSValue attributes; /* JS_UNDEFINED or an object contains the attributes as key/value */
} JSReqModuleEntry;
typedef enum JSExportTypeEnum {
@@ -844,6 +850,7 @@ struct JSModuleDef {
BOOL eval_has_exception : 8;
JSValue eval_exception;
JSValue meta_obj; /* for import.meta */
+ JSValue private_value; /* private value for C modules */
};
typedef struct JSJobEntry {
@@ -1217,7 +1224,7 @@ 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 JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options);
static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref);
static JSValue js_new_promise_capability(JSContext *ctx,
JSValue *resolving_funcs,
@@ -5345,6 +5352,10 @@ static JSValue JS_NewCFunction3(JSContext *ctx, JSCFunction *func,
if (!name)
name = "";
name_atom = JS_NewAtom(ctx, name);
+ if (name_atom == JS_ATOM_NULL) {
+ JS_FreeValue(ctx, func_obj);
+ return JS_EXCEPTION;
+ }
js_function_set_properties(ctx, func_obj, name_atom, length);
JS_FreeAtom(ctx, name_atom);
return func_obj;
@@ -6875,6 +6886,9 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
const char *str1;
JSObject *p;
+ if (!JS_IsObject(error_obj))
+ return; /* protection in the out of memory case */
+
js_dbuf_init(ctx, &dbuf);
if (filename) {
dbuf_printf(&dbuf, " at %s", filename);
@@ -6882,13 +6896,17 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_obj,
dbuf_printf(&dbuf, ":%d:%d", line_num, col_num);
dbuf_putc(&dbuf, '\n');
str = JS_NewString(ctx, filename);
+ if (JS_IsException(str))
+ return;
/* Note: SpiderMonkey does that, could update once there is a standard */
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num),
- JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
+ if (JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_fileName, str,
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 ||
+ JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_lineNumber, JS_NewInt32(ctx, line_num),
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0 ||
+ JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_columnNumber, JS_NewInt32(ctx, col_num),
+ JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE) < 0) {
+ return;
+ }
}
for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
if (sf->js_mode & JS_MODE_BACKTRACE_BARRIER)
@@ -6973,9 +6991,9 @@ static JSValue JS_ThrowError2(JSContext *ctx, JSErrorEnum error_num,
JS_DefinePropertyValue(ctx, obj, JS_ATOM_message,
JS_NewString(ctx, buf),
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
- }
- if (add_backtrace) {
- build_backtrace(ctx, obj, NULL, 0, 0, 0);
+ if (add_backtrace) {
+ build_backtrace(ctx, obj, NULL, 0, 0, 0);
+ }
}
ret = JS_Throw(ctx, obj);
return ret;
@@ -8447,6 +8465,8 @@ JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
JSValue ret;
atom = JS_NewAtom(ctx, prop);
+ if (atom == JS_ATOM_NULL)
+ return JS_EXCEPTION;
ret = JS_GetProperty(ctx, this_obj, atom);
JS_FreeAtom(ctx, atom);
return ret;
@@ -9266,6 +9286,10 @@ int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
int ret;
atom = JS_NewAtom(ctx, prop);
+ if (atom == JS_ATOM_NULL) {
+ JS_FreeValue(ctx, val);
+ return -1;
+ }
ret = JS_SetPropertyInternal(ctx, this_obj, atom, val, this_obj, JS_PROP_THROW);
JS_FreeAtom(ctx, atom);
return ret;
@@ -9822,6 +9846,10 @@ int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
JSAtom atom;
int ret;
atom = JS_NewAtom(ctx, prop);
+ if (atom == JS_ATOM_NULL) {
+ JS_FreeValue(ctx, val);
+ return -1;
+ }
ret = JS_DefinePropertyValue(ctx, this_obj, atom, val, flags);
JS_FreeAtom(ctx, atom);
return ret;
@@ -10535,6 +10563,15 @@ static inline js_limb_t js_limb_clz(js_limb_t a)
}
#endif
+/* handle a = 0 too */
+static inline js_limb_t js_limb_safe_clz(js_limb_t a)
+{
+ if (a == 0)
+ return JS_LIMB_BITS;
+ else
+ return js_limb_clz(a);
+}
+
static js_limb_t mp_add(js_limb_t *res, const js_limb_t *op1, const js_limb_t *op2,
js_limb_t n, js_limb_t carry)
{
@@ -11883,7 +11920,7 @@ static JSValue js_bigint_to_string1(JSContext *ctx, JSValueConst val, int radix)
r = tmp;
}
log2_radix = 31 - clz32(radix); /* floor(log2(radix)) */
- n_bits = r->len * JS_LIMB_BITS - js_limb_clz(r->tab[r->len - 1]);
+ n_bits = r->len * JS_LIMB_BITS - js_limb_safe_clz(r->tab[r->len - 1]);
/* n_digits is exact only if radix is a power of
two. Otherwise it is >= the exact number of digits */
n_digits = (n_bits + log2_radix - 1) / log2_radix;
@@ -17383,10 +17420,12 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
{
JSValue val;
sf->cur_pc = pc;
- val = js_dynamic_import(ctx, sp[-1]);
+ val = js_dynamic_import(ctx, sp[-2], sp[-1]);
if (JS_IsException(val))
goto exception;
+ JS_FreeValue(ctx, sp[-2]);
JS_FreeValue(ctx, sp[-1]);
+ sp--;
sp[-1] = val;
}
BREAK;
@@ -20962,6 +21001,7 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
{
uint32_t c;
StringBuffer b_s, *b = &b_s;
+ JSValue str;
/* p points to the first byte of the template part */
if (string_buffer_init(s->ctx, b, 32))
@@ -21004,9 +21044,12 @@ static __exception int js_parse_template_part(JSParseState *s, const uint8_t *p)
if (string_buffer_putc(b, c))
goto fail;
}
+ str = string_buffer_end(b);
+ if (JS_IsException(str))
+ return -1;
s->token.val = TOK_TEMPLATE;
s->token.u.str.sep = c;
- s->token.u.str.str = string_buffer_end(b);
+ s->token.u.str.str = str;
s->buf_ptr = p;
return 0;
@@ -21025,7 +21068,8 @@ static __exception int js_parse_string(JSParseState *s, int sep,
uint32_t c;
StringBuffer b_s, *b = &b_s;
const uint8_t *p_escape;
-
+ JSValue str;
+
/* string */
if (string_buffer_init(s->ctx, b, 32))
goto fail;
@@ -21132,9 +21176,12 @@ static __exception int js_parse_string(JSParseState *s, int sep,
if (string_buffer_putc(b, c))
goto fail;
}
+ str = string_buffer_end(b);
+ if (JS_IsException(str))
+ return -1;
token->val = TOK_STRING;
token->u.str.sep = c;
- token->u.str.str = string_buffer_end(b);
+ token->u.str.str = str;
*pp = p;
return 0;
@@ -21162,6 +21209,7 @@ static __exception int js_parse_regexp(JSParseState *s)
StringBuffer b_s, *b = &b_s;
StringBuffer b2_s, *b2 = &b2_s;
uint32_t c;
+ JSValue body_str, flags_str;
p = s->buf_ptr;
p++;
@@ -21243,9 +21291,17 @@ static __exception int js_parse_regexp(JSParseState *s)
p = p_next;
}
+ body_str = string_buffer_end(b);
+ flags_str = string_buffer_end(b2);
+ if (JS_IsException(body_str) ||
+ JS_IsException(flags_str)) {
+ JS_FreeValue(s->ctx, body_str);
+ JS_FreeValue(s->ctx, flags_str);
+ return -1;
+ }
s->token.val = TOK_REGEXP;
- s->token.u.regexp.body = string_buffer_end(b);
- s->token.u.regexp.flags = string_buffer_end(b2);
+ s->token.u.regexp.body = body_str;
+ s->token.u.regexp.flags = flags_str;
s->buf_ptr = p;
return 0;
fail:
@@ -21815,6 +21871,7 @@ static __exception int next_token(JSParseState *s)
}
/* 'c' is the first character. Return JS_ATOM_NULL in case of error */
+/* XXX: accept unicode identifiers as JSON5 ? */
static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
{
const uint8_t *p;
@@ -21890,11 +21947,22 @@ static int json_parse_string(JSParseState *s, const uint8_t **pp, int sep)
c = (c << 4) | h;
}
break;
+ case '\n':
+ if (s->ext_json)
+ continue;
+ goto bad_escape;
+ case 'v':
+ if (s->ext_json) {
+ c = '\v';
+ break;
+ }
+ goto bad_escape;
default:
if (c == sep)
break;
if (p > s->buf_end)
goto end_of_input;
+ bad_escape:
js_parse_error_pos(s, p - 1, "Bad escaped character");
goto fail;
}
@@ -21934,8 +22002,23 @@ static int json_parse_number(JSParseState *s, const uint8_t **pp)
if (*p == '+' || *p == '-')
p++;
- if (!is_digit(*p))
- return js_parse_error_pos(s, p, "Unexpected token '%c'", *p_start);
+ if (!is_digit(*p)) {
+ if (s->ext_json) {
+ if (strstart((const char *)p, "Infinity", (const char **)&p)) {
+ d = 1.0 / 0.0;
+ if (*p_start == '-')
+ d = -d;
+ goto done;
+ } else if (strstart((const char *)p, "NaN", (const char **)&p)) {
+ d = NAN;
+ goto done;
+ } else if (*p != '.') {
+ goto unexpected_token;
+ }
+ } else {
+ goto unexpected_token;
+ }
+ }
if (p[0] == '0') {
if (s->ext_json) {
@@ -21953,8 +22036,10 @@ static int json_parse_number(JSParseState *s, const uint8_t **pp)
}
if (radix != 10) {
/* prefix is present */
- if (to_digit(*p) >= radix)
+ if (to_digit(*p) >= radix) {
+ unexpected_token:
return js_parse_error_pos(s, p, "Unexpected token '%c'", *p);
+ }
d = js_atod((const char *)p_start, (const char **)&p, 0,
JS_ATOD_INT_ONLY | JS_ATOD_ACCEPT_BIN_OCT, &atod_mem);
goto done;
@@ -22113,7 +22198,6 @@ static __exception int json_next_token(JSParseState *s)
case 'Y': case 'Z':
case '_':
case '$':
- /* identifier : only pure ascii characters are accepted */
p++;
atom = json_parse_ident(s, &p, c);
if (atom == JS_ATOM_NULL)
@@ -22124,17 +22208,16 @@ static __exception int json_next_token(JSParseState *s)
s->token.val = TOK_IDENT;
break;
case '+':
- if (!s->ext_json || !is_digit(p[1]))
+ if (!s->ext_json)
goto def_token;
goto parse_number;
- case '0':
- if (is_digit(p[1]))
+ case '.':
+ if (s->ext_json && is_digit(p[1]))
+ goto parse_number;
+ else
goto def_token;
- goto parse_number;
case '-':
- if (!is_digit(p[1]))
- goto def_token;
- goto parse_number;
+ case '0':
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8':
case '9':
@@ -22326,7 +22409,7 @@ BOOL JS_DetectModule(const char *input, size_t input_len)
}
static inline int get_prev_opcode(JSFunctionDef *fd) {
- if (fd->last_opcode_pos < 0)
+ if (fd->last_opcode_pos < 0 || dbuf_error(&fd->byte_code))
return OP_invalid;
else
return fd->byte_code.buf[fd->last_opcode_pos];
@@ -22391,7 +22474,11 @@ static void emit_op(JSParseState *s, uint8_t val)
static void emit_atom(JSParseState *s, JSAtom name)
{
- emit_u32(s, JS_DupAtom(s->ctx, name));
+ DynBuf *bc = &s->cur_func->byte_code;
+ if (dbuf_realloc(bc, bc->size + 4))
+ return; /* not enough memory : don't duplicate the atom */
+ put_u32(bc->buf + bc->size, JS_DupAtom(s->ctx, name));
+ bc->size += 4;
}
static int update_label(JSFunctionDef *s, int label, int delta)
@@ -22405,29 +22492,33 @@ static int update_label(JSFunctionDef *s, int label, int delta)
return ls->ref_count;
}
-static int new_label_fd(JSFunctionDef *fd, int label)
+static int new_label_fd(JSFunctionDef *fd)
{
+ int label;
LabelSlot *ls;
- if (label < 0) {
- if (js_resize_array(fd->ctx, (void *)&fd->label_slots,
- sizeof(fd->label_slots[0]),
- &fd->label_size, fd->label_count + 1))
- return -1;
- label = fd->label_count++;
- ls = &fd->label_slots[label];
- ls->ref_count = 0;
- ls->pos = -1;
- ls->pos2 = -1;
- ls->addr = -1;
- ls->first_reloc = NULL;
- }
+ if (js_resize_array(fd->ctx, (void *)&fd->label_slots,
+ sizeof(fd->label_slots[0]),
+ &fd->label_size, fd->label_count + 1))
+ return -1;
+ label = fd->label_count++;
+ ls = &fd->label_slots[label];
+ ls->ref_count = 0;
+ ls->pos = -1;
+ ls->pos2 = -1;
+ ls->addr = -1;
+ ls->first_reloc = NULL;
return label;
}
static int new_label(JSParseState *s)
{
- return new_label_fd(s->cur_func, -1);
+ int label;
+ label = new_label_fd(s->cur_func);
+ if (unlikely(label < 0)) {
+ dbuf_set_error(&s->cur_func->byte_code);
+ }
+ return label;
}
/* don't update the last opcode and don't emit line number info */
@@ -22455,8 +22546,11 @@ static int emit_label(JSParseState *s, int label)
static int emit_goto(JSParseState *s, int opcode, int label)
{
if (js_is_live_code(s)) {
- if (label < 0)
+ if (label < 0) {
label = new_label(s);
+ if (label < 0)
+ return -1;
+ }
emit_op(s, opcode);
emit_u32(s, label);
s->cur_func->label_slots[label].ref_count++;
@@ -24497,6 +24591,8 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
switch(opcode) {
case OP_scope_get_var:
label = new_label(s);
+ if (label < 0)
+ return -1;
emit_op(s, OP_scope_make_ref);
emit_atom(s, name);
emit_u32(s, label);
@@ -24529,6 +24625,8 @@ static __exception int get_lvalue(JSParseState *s, int *popcode, int *pscope,
switch(opcode) {
case OP_scope_get_var:
label = new_label(s);
+ if (label < 0)
+ return -1;
emit_op(s, OP_scope_make_ref);
emit_atom(s, name);
emit_u32(s, label);
@@ -25538,6 +25636,23 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
return js_parse_error(s, "invalid use of 'import()'");
if (js_parse_assign_expr(s))
return -1;
+ if (s->token.val == ',') {
+ if (next_token(s))
+ return -1;
+ if (s->token.val != ')') {
+ if (js_parse_assign_expr(s))
+ return -1;
+ /* accept a trailing comma */
+ if (s->token.val == ',') {
+ if (next_token(s))
+ return -1;
+ }
+ } else {
+ emit_op(s, OP_undefined);
+ }
+ } else {
+ emit_op(s, OP_undefined);
+ }
if (js_parse_expect(s, ')'))
return -1;
emit_op(s, OP_import);
@@ -25554,6 +25669,8 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
BOOL has_optional_chain = FALSE;
if (s->token.val == TOK_QUESTION_MARK_DOT) {
+ if ((parse_flags & PF_POSTFIX_CALL) == 0)
+ return js_parse_error(s, "new keyword cannot be used with an optional chain");
op_token_ptr = s->token.ptr;
/* optional chaining */
if (next_token(s))
@@ -28115,6 +28232,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
m->promise = JS_UNDEFINED;
m->resolving_funcs[0] = JS_UNDEFINED;
m->resolving_funcs[1] = JS_UNDEFINED;
+ m->private_value = JS_UNDEFINED;
list_add_tail(&m->link, &ctx->loaded_modules);
return m;
}
@@ -28124,6 +28242,11 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
{
int i;
+ for(i = 0; i < m->req_module_entries_count; i++) {
+ JSReqModuleEntry *rme = &m->req_module_entries[i];
+ JS_MarkValue(rt, rme->attributes, mark_func);
+ }
+
for(i = 0; i < m->export_entries_count; i++) {
JSExportEntry *me = &m->export_entries[i];
if (me->export_type == JS_EXPORT_TYPE_LOCAL &&
@@ -28139,6 +28262,7 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
JS_MarkValue(rt, m->promise, mark_func);
JS_MarkValue(rt, m->resolving_funcs[0], mark_func);
JS_MarkValue(rt, m->resolving_funcs[1], mark_func);
+ JS_MarkValue(rt, m->private_value, mark_func);
}
static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
@@ -28150,6 +28274,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
JS_FreeAtom(ctx, rme->module_name);
+ JS_FreeValue(ctx, rme->attributes);
}
js_free(ctx, m->req_module_entries);
@@ -28178,6 +28303,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m)
JS_FreeValue(ctx, m->promise);
JS_FreeValue(ctx, m->resolving_funcs[0]);
JS_FreeValue(ctx, m->resolving_funcs[1]);
+ JS_FreeValue(ctx, m->private_value);
list_del(&m->link);
js_free(ctx, m);
}
@@ -28186,14 +28312,6 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
JSAtom module_name)
{
JSReqModuleEntry *rme;
- int i;
-
- /* no need to add the module request if it is already present */
- for(i = 0; i < m->req_module_entries_count; i++) {
- rme = &m->req_module_entries[i];
- if (rme->module_name == module_name)
- return i;
- }
if (js_resize_array(ctx, (void **)&m->req_module_entries,
sizeof(JSReqModuleEntry),
@@ -28203,7 +28321,8 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
rme = &m->req_module_entries[m->req_module_entries_count++];
rme->module_name = JS_DupAtom(ctx, module_name);
rme->module = NULL;
- return i;
+ rme->attributes = JS_UNDEFINED;
+ return m->req_module_entries_count - 1;
}
static JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m,
@@ -28283,6 +28402,8 @@ JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
if (name == JS_ATOM_NULL)
return NULL;
m = js_new_module_def(ctx, name);
+ if (!m)
+ return NULL;
m->init_func = func;
return m;
}
@@ -28322,12 +28443,38 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
return -1;
}
+int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val)
+{
+ set_value(ctx, &m->private_value, val);
+ return 0;
+}
+
+JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m)
+{
+ return JS_DupValue(ctx, m->private_value);
+}
+
void JS_SetModuleLoaderFunc(JSRuntime *rt,
JSModuleNormalizeFunc *module_normalize,
JSModuleLoaderFunc *module_loader, void *opaque)
{
rt->module_normalize_func = module_normalize;
- rt->module_loader_func = module_loader;
+ rt->module_loader_has_attr = FALSE;
+ rt->u.module_loader_func = module_loader;
+ rt->module_check_attrs = NULL;
+ rt->module_loader_opaque = opaque;
+}
+
+void JS_SetModuleLoaderFunc2(JSRuntime *rt,
+ JSModuleNormalizeFunc *module_normalize,
+ JSModuleLoaderFunc2 *module_loader,
+ JSModuleCheckSupportedImportAttributes *module_check_attrs,
+ void *opaque)
+{
+ rt->module_normalize_func = module_normalize;
+ rt->module_loader_has_attr = TRUE;
+ rt->u.module_loader_func2 = module_loader;
+ rt->module_check_attrs = module_check_attrs;
rt->module_loader_opaque = opaque;
}
@@ -28408,7 +28555,8 @@ static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name)
/* return NULL in case of exception (e.g. module could not be loaded) */
static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
const char *base_cname,
- const char *cname1)
+ const char *cname1,
+ JSValueConst attributes)
{
JSRuntime *rt = ctx->rt;
JSModuleDef *m;
@@ -28441,22 +28589,26 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx,
JS_FreeAtom(ctx, module_name);
/* load the module */
- if (!rt->module_loader_func) {
+ if (!rt->u.module_loader_func) {
/* XXX: use a syntax error ? */
JS_ThrowReferenceError(ctx, "could not load module '%s'",
cname);
js_free(ctx, cname);
return NULL;
}
-
- m = rt->module_loader_func(ctx, cname, rt->module_loader_opaque);
+ if (rt->module_loader_has_attr) {
+ m = rt->u.module_loader_func2(ctx, cname, rt->module_loader_opaque, attributes);
+ } else {
+ m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque);
+ }
js_free(ctx, cname);
return m;
}
static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,
- JSAtom base_module_name,
- JSAtom module_name1)
+ JSAtom base_module_name,
+ JSAtom module_name1,
+ JSValueConst attributes)
{
const char *base_cname, *cname;
JSModuleDef *m;
@@ -28469,7 +28621,7 @@ static JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx,
JS_FreeCString(ctx, base_cname);
return NULL;
}
- m = js_host_resolve_imported_module(ctx, base_cname, cname);
+ m = js_host_resolve_imported_module(ctx, base_cname, cname, attributes);
JS_FreeCString(ctx, base_cname);
JS_FreeCString(ctx, cname);
return m;
@@ -28931,7 +29083,8 @@ static int js_resolve_module(JSContext *ctx, JSModuleDef *m)
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
m1 = js_host_resolve_imported_module_atom(ctx, m->module_name,
- rme->module_name);
+ rme->module_name,
+ rme->attributes);
if (!m1)
return -1;
rme->module = m1;
@@ -29408,14 +29561,15 @@ static JSValue js_load_module_fulfilled(JSContext *ctx, JSValueConst this_val,
static void JS_LoadModuleInternal(JSContext *ctx, const char *basename,
const char *filename,
- JSValueConst *resolving_funcs)
+ JSValueConst *resolving_funcs,
+ JSValueConst attributes)
{
JSValue evaluate_promise;
JSModuleDef *m;
JSValue ret, err, func_obj, evaluate_resolving_funcs[2];
JSValueConst func_data[3];
- m = js_host_resolve_imported_module(ctx, basename, filename);
+ m = js_host_resolve_imported_module(ctx, basename, filename, attributes);
if (!m)
goto fail;
@@ -29462,7 +29616,7 @@ JSValue JS_LoadModule(JSContext *ctx, const char *basename,
if (JS_IsException(promise))
return JS_EXCEPTION;
JS_LoadModuleInternal(ctx, basename, filename,
- (JSValueConst *)resolving_funcs);
+ (JSValueConst *)resolving_funcs, JS_UNDEFINED);
JS_FreeValue(ctx, resolving_funcs[0]);
JS_FreeValue(ctx, resolving_funcs[1]);
return promise;
@@ -29474,6 +29628,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
JSValueConst *resolving_funcs = argv;
JSValueConst basename_val = argv[2];
JSValueConst specifier = argv[3];
+ JSValueConst attributes = argv[4];
const char *basename = NULL, *filename;
JSValue ret, err;
@@ -29490,7 +29645,7 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
goto exception;
JS_LoadModuleInternal(ctx, basename, filename,
- resolving_funcs);
+ resolving_funcs, attributes);
JS_FreeCString(ctx, filename);
JS_FreeCString(ctx, basename);
return JS_UNDEFINED;
@@ -29504,11 +29659,12 @@ static JSValue js_dynamic_import_job(JSContext *ctx,
return JS_UNDEFINED;
}
-static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
+static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options)
{
JSAtom basename;
- JSValue promise, resolving_funcs[2], basename_val;
- JSValueConst args[4];
+ JSValue promise, resolving_funcs[2], basename_val, err, ret;
+ JSValue specifier_str = JS_UNDEFINED, attributes = JS_UNDEFINED, attributes_obj = JS_UNDEFINED;
+ JSValueConst args[5];
basename = JS_GetScriptOrModuleName(ctx, 0);
if (basename == JS_ATOM_NULL)
@@ -29525,19 +29681,82 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier)
return promise;
}
+ /* the string conversion must occur here */
+ specifier_str = JS_ToString(ctx, specifier);
+ if (JS_IsException(specifier_str))
+ goto exception;
+
+ if (!JS_IsUndefined(options)) {
+ if (!JS_IsObject(options)) {
+ JS_ThrowTypeError(ctx, "options must be an object");
+ goto exception;
+ }
+ attributes_obj = JS_GetProperty(ctx, options, JS_ATOM_with);
+ if (JS_IsException(attributes_obj))
+ goto exception;
+ if (!JS_IsUndefined(attributes_obj)) {
+ JSPropertyEnum *atoms;
+ uint32_t atoms_len, i;
+ JSValue val;
+
+ if (!JS_IsObject(attributes_obj)) {
+ JS_ThrowTypeError(ctx, "options.with must be an object");
+ goto exception;
+ }
+ attributes = JS_NewObjectProto(ctx, JS_NULL);
+ if (JS_GetOwnPropertyNamesInternal(ctx, &atoms, &atoms_len, JS_VALUE_GET_OBJ(attributes_obj),
+ JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY)) {
+ goto exception;
+ }
+ for(i = 0; i < atoms_len; i++) {
+ val = JS_GetProperty(ctx, attributes_obj, atoms[i].atom);
+ if (JS_IsException(val))
+ goto exception1;
+ if (!JS_IsString(val)) {
+ JS_FreeValue(ctx, val);
+ JS_ThrowTypeError(ctx, "module attribute values must be strings");
+ goto exception1;
+ }
+ if (JS_DefinePropertyValue(ctx, attributes, atoms[i].atom, val,
+ JS_PROP_C_W_E) < 0) {
+ exception1:
+ JS_FreePropertyEnum(ctx, atoms, atoms_len);
+ goto exception;
+ }
+ }
+ JS_FreePropertyEnum(ctx, atoms, atoms_len);
+ if (ctx->rt->module_check_attrs &&
+ ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, attributes) < 0) {
+ goto exception;
+ }
+ JS_FreeValue(ctx, attributes_obj);
+ }
+ }
+
args[0] = resolving_funcs[0];
args[1] = resolving_funcs[1];
args[2] = basename_val;
- args[3] = specifier;
-
+ args[3] = specifier_str;
+ args[4] = attributes;
+
/* cannot run JS_LoadModuleInternal synchronously because it would
cause an unexpected recursion in js_evaluate_module() */
- JS_EnqueueJob(ctx, js_dynamic_import_job, 4, args);
-
+ JS_EnqueueJob(ctx, js_dynamic_import_job, 5, args);
+ done:
JS_FreeValue(ctx, basename_val);
JS_FreeValue(ctx, resolving_funcs[0]);
JS_FreeValue(ctx, resolving_funcs[1]);
+ JS_FreeValue(ctx, specifier_str);
+ JS_FreeValue(ctx, attributes);
return promise;
+ exception:
+ JS_FreeValue(ctx, attributes_obj);
+ err = JS_GetException(ctx);
+ ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED,
+ 1, (JSValueConst *)&err);
+ JS_FreeValue(ctx, ret);
+ JS_FreeValue(ctx, err);
+ goto done;
}
static void js_set_module_evaluated(JSContext *ctx, JSModuleDef *m)
@@ -29933,27 +30152,109 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m)
return JS_DupValue(ctx, m->promise);
}
-static __exception JSAtom js_parse_from_clause(JSParseState *s)
+static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme)
+{
+ JSContext *ctx = s->ctx;
+ JSAtom key;
+ int ret;
+ const uint8_t *key_token_ptr;
+
+ if (next_token(s))
+ return -1;
+ if (js_parse_expect(s, '{'))
+ return -1;
+ while (s->token.val != '}') {
+ key_token_ptr = s->token.ptr;
+ if (s->token.val == TOK_STRING) {
+ key = JS_ValueToAtom(ctx, s->token.u.str.str);
+ if (key == JS_ATOM_NULL)
+ return -1;
+ } else {
+ if (!token_is_ident(s->token.val)) {
+ js_parse_error(s, "identifier expected");
+ return -1;
+ }
+ key = JS_DupAtom(ctx, s->token.u.ident.atom);
+ }
+ if (next_token(s))
+ return -1;
+ if (js_parse_expect(s, ':')) {
+ JS_FreeAtom(ctx, key);
+ return -1;
+ }
+ if (s->token.val != TOK_STRING) {
+ js_parse_error_pos(s, key_token_ptr, "string expected");
+ return -1;
+ }
+ if (JS_IsUndefined(rme->attributes)) {
+ JSValue attributes = JS_NewObjectProto(ctx, JS_NULL);
+ if (JS_IsException(attributes)) {
+ JS_FreeAtom(ctx, key);
+ return -1;
+ }
+ rme->attributes = attributes;
+ }
+ ret = JS_HasProperty(ctx, rme->attributes, key);
+ if (ret != 0) {
+ JS_FreeAtom(ctx, key);
+ if (ret < 0)
+ return -1;
+ else
+ return js_parse_error(s, "duplicate with key");
+ }
+ ret = JS_DefinePropertyValue(ctx, rme->attributes, key,
+ JS_DupValue(ctx, s->token.u.str.str), JS_PROP_C_W_E);
+ JS_FreeAtom(ctx, key);
+ if (ret < 0)
+ return -1;
+ if (next_token(s))
+ return -1;
+ if (s->token.val != ',')
+ break;
+ if (next_token(s))
+ return -1;
+ }
+ if (!JS_IsUndefined(rme->attributes) &&
+ ctx->rt->module_check_attrs &&
+ ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) {
+ return -1;
+ }
+ return js_parse_expect(s, '}');
+}
+
+/* return the module index in m->req_module_entries[] or < 0 if error */
+static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m)
{
JSAtom module_name;
+ int idx;
+
if (!token_is_pseudo_keyword(s, JS_ATOM_from)) {
js_parse_error(s, "from clause expected");
- return JS_ATOM_NULL;
+ return -1;
}
if (next_token(s))
- return JS_ATOM_NULL;
+ return -1;
if (s->token.val != TOK_STRING) {
js_parse_error(s, "string expected");
- return JS_ATOM_NULL;
+ return -1;
}
module_name = JS_ValueToAtom(s->ctx, s->token.u.str.str);
if (module_name == JS_ATOM_NULL)
- return JS_ATOM_NULL;
+ return -1;
if (next_token(s)) {
JS_FreeAtom(s->ctx, module_name);
- return JS_ATOM_NULL;
+ return -1;
+ }
+
+ idx = add_req_module_entry(s->ctx, m, module_name);
+ JS_FreeAtom(s->ctx, module_name);
+ if (idx < 0)
+ return -1;
+ if (s->token.val == TOK_WITH) {
+ if (js_parse_with_clause(s, &m->req_module_entries[idx]))
+ return -1;
}
- return module_name;
+ return idx;
}
static __exception int js_parse_export(JSParseState *s)
@@ -29962,7 +30263,6 @@ static __exception int js_parse_export(JSParseState *s)
JSModuleDef *m = s->cur_func->module;
JSAtom local_name, export_name;
int first_export, idx, i, tok;
- JSAtom module_name;
JSExportEntry *me;
if (next_token(s))
@@ -30037,11 +30337,7 @@ static __exception int js_parse_export(JSParseState *s)
if (js_parse_expect(s, '}'))
return -1;
if (token_is_pseudo_keyword(s, JS_ATOM_from)) {
- module_name = js_parse_from_clause(s);
- if (module_name == JS_ATOM_NULL)
- return -1;
- idx = add_req_module_entry(ctx, m, module_name);
- JS_FreeAtom(ctx, module_name);
+ idx = js_parse_from_clause(s, m);
if (idx < 0)
return -1;
for(i = first_export; i < m->export_entries_count; i++) {
@@ -30063,11 +30359,7 @@ static __exception int js_parse_export(JSParseState *s)
export_name = JS_DupAtom(ctx, s->token.u.ident.atom);
if (next_token(s))
goto fail1;
- module_name = js_parse_from_clause(s);
- if (module_name == JS_ATOM_NULL)
- goto fail1;
- idx = add_req_module_entry(ctx, m, module_name);
- JS_FreeAtom(ctx, module_name);
+ idx = js_parse_from_clause(s, m);
if (idx < 0)
goto fail1;
me = add_export_entry(s, m, JS_ATOM__star_, export_name,
@@ -30077,11 +30369,7 @@ static __exception int js_parse_export(JSParseState *s)
return -1;
me->u.req_module_idx = idx;
} else {
- module_name = js_parse_from_clause(s);
- if (module_name == JS_ATOM_NULL)
- return -1;
- idx = add_req_module_entry(ctx, m, module_name);
- JS_FreeAtom(ctx, module_name);
+ idx = js_parse_from_clause(s, m);
if (idx < 0)
return -1;
if (add_star_export_entry(ctx, m, idx) < 0)
@@ -30187,6 +30475,14 @@ static __exception int js_parse_import(JSParseState *s)
JS_FreeAtom(ctx, module_name);
return -1;
}
+ idx = add_req_module_entry(ctx, m, module_name);
+ JS_FreeAtom(ctx, module_name);
+ if (idx < 0)
+ return -1;
+ if (s->token.val == TOK_WITH) {
+ if (js_parse_with_clause(s, &m->req_module_entries[idx]))
+ return -1;
+ }
} else {
if (s->token.val == TOK_IDENT) {
if (s->token.u.ident.is_reserved) {
@@ -30285,14 +30581,10 @@ static __exception int js_parse_import(JSParseState *s)
return -1;
}
end_import_clause:
- module_name = js_parse_from_clause(s);
- if (module_name == JS_ATOM_NULL)
+ idx = js_parse_from_clause(s, m);
+ if (idx < 0)
return -1;
}
- idx = add_req_module_entry(ctx, m, module_name);
- JS_FreeAtom(ctx, module_name);
- if (idx < 0)
- return -1;
for(i = first_import; i < m->import_entries_count; i++)
m->import_entries[i].req_module_idx = idx;
@@ -30415,6 +30707,8 @@ static void free_bytecode_atoms(JSRuntime *rt,
case OP_FMT_atom_u16:
case OP_FMT_atom_label_u8:
case OP_FMT_atom_label_u16:
+ if ((pos + 1 + 4) > bc_len)
+ break; /* may happen if there is not enough memory when emiting bytecode */
atom = get_u32(bc_buf + pos + 1);
JS_FreeAtomRT(rt, atom);
break;
@@ -31204,7 +31498,13 @@ static void var_object_test(JSContext *ctx, JSFunctionDef *s,
{
dbuf_putc(bc, get_with_scope_opcode(op));
dbuf_put_u32(bc, JS_DupAtom(ctx, var_name));
- *plabel_done = new_label_fd(s, *plabel_done);
+ if (*plabel_done < 0) {
+ *plabel_done = new_label_fd(s);
+ if (*plabel_done < 0) {
+ dbuf_set_error(bc);
+ return;
+ }
+ }
dbuf_put_u32(bc, *plabel_done);
dbuf_putc(bc, is_with);
update_label(s, *plabel_done, 1);
@@ -32249,8 +32549,11 @@ static void instantiate_hoisted_definitions(JSContext *ctx, JSFunctionDef *s, Dy
evaluating the module so that the exported functions are
visible if there are cyclic module references */
if (s->module) {
- label_next = new_label_fd(s, -1);
-
+ label_next = new_label_fd(s);
+ if (label_next < 0) {
+ dbuf_set_error(bc);
+ return;
+ }
/* if 'this' is true, initialize the global variables and return */
dbuf_putc(bc, OP_push_this);
dbuf_putc(bc, OP_if_false);
@@ -35061,7 +35364,7 @@ static __exception int js_parse_function_decl2(JSParseState *s,
push_scope(s); /* enter body scope */
fd->body_scope = fd->scope_level;
- if (s->token.val == TOK_ARROW) {
+ if (s->token.val == TOK_ARROW && func_type == JS_PARSE_FUNC_ARROW) {
if (next_token(s))
goto fail;
@@ -36100,6 +36403,8 @@ static int JS_WriteModule(BCWriterState *s, JSValueConst obj)
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
bc_put_atom(s, rme->module_name);
+ if (JS_WriteObjectRec(s, rme->attributes))
+ goto fail;
}
bc_put_leb128(s, m->export_entries_count);
@@ -37099,8 +37404,13 @@ static JSValue JS_ReadModule(BCReaderState *s)
goto fail;
for(i = 0; i < m->req_module_entries_count; i++) {
JSReqModuleEntry *rme = &m->req_module_entries[i];
+ JSValue val;
if (bc_get_atom(s, &rme->module_name))
goto fail;
+ val = JS_ReadObjectRec(s);
+ if (JS_IsException(val))
+ goto fail;
+ rme->attributes = val;
}
}
@@ -37768,17 +38078,22 @@ static int JS_InstantiateFunctionListItem(JSContext *ctx, JSValueConst obj,
return 0;
}
-void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
- const JSCFunctionListEntry *tab, int len)
+int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
+ const JSCFunctionListEntry *tab, int len)
{
- int i;
+ int i, ret;
for (i = 0; i < len; i++) {
const JSCFunctionListEntry *e = &tab[i];
JSAtom atom = find_atom(ctx, e->name);
- JS_InstantiateFunctionListItem(ctx, obj, atom, e);
+ if (atom == JS_ATOM_NULL)
+ return -1;
+ ret = JS_InstantiateFunctionListItem(ctx, obj, atom, e);
JS_FreeAtom(ctx, atom);
+ if (ret)
+ return -1;
}
+ return 0;
}
int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
@@ -44196,9 +44511,13 @@ static int getTimezoneOffset(int64_t time)
time_t gm_ti, loc_ti;
tm = gmtime(&ti);
+ if (!tm)
+ return 0;
gm_ti = mktime(tm);
tm = localtime(&ti);
+ if (!tm)
+ return 0;
loc_ti = mktime(tm);
res = (gm_ti - loc_ti) / 60;
@@ -45170,7 +45489,7 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val,
if (JS_IsException(matchStr))
goto exception;
isEmpty = JS_IsEmptyString(matchStr);
- if (JS_SetPropertyInt64(ctx, A, n++, matchStr) < 0)
+ if (JS_DefinePropertyValueInt64(ctx, A, n++, matchStr, JS_PROP_C_W_E | JS_PROP_THROW) < 0)
goto exception;
if (isEmpty) {
int64_t thisIndex, nextIndex;
@@ -45988,6 +46307,12 @@ static JSValue json_parse_value(JSParseState *s)
val = JS_NewBool(ctx, s->token.u.ident.atom == JS_ATOM_true);
} else if (s->token.u.ident.atom == JS_ATOM_null) {
val = JS_NULL;
+ } else if (s->token.u.ident.atom == JS_ATOM_NaN && s->ext_json) {
+ /* Note: json5 identifier handling is ambiguous e.g. is
+ '{ NaN: 1 }' a valid JSON5 production ? */
+ val = JS_NewFloat64(s->ctx, NAN);
+ } else if (s->token.u.ident.atom == JS_ATOM_Infinity && s->ext_json) {
+ val = JS_NewFloat64(s->ctx, INFINITY);
} else {
goto def_token;
}
diff --git a/quickjs.h b/quickjs.h
index 60a8d49..4570c6d 100644
--- a/quickjs.h
+++ b/quickjs.h
@@ -936,12 +936,25 @@ typedef char *JSModuleNormalizeFunc(JSContext *ctx,
const char *module_name, void *opaque);
typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
const char *module_name, void *opaque);
-
+typedef JSModuleDef *JSModuleLoaderFunc2(JSContext *ctx,
+ const char *module_name, void *opaque,
+ JSValueConst attributes);
+/* return -1 if exception, 0 if OK */
+typedef int JSModuleCheckSupportedImportAttributes(JSContext *ctx, void *opaque,
+ JSValueConst attributes);
+
/* module_normalize = NULL is allowed and invokes the default module
filename normalizer */
void JS_SetModuleLoaderFunc(JSRuntime *rt,
JSModuleNormalizeFunc *module_normalize,
JSModuleLoaderFunc *module_loader, void *opaque);
+/* same as JS_SetModuleLoaderFunc but with attributes. if
+ module_check_attrs = NULL, no attribute checking is done. */
+void JS_SetModuleLoaderFunc2(JSRuntime *rt,
+ JSModuleNormalizeFunc *module_normalize,
+ JSModuleLoaderFunc2 *module_loader,
+ JSModuleCheckSupportedImportAttributes *module_check_attrs,
+ void *opaque);
/* return the import.meta object of a module */
JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
@@ -1100,9 +1113,9 @@ typedef struct JSCFunctionListEntry {
#define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, -1 } } }
#define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u = { .alias = { from, base } } }
-void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
- const JSCFunctionListEntry *tab,
- int len);
+int JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
+ const JSCFunctionListEntry *tab,
+ int len);
/* C module definition */
@@ -1119,7 +1132,10 @@ int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
JSValue val);
int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
const JSCFunctionListEntry *tab, int len);
-
+/* associate a JSValue to a C module */
+int JS_SetModulePrivateValue(JSContext *ctx, JSModuleDef *m, JSValue val);
+JSValue JS_GetModulePrivateValue(JSContext *ctx, JSModuleDef *m);
+
/* debug value output */
typedef struct {
diff --git a/run-test262.c b/run-test262.c
index 3da79a0..03b37c6 100644
--- a/run-test262.c
+++ b/run-test262.c
@@ -836,13 +836,21 @@ static char *load_file(const char *filename, size_t *lenp)
return buf;
}
+static int json_module_init_test(JSContext *ctx, JSModuleDef *m)
+{
+ JSValue val;
+ val = JS_GetModulePrivateValue(ctx, m);
+ JS_SetModuleExport(ctx, m, "default", val);
+ return 0;
+}
+
static JSModuleDef *js_module_loader_test(JSContext *ctx,
- const char *module_name, void *opaque)
+ const char *module_name, void *opaque,
+ JSValueConst attributes)
{
size_t buf_len;
uint8_t *buf;
JSModuleDef *m;
- JSValue func_val;
char *filename, *slash, path[1024];
// interpret import("bar.js") from path/to/foo.js as
@@ -864,15 +872,33 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx,
return NULL;
}
- /* compile the module */
- func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
- JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
- js_free(ctx, buf);
- if (JS_IsException(func_val))
- return NULL;
- /* the module is already referenced, so we must free it */
- m = JS_VALUE_GET_PTR(func_val);
- JS_FreeValue(ctx, func_val);
+ if (js_module_test_json(ctx, attributes) == 1) {
+ /* compile as JSON */
+ JSValue val;
+ val = JS_ParseJSON(ctx, (char *)buf, buf_len, module_name);
+ js_free(ctx, buf);
+ if (JS_IsException(val))
+ return NULL;
+ m = JS_NewCModule(ctx, module_name, json_module_init_test);
+ if (!m) {
+ JS_FreeValue(ctx, val);
+ return NULL;
+ }
+ /* only export the "default" symbol which will contain the JSON object */
+ JS_AddModuleExport(ctx, m, "default");
+ JS_SetModulePrivateValue(ctx, m, val);
+ } else {
+ JSValue func_val;
+ /* compile the module */
+ func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
+ JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
+ js_free(ctx, buf);
+ if (JS_IsException(func_val))
+ return NULL;
+ /* the module is already referenced, so we must free it */
+ m = JS_VALUE_GET_PTR(func_val);
+ JS_FreeValue(ctx, func_val);
+ }
return m;
}
@@ -1587,7 +1613,7 @@ int run_test_buf(const char *filename, const char *harness, namelist_t *ip,
JS_SetCanBlock(rt, can_block);
/* loader for ES6 modules */
- JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *)filename);
+ JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *)filename);
add_helpers(ctx);
@@ -1888,7 +1914,7 @@ int run_test262_harness_test(const char *filename, BOOL is_module)
JS_SetCanBlock(rt, can_block);
/* loader for ES6 modules */
- JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, (void *)filename);
+ JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader_test, NULL, (void *)filename);
add_helpers(ctx);
diff --git a/test262.conf b/test262.conf
index 02df380..0966a59 100644
--- a/test262.conf
+++ b/test262.conf
@@ -116,9 +116,7 @@ for-of
generators
globalThis
hashbang
-host-gc-required=skip
-import-assertions=skip
-import-attributes=skip
+import-attributes
import-defer=skip
import.meta
Int16Array
@@ -144,7 +142,7 @@ Intl.Segmenter=skip
IsHTMLDDA
iterator-helpers=skip
iterator-sequencing=skip
-json-modules=skip
+json-modules
json-parse-with-source=skip
json-superset
legacy-regexp=skip
@@ -230,6 +228,7 @@ Uint32Array
Uint8Array
uint8array-base64=skip
Uint8ClampedArray
+upsert=skip
WeakMap
WeakRef
WeakSet
@@ -323,6 +322,15 @@ test262/test/staging/sm/Function/function-toString-builtin-name.js
test262/test/staging/sm/extensions/arguments-property-access-in-function.js
test262/test/staging/sm/extensions/function-caller-skips-eval-frames.js
test262/test/staging/sm/extensions/function-properties.js
+test262/test/staging/sm/regress/regress-577648-1.js
+test262/test/staging/sm/regress/regress-577648-2.js
+test262/test/staging/sm/regress/regress-584355.js
+test262/test/staging/sm/regress/regress-586482-1.js
+test262/test/staging/sm/regress/regress-586482-2.js
+test262/test/staging/sm/regress/regress-586482-3.js
+test262/test/staging/sm/regress/regress-586482-4.js
+test262/test/staging/sm/regress/regress-699682.js
+
# RegExp toSource not fully compliant
test262/test/staging/sm/RegExp/toString.js
test262/test/staging/sm/RegExp/source.js
diff --git a/test262_errors.txt b/test262_errors.txt
index d3f06c3..9df6f74 100644
--- a/test262_errors.txt
+++ b/test262_errors.txt
@@ -1,3 +1,5 @@
+test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34: TypeError: ArrayBuffer is detached
+test262/test/built-ins/Atomics/notify/retrieve-length-before-index-coercion-non-shared-detached.js:34: strict mode: TypeError: ArrayBuffer is detached
test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called
test262/test/staging/sm/Date/UTC-convert-all-arguments.js:75: Test262Error: index 1: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true
test262/test/staging/sm/Date/constructor-convert-all-arguments.js:75: Test262Error: index undefined: expected 42, got Error: didn't throw Expected SameValue(«Error: didn't throw», «42») to be true
@@ -12,12 +14,10 @@ test262/test/staging/sm/Function/function-toString-builtin.js:14: Test262Error:
}' Expected SameValue(«null», «null») to be false
test262/test/staging/sm/Function/implicit-this-in-parameter-expression.js:13: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
test262/test/staging/sm/Function/invalid-parameter-list.js:35: Error: Assertion failed: expected exception SyntaxError, no exception thrown
-test262/test/staging/sm/Math/cbrt-approx.js:26: Error: got 1.39561242508609, expected a number near 1.3956124250860895 (relative error: 2)
test262/test/staging/sm/RegExp/constructor-ordering-2.js:15: Test262Error: Expected SameValue(«false», «true») to be true
test262/test/staging/sm/RegExp/regress-613820-1.js:13: Test262Error: Expected SameValue(«"aaa"», «"aa"») to be true
test262/test/staging/sm/RegExp/regress-613820-2.js:13: Test262Error: Expected SameValue(«"f"», «undefined») to be true
test262/test/staging/sm/RegExp/regress-613820-3.js:13: Test262Error: Expected SameValue(«"aab"», «"aa"») to be true
-test262/test/staging/sm/String/match-defines-match-elements.js:52: Test262Error: Expected SameValue(«true», «false») to be true
test262/test/staging/sm/TypedArray/constructor-buffer-sequence.js:73: Error: Assertion failed: expected exception ExpectedError, got Error: Poisoned Value
test262/test/staging/sm/TypedArray/prototype-constructor-identity.js:17: Test262Error: Expected SameValue(«2», «6») to be true
test262/test/staging/sm/TypedArray/set-detached-bigint.js:27: Error: Assertion failed: expected exception SyntaxError, got RangeError: invalid array length
@@ -29,14 +29,11 @@ test262/test/staging/sm/async-functions/await-error.js:12: Test262Error: Expecte
test262/test/staging/sm/async-functions/await-in-arrow-parameters.js:33: Error: Assertion failed: expected exception SyntaxError, no exception thrown - AsyncFunction:(a = (b = await/r/g) => {}) => {}
test262/test/staging/sm/class/boundFunctionSubclassing.js:12: Test262Error: Expected SameValue(«false», «true») to be true
test262/test/staging/sm/class/compPropNames.js:26: Error: Expected syntax error: ({[1, 2]: 3})
-test262/test/staging/sm/class/methDefn.js:26: Error: Expected syntax error: b = {a() => 0}
test262/test/staging/sm/class/strictExecution.js:32: Error: Assertion failed: expected exception TypeError, no exception thrown
test262/test/staging/sm/class/superPropOrdering.js:83: Error: Assertion failed: expected exception TypeError, no exception thrown
-test262/test/staging/sm/expressions/optional-chain.js:25: Error: Assertion failed: expected exception SyntaxError, no exception thrown
test262/test/staging/sm/expressions/short-circuit-compound-assignment-const.js:97: TypeError: 'a' is read-only
test262/test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js:23: Error: Assertion failed: expected exception ReferenceError, got TypeError: 'a' is read-only
test262/test/staging/sm/extensions/TypedArray-set-object-funky-length-detaches.js:55: RangeError: invalid array length
-test262/test/staging/sm/extensions/regress-469625-01.js:16: Test262Error: TM: Array prototype and expression closures Expected SameValue(«"TypeError: [].__proto__ is not a function"», «"TypeError: not a function"») to be true
test262/test/staging/sm/generators/syntax.js:30: Error: Assertion failed: expected SyntaxError, but no exception thrown - function* g() { (function* yield() {}); }
test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-arguments.js:14: Test262Error: Expected SameValue(«"object"», «"function"») to be true
test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-eval.js:12: Test262Error: Expected SameValue(«"outer-gouter-geval-gtruefalseq"», «"outer-geval-gwith-gtruefalseq"») to be true
@@ -45,15 +42,7 @@ test262/test/staging/sm/lexical-environment/block-scoped-functions-annex-b-notap
test262/test/staging/sm/lexical-environment/block-scoped-functions-deprecated-redecl.js:23: Test262Error: Expected SameValue(«3», «4») to be true
test262/test/staging/sm/lexical-environment/var-in-catch-body-annex-b-eval.js:17: Test262Error: Expected SameValue(«"g"», «"global-x"») to be true
test262/test/staging/sm/object/defineProperties-order.js:14: Test262Error: Expected SameValue(«"ownKeys,getOwnPropertyDescriptor,getOwnPropertyDescriptor,get,get"», «"ownKeys,getOwnPropertyDescriptor,get,getOwnPropertyDescriptor,get"») to be true
-test262/test/staging/sm/regress/regress-577648-1.js:21: Test262Error: 1 Expected SameValue(«true», «false») to be true
-test262/test/staging/sm/regress/regress-577648-2.js:14: Test262Error: Expected SameValue(«true», «false») to be true
-test262/test/staging/sm/regress/regress-584355.js:12: Test262Error: Expected SameValue(«"function f () { ff (); }"», «"undefined"») to be true
-test262/test/staging/sm/regress/regress-586482-1.js:19: Test262Error: ok Expected SameValue(«true», «false») to be true
-test262/test/staging/sm/regress/regress-586482-2.js:19: Test262Error: ok Expected SameValue(«true», «false») to be true
-test262/test/staging/sm/regress/regress-586482-3.js:18: Test262Error: ok Expected SameValue(«true», «false») to be true
-test262/test/staging/sm/regress/regress-586482-4.js:14: Test262Error: ok Expected SameValue(«function() { this.f(); }», «undefined») to be true
test262/test/staging/sm/regress/regress-602621.js:14: Test262Error: function sub-statement must override arguments Expected SameValue(«"function"», «"object"») to be true
-test262/test/staging/sm/regress/regress-699682.js:15: Test262Error: Expected SameValue(«false», «true») to be true
test262/test/staging/sm/regress/regress-1383630.js:30: Error: Assertion failed: expected exception TypeError, no exception thrown
test262/test/staging/sm/statements/arrow-function-in-for-statement-head.js:15: Test262Error: expected syntax error, got Error: didn't throw Expected SameValue(«false», «true») to be true
test262/test/staging/sm/statements/regress-642975.js:14: Test262Error: Expected SameValue(«undefined», «"y"») to be true
diff --git a/tests/assert.js b/tests/assert.js
index c8240c8..42369ed 100644
--- a/tests/assert.js
+++ b/tests/assert.js
@@ -3,14 +3,8 @@ export function assert(actual, expected, message) {
expected = true;
if (typeof actual === typeof expected) {
- if (actual === expected) {
- if (actual !== 0 || (1 / actual) === (1 / expected))
- return;
- }
- if (typeof actual === 'number') {
- if (isNaN(actual) && isNaN(expected))
- return;
- }
+ if (Object.is(actual, expected))
+ return;
if (typeof actual === 'object') {
if (actual !== null && expected !== null
&& actual.constructor === expected.constructor
diff --git a/tests/test262.patch b/tests/test262.patch
index b6f4aa5..4ed0afb 100644
--- a/tests/test262.patch
+++ b/tests/test262.patch
@@ -90,6 +90,43 @@ index c1829e3..3a3ee27 100644
-}
\ No newline at end of file
+}
+diff --git a/test/staging/sm/extensions/regress-469625-01.js b/test/staging/sm/extensions/regress-469625-01.js
+index 5b62aeb..da07aae 100644
+--- a/test/staging/sm/extensions/regress-469625-01.js
++++ b/test/staging/sm/extensions/regress-469625-01.js
+@@ -14,8 +14,7 @@ esid: pending
+ //-----------------------------------------------------------------------------
+ var BUGNUMBER = 469625;
+ var summary = 'TM: Array prototype and expression closures';
+-var actual = '';
+-var expect = '';
++var actual = null;
+
+
+ //-----------------------------------------------------------------------------
+@@ -27,9 +26,6 @@ function test()
+ printBugNumber(BUGNUMBER);
+ printStatus (summary);
+
+- expect = 'TypeError: [].__proto__ is not a function';
+-
+-
+ Array.prototype.__proto__ = function () { return 3; };
+
+ try
+@@ -38,8 +34,10 @@ function test()
+ }
+ catch(ex)
+ {
+- print(actual = ex + '');
++ print(ex + '');
++ actual = ex;
+ }
+
+- assert.sameValue(expect, actual, summary);
++ assert.sameValue(actual instanceof TypeError, true);
++ assert.sameValue(actual.message.includes("not a function"), true);
+ }
diff --git a/test/staging/sm/misc/new-with-non-constructor.js b/test/staging/sm/misc/new-with-non-constructor.js
index 18c2f0c..f9aa209 100644
--- a/test/staging/sm/misc/new-with-non-constructor.js
diff --git a/tests/test_language.js b/tests/test_language.js
index cda782b..4fa16c8 100644
--- a/tests/test_language.js
+++ b/tests/test_language.js
@@ -2,7 +2,7 @@ function assert(actual, expected, message) {
if (arguments.length == 1)
expected = true;
- if (actual === expected)
+ if (Object.is(actual, expected))
return;
if (actual !== null && expected !== null
diff --git a/tests/test_std.js b/tests/test_std.js
index df02f92..3debe40 100644
--- a/tests/test_std.js
+++ b/tests/test_std.js
@@ -6,7 +6,7 @@ function assert(actual, expected, message) {
if (arguments.length == 1)
expected = true;
- if (actual === expected)
+ if (Object.is(actual, expected))
return;
if (actual !== null && expected !== null
@@ -129,15 +129,27 @@ function test_popen()
function test_ext_json()
{
var expected, input, obj;
- expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"s":"str"}';
+ expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"b":"abc\\u000bd","s":"str"}';
input = `{ "x":false, /*comments are allowed */
"y":true, // also a comment
z2:null, // unquoted property names
"a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal
+ "b": "ab\
+c\\vd", // multi-line strings, '\v' escape
"s":'str',} // trailing comma in objects and arrays, single quoted string
`;
obj = std.parseExtJSON(input);
assert(JSON.stringify(obj), expected);
+
+ obj = std.parseExtJSON('[Infinity, +Infinity, -Infinity, NaN, +NaN, -NaN, .1, -.2]');
+ assert(obj[0], Infinity);
+ assert(obj[1], Infinity);
+ assert(obj[2], -Infinity);
+ assert(obj[3], NaN);
+ assert(obj[4], NaN);
+ assert(obj[5], NaN);
+ assert(obj[6], 0.1);
+ assert(obj[7], -0.2);
}
function test_os()
diff --git a/unicode_gen.c b/unicode_gen.c
index 1b43538..c793ba1 100644
--- a/unicode_gen.c
+++ b/unicode_gen.c
@@ -2087,10 +2087,9 @@ void build_script_table(FILE *f)
fprintf(f, " UNICODE_SCRIPT_COUNT,\n");
fprintf(f, "} UnicodeScriptEnum;\n\n");
- i = 1;
dump_name_table(f, "unicode_script_name_table",
- unicode_script_name + i, SCRIPT_COUNT - i,
- unicode_script_short_name + i);
+ unicode_script_name, SCRIPT_COUNT,
+ unicode_script_short_name);
dbuf_init(dbuf);
#ifdef DUMP_TABLE_SIZE