]> git.kaiwu.me - quickjs.git/commitdiff
added support of the import-text proposal (initial patch by bnoordhuis) - take into...
authorFabrice Bellard <fabrice@bellard.org>
Mon, 2 Nov 2026 13:41:45 +0000 (14:41 +0100)
committerFabrice Bellard <fabrice@bellard.org>
Mon, 2 Nov 2026 13:41:45 +0000 (14:41 +0100)
examples/hello_module.js
examples/message.json
qjsc.c
quickjs-libc.c
quickjs-libc.h
quickjs.c
run-test262.c
test262.conf

index 5d4c78ef28e1a4ca891197435c8e4f418c7c6b06..b53c1076bc5a1e62c226f12f79b7a670ceb37435 100644 (file)
@@ -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);
index 3b7fe4807468045ca5b16f34e17d1cb2f952daf5..9329157e55d1ead6909c30665e3b4e3ac1294aa0 100644 (file)
@@ -1,2 +1 @@
 { "x" : 1, "tab": [ 1, 2, 3 ] }
-
diff --git a/qjsc.c b/qjsc.c
index 7250f0f501d374b1f0c66bd1566090d8f6e430b2..9493a8cfc91c2bb9a47aaeb5f59ef8436e987b05 100644 (file)
--- 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);
             }
         }
index a180d832a958a41ec5929738e080c1038f495aa4..9eec1a0ea5980347d3b14ca8eab85755948d6d02 100644 (file)
@@ -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);
index 5c8301b7173a3c7c97cc177f5d53d2b2a48e64e9..20836846fcc74555f83b0d5b4384e23751ba6b59 100644 (file)
@@ -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,
index ff19e031fe9666d99dc6b5efdf59da3018f28b3b..3f206162c3cd7dd2cd6205afccb237e6caf9d728 100644 (file)
--- 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) {
index f5ff048f239056124ccf14b3f92221b71442e4db..9cc8de595e1cc5e354fe31b18ed0b80f0ad34bbb 100644 (file)
@@ -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;
 }
index f0bfc68246dec6235203bb4ce479b31670babc55..004ff7718ce7cbd3329ce3711a9012c3360448dc 100644 (file)
@@ -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