Documentation Index
Fetch the complete documentation index at: https://mintlify.com/quickjs-ng/quickjs/llms.txt
Use this file to discover all available pages before exploring further.
ES6 Modules
QuickJS has full support for ES6 modules, including dynamic imports, import attributes, and custom module loaders.
Module Loader Functions
JS_SetModuleLoaderFunc
Set the module loader for a runtime.
void JS_SetModuleLoaderFunc(JSRuntime *rt,
JSModuleNormalizeFunc *module_normalize,
JSModuleLoaderFunc *module_loader, void *opaque);
Function Type Definitions
// Return the module specifier (allocated with js_malloc()) or NULL if exception
typedef char *JSModuleNormalizeFunc(JSContext *ctx,
const char *module_base_name,
const char *module_name, void *opaque);
typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
const char *module_name, void *opaque);
Parameters
rt - The JavaScript runtime
module_normalize - Function to normalize module names (can be NULL for default)
module_loader - Function to load modules
opaque - User data passed to loader functions
Example: Basic Module Loader
From quickjs-libc:
JSModuleDef *js_module_loader(JSContext *ctx,
const char *module_name, void *opaque,
JSValueConst attributes)
{
JSModuleDef *m;
size_t buf_len;
uint8_t *buf;
// Load file contents
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
JS_ThrowReferenceError(ctx, "could not load module '%s'", module_name);
return NULL;
}
// Check if it's JSON module
if (js_module_test_json(ctx, attributes)) {
JSValue val = JS_ParseJSON(ctx, (const char *)buf, buf_len, module_name);
js_free(ctx, buf);
if (JS_IsException(val))
return NULL;
m = JS_NewCModule(ctx, module_name, NULL);
if (!m) {
JS_FreeValue(ctx, val);
return NULL;
}
JS_SetModuleExport(ctx, m, "default", val);
return m;
}
// Compile as JavaScript module
JSValue 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;
js_module_set_import_meta(ctx, func_val, TRUE, FALSE);
return JS_VALUE_GET_PTR(func_val);
}
Import Attributes Support
JS_SetModuleLoaderFunc2
Set module loader with import attributes support.
void JS_SetModuleLoaderFunc2(JSRuntime *rt,
JSModuleNormalizeFunc *module_normalize,
JSModuleLoaderFunc2 *module_loader,
JSModuleCheckSupportedImportAttributes *module_check_attrs,
void *opaque);
Function Type Definitions
typedef JSModuleDef *JSModuleLoaderFunc2(JSContext *ctx,
const char *module_name, void *opaque,
JSValueConst attributes);
typedef int JSModuleCheckSupportedImportAttributes(JSContext *ctx, void *opaque,
JSValueConst attributes);
Example: JSON Module Import
// Import with type attribute
import data from './config.json' with { type: 'json' };
console.log(data);
int js_module_check_attributes(JSContext *ctx, void *opaque,
JSValueConst attributes)
{
JSValue type = JS_GetPropertyStr(ctx, attributes, "type");
const char *type_str = JS_ToCString(ctx, type);
int ret = 0;
if (type_str && strcmp(type_str, "json") != 0) {
JS_ThrowTypeError(ctx, "unsupported import attribute type '%s'", type_str);
ret = -1;
}
JS_FreeCString(ctx, type_str);
JS_FreeValue(ctx, type);
return ret;
}
C Modules
JS_NewCModule
Create a new C module.
JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
JSModuleInitFunc *func);
Parameters
ctx - The JavaScript context
name_str - Module name
func - Initialization function (called when module is first imported)
Returns
Returns a module definition, or NULL on error.
Example: Creating a C Module
From examples/fib.c:
static JSValue js_fib(JSContext *ctx, JSValue this_val,
int argc, JSValue *argv)
{
int n, res;
if (JS_ToInt32(ctx, &n, argv[0]))
return JS_EXCEPTION;
res = fib(n);
return JS_NewInt32(ctx, res);
}
static const JSCFunctionListEntry js_fib_funcs[] = {
JS_CFUNC_DEF("fib", 1, js_fib),
};
static int js_fib_init(JSContext *ctx, JSModuleDef *m)
{
return JS_SetModuleExportList(ctx, m, js_fib_funcs,
countof(js_fib_funcs));
}
JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
{
JSModuleDef *m;
m = JS_NewCModule(ctx, module_name, js_fib_init);
if (!m)
return NULL;
JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs));
return m;
}
JS_AddModuleExport
Declare a module export (before instantiation).
int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
JS_AddModuleExportList
Declare multiple module exports.
int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
const JSCFunctionListEntry *tab, int len);
JS_SetModuleExport
Set the value of a module export (after instantiation).
int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
JSValue val);
JS_SetModuleExportList
Set multiple module export values.
int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
const JSCFunctionListEntry *tab, int len);
Get the import.meta object for a module.
JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
From quickjs-libc:
int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
bool use_realpath, bool is_main)
{
JSModuleDef *m;
char buf[PATH_MAX + 16];
JSValue meta_obj;
JSAtom module_name_atom;
const char *module_name;
m = JS_VALUE_GET_PTR(func_val);
module_name_atom = JS_GetModuleName(ctx, m);
module_name = JS_AtomToCString(ctx, module_name_atom);
JS_FreeAtom(ctx, module_name_atom);
if (!module_name)
return -1;
meta_obj = JS_GetImportMeta(ctx, m);
if (JS_IsException(meta_obj))
goto fail;
JS_DefinePropertyValueStr(ctx, meta_obj, "url",
JS_NewString(ctx, module_name),
JS_PROP_C_W_E);
JS_DefinePropertyValueStr(ctx, meta_obj, "main",
JS_NewBool(ctx, is_main),
JS_PROP_C_W_E);
JS_FreeValue(ctx, meta_obj);
JS_FreeCString(ctx, module_name);
return 0;
fail:
JS_FreeCString(ctx, module_name);
return -1;
}
JS_GetModuleName
Get the name of a module.
JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
JS_GetModuleNamespace
Get the namespace object of a module.
JSValue JS_GetModuleNamespace(JSContext *ctx, JSModuleDef *m);
Dynamic Import
Dynamic imports are handled automatically by the module loader:
// JavaScript code
const module = await import('./my-module.js');
console.log(module.default);
The module loader function is called when the import executes.
Complete Example
#include <quickjs.h>
#include <quickjs-libc.h>
int main(int argc, char **argv)
{
JSRuntime *rt = JS_NewRuntime();
JSContext *ctx = JS_NewContext(rt);
// Set up module loader
JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader,
js_module_check_attributes, NULL);
// Add standard helpers
js_std_add_helpers(ctx, argc, argv);
// Load and execute a module
const char *module_code =
"import { fib } from './fib.so';\n"
"console.log('fib(10) =', fib(10));";
JSValue result = JS_Eval(ctx, module_code, strlen(module_code),
"main.js", JS_EVAL_TYPE_MODULE);
if (JS_IsException(result)) {
js_std_dump_error(ctx);
}
JS_FreeValue(ctx, result);
// Run pending jobs (for async operations)
js_std_loop(ctx);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
Notes
- Module loader functions are called per runtime, not per context
- Use
JS_EVAL_TYPE_MODULE flag when evaluating module code
- C modules can be dynamically loaded as
.so/.dll files
- Import attributes (formerly “import assertions”) are supported
- The default normalizer resolves relative paths
import.meta.url and import.meta.main are commonly set by loaders