Skip to main content

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);

Module Metadata

JS_GetImportMeta

Get the import.meta object for a module.
JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);

Example: Setting import.meta

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