From: Fabrice Bellard Date: Mon, 2 Nov 2026 13:41:45 +0000 (+0100) Subject: added support of the import-text proposal (initial patch by bnoordhuis) - take into... X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=28e801a4d3e65f84b4f6c42ea0547bf5ef7b44cf;p=quickjs.git added support of the import-text proposal (initial patch by bnoordhuis) - take into account the attributes with comparing modules (initial patch by Divy Srivastava) --- diff --git a/examples/hello_module.js b/examples/hello_module.js index 5d4c78e..b53c107 100644 --- a/examples/hello_module.js +++ b/examples/hello_module.js @@ -2,7 +2,9 @@ import { fib } from "./fib_module.js"; import msg from "./message.json"; +import msg2 from "./message.json" with { type: "text" }; console.log("Hello World"); console.log("fib(10)=", fib(10)); console.log("msg=", msg); +console.log("msg2=", msg2); diff --git a/examples/message.json b/examples/message.json index 3b7fe48..9329157 100644 --- a/examples/message.json +++ b/examples/message.json @@ -1,2 +1 @@ { "x" : 1, "tab": [ 1, 2, 3 ] } - diff --git a/qjsc.c b/qjsc.c index 7250f0f..9493a8c 100644 --- a/qjsc.c +++ b/qjsc.c @@ -176,7 +176,7 @@ static void dump_hex(FILE *f, const uint8_t *buf, size_t len) typedef enum { CNAME_TYPE_SCRIPT, CNAME_TYPE_MODULE, - CNAME_TYPE_JSON_MODULE, + CNAME_TYPE_DATA_MODULE, } CNameTypeEnum; static void output_object_code(JSContext *ctx, @@ -187,7 +187,7 @@ static void output_object_code(JSContext *ctx, size_t out_buf_len; int flags; - if (c_name_type == CNAME_TYPE_JSON_MODULE) + if (c_name_type == CNAME_TYPE_DATA_MODULE) flags = 0; else flags = JS_WRITE_OBJ_BYTECODE; @@ -264,8 +264,13 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, size_t buf_len; uint8_t *buf; char cname[1024]; - int res; + int type; + JSValue val; + type = js_module_import_type(ctx, attributes); + if (type < 0) + return NULL; + buf = js_load_file(ctx, &buf_len, module_name); if (!buf) { JS_ThrowReferenceError(ctx, "could not load module filename '%s'", @@ -273,20 +278,49 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, return NULL; } - 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; + if (type == JS_IMPORT_TYPE_JS) { + if (has_suffix(module_name, ".json")) + type = JS_IMPORT_TYPE_JSON; + } + + switch(type) { + case JS_IMPORT_TYPE_JS: + val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + break; + case JS_IMPORT_TYPE_JSON: + case JS_IMPORT_TYPE_JSON5: + { + int flags; + if (type == JS_IMPORT_TYPE_JSON5) + flags = JS_PARSE_JSON_EXT; + else + flags = 0; + val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags); + } + break; + case JS_IMPORT_TYPE_TEXT: + val = JS_NewStringLen(ctx, (char *)buf, buf_len); + break; + default: + val = JS_ThrowInternalError(ctx, "unhandled import type"); + break; + } + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + + if (type == JS_IMPORT_TYPE_JS) { + 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, val, cname, CNAME_TYPE_MODULE); + + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(val); + JS_FreeValue(ctx, val); + } else { /* create a dummy module */ m = JS_NewCModule(ctx, module_name, js_module_dummy_init); if (!m) { @@ -305,26 +339,8 @@ JSModuleDef *jsc_module_loader(JSContext *ctx, dump_hex(outfile, (const uint8_t *)module_name, strlen(module_name) + 1); fprintf(outfile, "};\n\n"); - output_object_code(ctx, outfile, val, cname, CNAME_TYPE_JSON_MODULE); + output_object_code(ctx, outfile, val, cname, CNAME_TYPE_DATA_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; @@ -850,8 +866,8 @@ int main(int argc, char **argv) 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", + } else if (e->flags == CNAME_TYPE_DATA_MODULE) { + fprintf(fo, " js_std_eval_binary_data_module(ctx, %s, %s_size, (const char *)%s_module_name);\n", e->name, e->name, e->name); } } diff --git a/quickjs-libc.c b/quickjs-libc.c index a180d83..9eec1a0 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -609,7 +609,7 @@ static int json_module_init(JSContext *ctx, JSModuleDef *m) return 0; } -static JSModuleDef *create_json_module(JSContext *ctx, const char *module_name, JSValue val) +static JSModuleDef *create_data_module(JSContext *ctx, const char *module_name, JSValue val) { JSModuleDef *m; m = JS_NewCModule(ctx, module_name, json_module_init); @@ -655,8 +655,8 @@ int js_module_check_attributes(JSContext *ctx, void *opaque, return ret; } -/* return > 0 if the attributes indicate a JSON module */ -int js_module_test_json(JSContext *ctx, JSValueConst attributes) +/* return the module type according to 'attributes' or -1 if error */ +int js_module_import_type(JSContext *ctx, JSValueConst attributes) { JSValue str; const char *cstr; @@ -664,21 +664,27 @@ int js_module_test_json(JSContext *ctx, JSValueConst attributes) BOOL res; if (JS_IsUndefined(attributes)) - return FALSE; + return JS_IMPORT_TYPE_JS; str = JS_GetPropertyStr(ctx, attributes, "type"); + if (JS_IsException(str)) + return -1; if (!JS_IsString(str)) - return FALSE; + return JS_IMPORT_TYPE_JS; cstr = JS_ToCStringLen(ctx, &len, str); JS_FreeValue(ctx, str); if (!cstr) - return FALSE; + return -1; /* XXX: raise an error if unknown type ? */ if (len == 4 && !memcmp(cstr, "json", len)) { - res = 1; + res = JS_IMPORT_TYPE_JSON; } else if (len == 5 && !memcmp(cstr, "json5", len)) { - res = 2; + res = JS_IMPORT_TYPE_JSON5; + } else if (len == 4 && !memcmp(cstr, "text", len)) { + res = JS_IMPORT_TYPE_TEXT; } else { - res = 0; + /* unknown type - throw error */ + JS_ThrowTypeError(ctx, "unsupported module type: '%s'", cstr); + res = -1; } JS_FreeCString(ctx, cstr); return res; @@ -689,13 +695,18 @@ JSModuleDef *js_module_loader(JSContext *ctx, 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; + int type; + JSValue val; + + type = js_module_import_type(ctx, attributes); + if (type < 0) + return NULL; buf = js_load_file(ctx, &buf_len, module_name); if (!buf) { @@ -703,35 +714,50 @@ JSModuleDef *js_module_loader(JSContext *ctx, module_name); return NULL; } - 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; + + /* the .json suffix only selects the JSON type when no type attribute + was given, so that e.g. 'with { type: "text" }' is honored */ + if (type == JS_IMPORT_TYPE_JS) { + if (has_suffix(module_name, ".json")) + type = JS_IMPORT_TYPE_JSON; + } + + switch(type) { + case JS_IMPORT_TYPE_JS: + val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + break; + case JS_IMPORT_TYPE_JSON: + case JS_IMPORT_TYPE_JSON5: + { + int flags; + if (type == JS_IMPORT_TYPE_JSON5) + flags = JS_PARSE_JSON_EXT; + else + flags = 0; + val = JS_ParseJSON2(ctx, (char *)buf, buf_len, module_name, flags); + } + break; + case JS_IMPORT_TYPE_TEXT: + val = JS_NewStringLen(ctx, (char *)buf, buf_len); + break; + default: + val = JS_ThrowInternalError(ctx, "unhandled import type"); + break; + } + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + + if (type == JS_IMPORT_TYPE_JS) { + js_module_set_import_meta(ctx, val, TRUE, FALSE); + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(val); + 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)) + m = create_data_module(ctx, module_name, val); + if (!m) 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; @@ -4449,7 +4475,7 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, } } -void js_std_eval_binary_json_module(JSContext *ctx, +void js_std_eval_binary_data_module(JSContext *ctx, const uint8_t *buf, size_t buf_len, const char *module_name) { @@ -4459,7 +4485,7 @@ void js_std_eval_binary_json_module(JSContext *ctx, obj = JS_ReadObject(ctx, buf, buf_len, 0); if (JS_IsException(obj)) goto exception; - m = create_json_module(ctx, module_name, obj); + m = create_data_module(ctx, module_name, obj); if (!m) { exception: js_std_dump_error(ctx); diff --git a/quickjs-libc.h b/quickjs-libc.h index 5c8301b..2083684 100644 --- a/quickjs-libc.h +++ b/quickjs-libc.h @@ -44,14 +44,21 @@ 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); +enum { + JS_IMPORT_TYPE_JS, + JS_IMPORT_TYPE_JSON, + JS_IMPORT_TYPE_JSON5, + JS_IMPORT_TYPE_TEXT, +}; +int js_module_import_type(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, 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, +void js_std_eval_binary_data_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, diff --git a/quickjs.c b/quickjs.c index ff19e03..3f20616 100644 --- a/quickjs.c +++ b/quickjs.c @@ -916,6 +916,7 @@ struct JSModuleDef { int import_entries_count; int import_entries_size; + JSValue attributes; JSValue module_ns; JSValue func_obj; /* only used for JS modules */ JSModuleInitFunc *init_func; /* only used for C modules */ @@ -30633,6 +30634,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->resolving_funcs[0] = JS_UNDEFINED; m->resolving_funcs[1] = JS_UNDEFINED; m->private_value = JS_UNDEFINED; + m->attributes = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -30663,6 +30665,7 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, 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); + JS_MarkValue(rt, m->attributes, mark_func); } static void js_free_module_def(JSRuntime *rt, JSModuleDef *m) @@ -30704,6 +30707,7 @@ static void js_free_module_def(JSRuntime *rt, JSModuleDef *m) JS_FreeValueRT(rt, m->resolving_funcs[0]); JS_FreeValueRT(rt, m->resolving_funcs[1]); JS_FreeValueRT(rt, m->private_value); + JS_FreeValueRT(rt, m->attributes); /* during the GC the finalizers are called in an arbitrary order so the module may no longer be referenced by the JSContext list */ if (m->link.next) { @@ -30718,7 +30722,7 @@ static void js_free_module_def(JSRuntime *rt, JSModuleDef *m) } static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, - JSAtom module_name) + JSAtom module_name, JSValueConst attributes) { JSReqModuleEntry *rme; @@ -30730,7 +30734,7 @@ 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; - rme->attributes = JS_UNDEFINED; + rme->attributes = JS_DupValue(ctx, attributes); return m->req_module_entries_count - 1; } @@ -30947,7 +30951,68 @@ static char *js_default_module_normalize_name(JSContext *ctx, return filename; } -static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) +/* the objects are assumed to be normal objects with string properties */ +static BOOL js_module_attributes_equal(JSContext *ctx, JSValueConst attr1, + JSValueConst attr2) +{ + JSObject *p1, *p2; + int len1, len2, i; + JSShapeProperty *prs1, *prs2; + JSProperty *pr1, *pr2; + JSShape *sh; + + if (JS_IsObject(attr1)) { + p1 = JS_VALUE_GET_OBJ(attr1); + len1 = p1->shape->prop_count - p1->shape->deleted_prop_count; + } else { + p1 = NULL; + len1 = 0; + } + + if (JS_IsObject(attr2)) { + p2 = JS_VALUE_GET_OBJ(attr2); + len2 = p2->shape->prop_count - p2->shape->deleted_prop_count; + } else { + p2 = NULL; + len2 = 0; + } + + if (len1 != len2) + return FALSE; + if (len1 == 0) + return TRUE; + sh = p1->shape; + for(i = 0, prs1 = get_shape_prop(sh); i < sh->prop_count; + i++, prs1++) { + if (prs1->atom != JS_ATOM_NULL) { + assert((prs1->flags & JS_PROP_TMASK) == 0); + prs2 = find_own_property(&pr2, p2, prs1->atom); + if (!prs2) + return FALSE; + assert((prs2->flags & JS_PROP_TMASK) == 0); + pr1 = &p1->prop[i]; + if (!js_same_value(ctx, pr1->u.value, pr2->u.value)) + return FALSE; + } + } + return TRUE; +} + +static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name, JSValueConst attributes) +{ + struct list_head *el; + JSModuleDef *m; + + /* first look at the loaded modules */ + list_for_each(el, &ctx->loaded_modules) { + m = list_entry(el, JSModuleDef, link); + if (m->module_name == name && js_module_attributes_equal(ctx, m->attributes, attributes)) + return m; + } + return NULL; +} + +static JSModuleDef *js_find_loaded_module_by_name(JSContext *ctx, JSAtom name) { struct list_head *el; JSModuleDef *m; @@ -30988,7 +31053,7 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, } /* first look at the loaded modules */ - m = js_find_loaded_module(ctx, module_name); + m = js_find_loaded_module(ctx, module_name, attributes); if (m) { js_free(ctx, cname); JS_FreeAtom(ctx, module_name); @@ -31010,6 +31075,10 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, } else { m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque); } + if (m) { + assert(JS_IsUndefined(m->attributes)); + m->attributes = JS_DupValue(ctx, attributes); + } js_free(ctx, cname); return m; } @@ -31877,7 +31946,7 @@ static JSValue js_import_meta(JSContext *ctx) /* XXX: inefficient, need to add a module or script pointer in JSFunctionBytecode */ - m = js_find_loaded_module(ctx, filename); + m = js_find_loaded_module_by_name(ctx, filename); JS_FreeAtom(ctx, filename); if (!m) { fail: @@ -32552,74 +32621,81 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) return JS_DupValue(ctx, m->promise); } -static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme) +static __exception JSValue js_parse_with_clause(JSParseState *s) { JSContext *ctx = s->ctx; JSAtom key; int ret; const uint8_t *key_token_ptr; + JSValue attributes = JS_UNDEFINED; if (next_token(s)) - return -1; + goto fail; if (js_parse_expect(s, '{')) - return -1; + goto fail; 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; + goto fail; } else { if (!token_is_ident(s->token.val)) { js_parse_error(s, "identifier expected"); - return -1; + goto fail; } key = JS_DupAtom(ctx, s->token.u.ident.atom); } if (next_token(s)) - return -1; + goto fail; if (js_parse_expect(s, ':')) { JS_FreeAtom(ctx, key); - return -1; + goto fail; } if (s->token.val != TOK_STRING) { js_parse_error_pos(s, key_token_ptr, "string expected"); - return -1; + goto fail; } - if (JS_IsUndefined(rme->attributes)) { - JSValue attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsUndefined(attributes)) { + attributes = JS_NewObjectProto(ctx, JS_NULL); if (JS_IsException(attributes)) { JS_FreeAtom(ctx, key); - return -1; + goto fail; } - rme->attributes = attributes; } - ret = JS_HasProperty(ctx, rme->attributes, key); + ret = JS_HasProperty(ctx, attributes, key); if (ret != 0) { JS_FreeAtom(ctx, key); - if (ret < 0) - return -1; - else - return js_parse_error(s, "duplicate with key"); + if (ret < 0) { + goto fail; + } else { + js_parse_error(s, "duplicate with key"); + goto fail; + } } - ret = JS_DefinePropertyValue(ctx, rme->attributes, key, + ret = JS_DefinePropertyValue(ctx, attributes, key, JS_DupValue(ctx, s->token.u.str.str), JS_PROP_C_W_E); JS_FreeAtom(ctx, key); if (ret < 0) - return -1; + goto fail; if (next_token(s)) - return -1; + goto fail; if (s->token.val != ',') break; if (next_token(s)) - return -1; + goto fail; } - if (!JS_IsUndefined(rme->attributes) && + if (!JS_IsUndefined(attributes) && ctx->rt->module_check_attrs && - ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) { - return -1; + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, attributes) < 0) { + goto fail; } - return js_parse_expect(s, '}'); + if (js_parse_expect(s, '}')) + goto fail; + return attributes; + fail: + JS_FreeValue(ctx, attributes); + return JS_EXCEPTION; } /* return the module index in m->req_module_entries[] or < 0 if error */ @@ -32627,7 +32703,8 @@ static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) { JSAtom module_name; int idx; - + JSValue attributes; + if (!token_is_pseudo_keyword(s, JS_ATOM_from)) { js_parse_error(s, "from clause expected"); return -1; @@ -32645,15 +32722,19 @@ static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) JS_FreeAtom(s->ctx, module_name); return -1; } - - idx = add_req_module_entry(s->ctx, m, module_name); - JS_FreeAtom(s->ctx, module_name); - if (idx < 0) - return -1; + attributes = JS_UNDEFINED; if (s->token.val == TOK_WITH) { - if (js_parse_with_clause(s, &m->req_module_entries[idx])) + attributes = js_parse_with_clause(s); + if (JS_IsException(attributes)) { + JS_FreeAtom(s->ctx, module_name); return -1; + } } + idx = add_req_module_entry(s->ctx, m, module_name, attributes); + JS_FreeAtom(s->ctx, module_name); + JS_FreeValue(s->ctx, attributes); + if (idx < 0) + return -1; return idx; } @@ -32893,6 +32974,7 @@ static __exception int js_parse_import(JSParseState *s) first_import = m->import_entries_count; if (s->token.val == TOK_STRING) { + JSValue attributes; module_name = JS_ValueToAtom(ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) return -1; @@ -32900,14 +32982,19 @@ 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; + attributes = JS_UNDEFINED; if (s->token.val == TOK_WITH) { - if (js_parse_with_clause(s, &m->req_module_entries[idx])) + attributes = js_parse_with_clause(s); + if (JS_IsException(attributes)) { + JS_FreeAtom(s->ctx, module_name); return -1; + } } + idx = add_req_module_entry(ctx, m, module_name, attributes); + JS_FreeAtom(ctx, module_name); + JS_FreeValue(ctx, attributes); + if (idx < 0) + return -1; } else { if (s->token.val == TOK_IDENT) { if (s->token.u.ident.is_reserved) { diff --git a/run-test262.c b/run-test262.c index f5ff048..9cc8de5 100644 --- a/run-test262.c +++ b/run-test262.c @@ -1014,7 +1014,9 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, uint8_t *buf; JSModuleDef *m; char *filename, *slash, path[1024]; - + int type; + JSValue val; + // interpret import("bar.js") from path/to/foo.js as // import("path/to/bar.js") but leave import("./bar.js") untouched filename = opaque; @@ -1027,6 +1029,10 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, } } + type = js_module_import_type(ctx, attributes); + if (type < 0) + return NULL; + buf = js_load_file(ctx, &buf_len, module_name); if (!buf) { JS_ThrowReferenceError(ctx, "could not load module filename '%s'", @@ -1034,13 +1040,31 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, return NULL; } - if (js_module_test_json(ctx, attributes) == 1) { - /* compile as JSON */ - JSValue val; + switch(type) { + case JS_IMPORT_TYPE_JS: + val = JS_Eval(ctx, (char *)buf, buf_len, module_name, + JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); + break; + case JS_IMPORT_TYPE_JSON: val = JS_ParseJSON(ctx, (char *)buf, buf_len, module_name); - js_free(ctx, buf); - if (JS_IsException(val)) - return NULL; + break; + case JS_IMPORT_TYPE_TEXT: + val = JS_NewStringLen(ctx, (char *)buf, buf_len); + break; + default: + val = JS_ThrowInternalError(ctx, "unhandled import type"); + break; + } + + js_free(ctx, buf); + if (JS_IsException(val)) + return NULL; + + if (type == JS_IMPORT_TYPE_JS) { + /* the module is already referenced, so we must free it */ + m = JS_VALUE_GET_PTR(val); + JS_FreeValue(ctx, val); + } else { m = JS_NewCModule(ctx, module_name, json_module_init_test); if (!m) { JS_FreeValue(ctx, val); @@ -1049,17 +1073,6 @@ static JSModuleDef *js_module_loader_test(JSContext *ctx, /* 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; } diff --git a/test262.conf b/test262.conf index f0bfc68..004ff77 100644 --- a/test262.conf +++ b/test262.conf @@ -123,7 +123,7 @@ immutable-arraybuffer=skip import-attributes import-bytes=skip import-defer=skip -import-text=skip +import-text import.meta joint-iteration Int16Array