@@ -62,14 +62,7 @@ static JSValue buf_empty_error(JSContext *ctx, uint8_t *buf, bool is_file, QJSEv
6262static JSValue load_buf (JSContext * ctx , QJSEvalOptions opts , int flags , bool eval )
6363{
6464 bool is_file = input_is_file (opts );
65- // bool has_filename = opts.filename && opts.filename[0] != '\0';
66- // bool invalid_file = is_file && (!has_filename || !file_exists(opts.filename));
67-
68- // if (invalid_file)
69- // return JS_ThrowReferenceError(ctx, "file does not exist: %s", opts.filename);
70-
7165 size_t buf_len = 0 ;
72- // char *filename;
7366 uint8_t * buf = detect_buf (ctx , & opts , & buf_len , is_file );
7467 if (buf == NULL )
7568 return buf_empty_error (ctx , buf , is_file , & opts );
@@ -93,18 +86,92 @@ static JSValue load_buf(JSContext *ctx, QJSEvalOptions opts, int flags, bool eva
9386 return module_val ;
9487}
9588
96- // static JSValue qjs_eval_global(JSContext *ctx, QJSEvalOptions opts)
97- // {
98- // return load_buf(ctx, opts, opts.eval_flags, true);
99- // }
89+ /* Create a JSON module with the parsed JSON as default export */
90+ static JSModuleDef * js_module_loader_json (JSContext * ctx , const char * module_name )
91+ {
92+ JSModuleDef * m ;
93+ size_t buf_len ;
94+ uint8_t * buf ;
95+ JSValue json_val , func_val ;
96+
97+ buf = js_load_file (ctx , & buf_len , module_name );
98+ if (!buf )
99+ {
100+ JS_ThrowReferenceError (ctx , "could not load JSON module filename '%s'" , module_name );
101+ return NULL ;
102+ }
103+
104+ /* Parse the JSON content */
105+ json_val = JS_ParseJSON (ctx , (char * )buf , buf_len , module_name );
106+ js_free (ctx , buf );
107+ if (JS_IsException (json_val ))
108+ return NULL ;
109+
110+ /* Create a synthetic module source that exports the JSON */
111+ const char * module_source_template =
112+ "const __json_data__ = %s;\n"
113+ "export default __json_data__;\n" ;
114+
115+ /* Convert JSON to string */
116+ JSValue json_str = JS_JSONStringify (ctx , json_val , JS_NULL , JS_NULL );
117+ if (JS_IsException (json_str ))
118+ {
119+ JS_FreeValue (ctx , json_val );
120+ return NULL ;
121+ }
122+
123+ const char * json_string = JS_ToCString (ctx , json_str );
124+ if (!json_string )
125+ {
126+ JS_FreeValue (ctx , json_val );
127+ JS_FreeValue (ctx , json_str );
128+ return NULL ;
129+ }
100130
101- /* Module loader with support for appending common suffixes */
131+ /* Create the module source */
132+ size_t source_len = strlen (module_source_template ) + strlen (json_string ) + 1 ;
133+ char * module_source = malloc (source_len );
134+ snprintf (module_source , source_len , module_source_template , json_string );
135+
136+ /* Compile the module */
137+ func_val = JS_Eval (ctx , module_source , strlen (module_source ), module_name ,
138+ JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY );
139+
140+ /* Cleanup */
141+ free (module_source );
142+ JS_FreeCString (ctx , json_string );
143+ JS_FreeValue (ctx , json_str );
144+ JS_FreeValue (ctx , json_val );
145+
146+ if (JS_IsException (func_val ))
147+ return NULL ;
148+
149+ /* Set import.meta */
150+ if (js_module_set_import_meta (ctx , func_val , true, false) < 0 )
151+ {
152+ JS_FreeValue (ctx , func_val );
153+ return NULL ;
154+ }
155+
156+ /* Return the compiled module */
157+ m = JS_VALUE_GET_PTR (func_val );
158+ JS_FreeValue (ctx , func_val );
159+ return m ;
160+ }
161+
162+ /* Module loader with support for appending common suffixes and JSON modules */
102163JSModuleDef * QJS_ModuleLoader (JSContext * ctx , const char * module_name , void * opaque )
103164{
104165 module_name = detect_entry_point ((char * )module_name );
105166 if (!module_name )
106167 return NULL ;
107168
169+ /* Check if it's a JSON module */
170+ if (js__has_suffix (module_name , ".json" ))
171+ {
172+ return js_module_loader_json (ctx , module_name );
173+ }
174+
108175 JSModuleDef * mod = js_module_loader (ctx , module_name , opaque );
109176 return mod ;
110177}
@@ -258,7 +325,7 @@ unsigned char *QJS_Compile(JSContext *c, QJSEvalOptions opts, size_t *outSize)
258325/**
259326 * Compiles code (as a module or global script) to bytecode and returns a packed uint64_t value
260327 * containing both the bytecode's memory address (high 32 bits) and length (low 32 bits).
261- *
328+ *
262329 * Returns NULL on error.
263330 * NOTE: The caller must free both the returned uint64_t pointer and the bytecode memory it points to.
264331 */
@@ -277,7 +344,7 @@ uint64_t *QJS_Compile2(JSContext *ctx, QJSEvalOptions opts)
277344 free (bytecode );
278345 return NULL ; // Allocation failure
279346 }
280-
347+
281348 // Store the address of the bytecode in the high 32 bits and the length in the low 32 bits
282349 * result = ((uint64_t )(uintptr_t )bytecode << 32 ) | (uint32_t )bytecode_len ;
283350 return result ;
@@ -286,11 +353,12 @@ uint64_t *QJS_Compile2(JSContext *ctx, QJSEvalOptions opts)
286353QJSEvalOptions * QJS_CreateEvalOption (void * buf , uint8_t * bytecode_buf , size_t bytecode_len , char * filename , int eval_flags )
287354{
288355 QJSEvalOptions * opts = (QJSEvalOptions * )malloc (sizeof (QJSEvalOptions ));
289- if (opts == NULL ) {
356+ if (opts == NULL )
357+ {
290358 printf ("Error allocating memory for QJSEvalOptions\n" );
291359 return NULL ;
292360 }
293-
361+
294362 opts -> buf = buf ;
295363 opts -> bytecode_buf = bytecode_buf ;
296364 opts -> bytecode_len = bytecode_len ;
0 commit comments