summaryrefslogtreecommitdiff
path: root/quickjs.c
diff options
context:
space:
mode:
Diffstat (limited to 'quickjs.c')
-rw-r--r--quickjs.c549
1 files changed, 437 insertions, 112 deletions
diff --git a/quickjs.c b/quickjs.c
index 401022e..475232c 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,
@@ -3205,15 +3212,18 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx, JSAtom v)
}
/* free with JS_FreeCString() */
-const char *JS_AtomToCString(JSContext *ctx, JSAtom atom)
+const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom)
{
JSValue str;
const char *cstr;
str = JS_AtomToString(ctx, atom);
- if (JS_IsException(str))
+ if (JS_IsException(str)) {
+ if (plen)
+ *plen = 0;
return NULL;
- cstr = JS_ToCString(ctx, str);
+ }
+ cstr = JS_ToCStringLen(ctx, plen, str);
JS_FreeValue(ctx, str);
return cstr;
}
@@ -7875,7 +7885,7 @@ static int num_keys_cmp(const void *p1, const void *p2, void *opaque)
return 1;
}
-static void js_free_prop_enum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
+void JS_FreePropertyEnum(JSContext *ctx, JSPropertyEnum *tab, uint32_t len)
{
uint32_t i;
if (tab) {
@@ -7969,7 +7979,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
/* set the "is_enumerable" field if necessary */
res = JS_GetOwnPropertyInternal(ctx, &desc, p, atom);
if (res < 0) {
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
return -1;
}
if (res) {
@@ -8000,7 +8010,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
if (atom_count < exotic_keys_count || atom_count > INT32_MAX) {
add_overflow:
JS_ThrowOutOfMemory(ctx);
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
return -1;
}
/* XXX: need generic way to test for js_malloc(ctx, a * b) overflow */
@@ -8008,7 +8018,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
/* avoid allocating 0 bytes */
tab_atom = js_malloc(ctx, sizeof(tab_atom[0]) * max_int(atom_count, 1));
if (!tab_atom) {
- js_free_prop_enum(ctx, tab_exotic, exotic_count);
+ JS_FreePropertyEnum(ctx, tab_exotic, exotic_count);
return -1;
}
@@ -8053,7 +8063,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx,
for(i = 0; i < len; i++) {
tab_atom[num_index].atom = __JS_AtomFromUInt32(i);
if (tab_atom[num_index].atom == JS_ATOM_NULL) {
- js_free_prop_enum(ctx, tab_atom, num_index);
+ JS_FreePropertyEnum(ctx, tab_atom, num_index);
return -1;
}
tab_atom[num_index].is_enumerable = TRUE;
@@ -12127,7 +12137,7 @@ static JSValue js_atof(JSContext *ctx, const char *str, const char **pp,
case ATOD_TYPE_FLOAT64:
{
double d;
- d = js_atod(buf,NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY,
+ d = js_atod(buf, NULL, radix, is_float ? 0 : JS_ATOD_INT_ONLY,
&atod_mem);
/* return int or float64 */
val = JS_NewFloat64(ctx, d);
@@ -15553,7 +15563,7 @@ static __exception int js_for_in_prepare_prototype_chain_enum(JSContext *ctx,
JS_FreeValue(ctx, obj1);
goto fail;
}
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
if (tab_atom_count != 0) {
JS_FreeValue(ctx, obj1);
goto slow_path;
@@ -15637,7 +15647,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp)
JS_GPN_STRING_MASK | JS_GPN_SET_ENUM)) {
return -1;
}
- js_free_prop_enum(ctx, it->tab_atom, it->atom_count);
+ JS_FreePropertyEnum(ctx, it->tab_atom, it->atom_count);
it->tab_atom = tab_atom;
it->atom_count = tab_atom_count;
it->idx = 0;
@@ -16160,10 +16170,10 @@ static __exception int JS_CopyDataProperties(JSContext *ctx,
if (ret < 0)
goto exception;
}
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
return 0;
exception:
- js_free_prop_enum(ctx, tab_atom, tab_atom_count);
+ JS_FreePropertyEnum(ctx, tab_atom, tab_atom_count);
return -1;
}
@@ -17380,10 +17390,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;
@@ -21031,11 +21043,6 @@ static __exception int js_parse_string(JSParseState *s, int sep,
goto invalid_char;
c = *p;
if (c < 0x20) {
- if (!s->cur_func) {
- if (do_throw)
- js_parse_error_pos(s, p, "invalid character in a JSON string");
- goto fail;
- }
if (sep == '`') {
if (c == '\r') {
if (p[1] == '\n')
@@ -21081,8 +21088,6 @@ static __exception int js_parse_string(JSParseState *s, int sep,
continue;
default:
if (c >= '0' && c <= '9') {
- if (!s->cur_func)
- goto invalid_escape; /* JSON case */
if (!(s->cur_func->js_mode & JS_MODE_STRICT) && sep != '`')
goto parse_escape;
if (c == '0' && !(p[1] >= '0' && p[1] <= '9')) {
@@ -21851,6 +21856,150 @@ static JSAtom json_parse_ident(JSParseState *s, const uint8_t **pp, int c)
return atom;
}
+static int json_parse_string(JSParseState *s, const uint8_t **pp, int sep)
+{
+ const uint8_t *p, *p_next;
+ int i;
+ uint32_t c;
+ StringBuffer b_s, *b = &b_s;
+
+ if (string_buffer_init(s->ctx, b, 32))
+ goto fail;
+
+ p = *pp;
+ for(;;) {
+ if (p >= s->buf_end) {
+ goto end_of_input;
+ }
+ c = *p++;
+ if (c == sep)
+ break;
+ if (c < 0x20) {
+ js_parse_error_pos(s, p - 1, "Bad control character in string literal");
+ goto fail;
+ }
+ if (c == '\\') {
+ c = *p++;
+ switch(c) {
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case '\\': break;
+ case '/': break;
+ case 'u':
+ c = 0;
+ for(i = 0; i < 4; i++) {
+ int h = from_hex(*p++);
+ if (h < 0) {
+ js_parse_error_pos(s, p - 1, "Bad Unicode escape");
+ goto fail;
+ }
+ c = (c << 4) | h;
+ }
+ break;
+ default:
+ if (c == sep)
+ break;
+ if (p > s->buf_end)
+ goto end_of_input;
+ js_parse_error_pos(s, p - 1, "Bad escaped character");
+ goto fail;
+ }
+ } else
+ if (c >= 0x80) {
+ c = unicode_from_utf8(p - 1, UTF8_CHAR_LEN_MAX, &p_next);
+ if (c > 0x10FFFF) {
+ js_parse_error_pos(s, p - 1, "Bad UTF-8 sequence");
+ goto fail;
+ }
+ p = p_next;
+ }
+ if (string_buffer_putc(b, c))
+ goto fail;
+ }
+ s->token.val = TOK_STRING;
+ s->token.u.str.sep = sep;
+ s->token.u.str.str = string_buffer_end(b);
+ *pp = p;
+ return 0;
+
+ end_of_input:
+ js_parse_error(s, "Unexpected end of JSON input");
+ fail:
+ string_buffer_free(b);
+ return -1;
+}
+
+static int json_parse_number(JSParseState *s, const uint8_t **pp)
+{
+ const uint8_t *p = *pp;
+ const uint8_t *p_start = p;
+ int radix;
+ double d;
+ JSATODTempMem atod_mem;
+
+ if (*p == '+' || *p == '-')
+ p++;
+
+ if (!is_digit(*p))
+ return js_parse_error_pos(s, p, "Unexpected token '%c'", *p_start);
+
+ if (p[0] == '0') {
+ if (s->ext_json) {
+ /* also accepts base 16, 8 and 2 prefix for integers */
+ radix = 10;
+ if (p[1] == 'x' || p[1] == 'X') {
+ p += 2;
+ radix = 16;
+ } else if ((p[1] == 'o' || p[1] == 'O')) {
+ p += 2;
+ radix = 8;
+ } else if ((p[1] == 'b' || p[1] == 'B')) {
+ p += 2;
+ radix = 2;
+ }
+ if (radix != 10) {
+ /* prefix is present */
+ if (to_digit(*p) >= radix)
+ 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;
+ }
+ }
+ if (is_digit(p[1]))
+ return js_parse_error_pos(s, p, "Unexpected number");
+ }
+
+ while (is_digit(*p))
+ p++;
+
+ if (*p == '.') {
+ p++;
+ if (!is_digit(*p))
+ return js_parse_error_pos(s, p, "Unterminated fractional number");
+ while (is_digit(*p))
+ p++;
+ }
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ if (*p == '+' || *p == '-')
+ p++;
+ if (!is_digit(*p))
+ return js_parse_error_pos(s, p, "Exponent part is missing a number");
+ while (is_digit(*p))
+ p++;
+ }
+ d = js_atod((const char *)p_start, NULL, 10, 0, &atod_mem);
+ done:
+ s->token.val = TOK_NUMBER;
+ s->token.u.num.val = JS_NewFloat64(s->ctx, d);
+ *pp = p;
+ return 0;
+}
+
static __exception int json_next_token(JSParseState *s)
{
const uint8_t *p;
@@ -21882,7 +22031,8 @@ static __exception int json_next_token(JSParseState *s)
}
/* fall through */
case '\"':
- if (js_parse_string(s, c, TRUE, p + 1, &s->token, &p))
+ p++;
+ if (json_parse_string(s, &p, c))
goto fail;
break;
case '\r': /* accept DOS and MAC newline sequences */
@@ -21999,23 +22149,8 @@ static __exception int json_next_token(JSParseState *s)
case '9':
/* number */
parse_number:
- {
- JSValue ret;
- int flags, radix;
- if (!s->ext_json) {
- flags = 0;
- radix = 10;
- } else {
- flags = ATOD_ACCEPT_BIN_OCT;
- radix = 0;
- }
- ret = js_atof(s->ctx, (const char *)p, (const char **)&p, radix,
- flags);
- if (JS_IsException(ret))
- goto fail;
- s->token.val = TOK_NUMBER;
- s->token.u.num.val = ret;
- }
+ if (json_parse_number(s, &p))
+ goto fail;
break;
default:
if (c >= 128) {
@@ -25412,6 +25547,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);
@@ -27989,6 +28141,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;
}
@@ -27998,6 +28151,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 &&
@@ -28013,6 +28171,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)
@@ -28024,6 +28183,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);
@@ -28052,6 +28212,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);
}
@@ -28060,14 +28221,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),
@@ -28077,7 +28230,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,
@@ -28196,12 +28350,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;
}
@@ -28282,7 +28462,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;
@@ -28315,22 +28496,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;
@@ -28343,7 +28528,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;
@@ -28805,7 +28990,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;
@@ -29282,14 +29468,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;
@@ -29336,7 +29523,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;
@@ -29348,6 +29535,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;
@@ -29364,7 +29552,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;
@@ -29378,11 +29566,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)
@@ -29399,19 +29588,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)
@@ -29807,27 +30059,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)
@@ -29836,7 +30170,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))
@@ -29911,11 +30244,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++) {
@@ -29937,11 +30266,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,
@@ -29951,11 +30276,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)
@@ -30061,6 +30382,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) {
@@ -30159,14 +30488,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;
@@ -37970,7 +38295,7 @@ static __exception int JS_ObjectDefineProperties(JSContext *ctx,
ret = 0;
exception:
- js_free_prop_enum(ctx, atoms, len);
+ JS_FreePropertyEnum(ctx, atoms, len);
JS_FreeValue(ctx, props);
JS_FreeValue(ctx, desc);
return ret;
@@ -38241,12 +38566,12 @@ static JSValue js_object_getOwnPropertyDescriptors(JSContext *ctx, JSValueConst
goto exception;
}
}
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
JS_FreeValue(ctx, obj);
return r;
exception:
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
JS_FreeValue(ctx, obj);
JS_FreeValue(ctx, r);
return JS_EXCEPTION;
@@ -38326,7 +38651,7 @@ exception:
JS_FreeValue(ctx, r);
r = JS_EXCEPTION;
done:
- js_free_prop_enum(ctx, atoms, len);
+ JS_FreePropertyEnum(ctx, atoms, len);
JS_FreeValue(ctx, obj);
return r;
}
@@ -38587,11 +38912,11 @@ static JSValue js_object_seal(JSContext *ctx, JSValueConst this_val,
JS_UNDEFINED, JS_UNDEFINED, desc_flags) < 0)
goto exception;
}
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
return JS_DupValue(ctx, obj);
exception:
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
return JS_EXCEPTION;
}
@@ -38633,11 +38958,11 @@ static JSValue js_object_isSealed(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION;
res ^= 1;
done:
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
return JS_NewBool(ctx, res);
exception:
- js_free_prop_enum(ctx, props, len);
+ JS_FreePropertyEnum(ctx, props, len);
return JS_EXCEPTION;
}
@@ -45966,7 +46291,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
goto fail;
}
}
- js_free_prop_enum(ctx, atoms, len);
+ JS_FreePropertyEnum(ctx, atoms, len);
atoms = NULL;
name_val = JS_AtomToValue(ctx, name);
if (JS_IsException(name_val))
@@ -45978,7 +46303,7 @@ static JSValue internalize_json_property(JSContext *ctx, JSValueConst holder,
JS_FreeValue(ctx, val);
return res;
fail:
- js_free_prop_enum(ctx, atoms, len);
+ JS_FreePropertyEnum(ctx, atoms, len);
JS_FreeValue(ctx, val);
return JS_EXCEPTION;
}
@@ -47352,14 +47677,14 @@ static int js_proxy_get_own_property_names(JSContext *ctx,
}
}
- js_free_prop_enum(ctx, tab2, len2);
+ JS_FreePropertyEnum(ctx, tab2, len2);
JS_FreeValue(ctx, prop_array);
*ptab = tab;
*plen = len;
return 0;
fail:
- js_free_prop_enum(ctx, tab2, len2);
- js_free_prop_enum(ctx, tab, len);
+ JS_FreePropertyEnum(ctx, tab2, len2);
+ JS_FreePropertyEnum(ctx, tab, len);
JS_FreeValue(ctx, prop_array);
return -1;
}