summaryrefslogtreecommitdiff
path: root/quickjs-libc.c
diff options
context:
space:
mode:
Diffstat (limited to 'quickjs-libc.c')
-rw-r--r--quickjs-libc.c153
1 files changed, 137 insertions, 16 deletions
diff --git a/quickjs-libc.c b/quickjs-libc.c
index 03ce012..10a7d00 100644
--- a/quickjs-libc.c
+++ b/quickjs-libc.c
@@ -591,17 +591,101 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
return 0;
}
-JSModuleDef *js_module_loader(JSContext *ctx,
- const char *module_name, void *opaque)
+static int json_module_init(JSContext *ctx, JSModuleDef *m)
+{
+ JSValue val;
+ val = JS_GetModulePrivateValue(ctx, m);
+ JS_SetModuleExport(ctx, m, "default", val);
+ return 0;
+}
+
+static JSModuleDef *create_json_module(JSContext *ctx, const char *module_name, JSValue val)
{
JSModuleDef *m;
+ m = JS_NewCModule(ctx, module_name, json_module_init);
+ if (!m) {
+ JS_FreeValue(ctx, val);
+ return NULL;
+ }
+ /* only export the "default" symbol which will contain the JSON object */
+ JS_AddModuleExport(ctx, m, "default");
+ JS_SetModulePrivateValue(ctx, m, val);
+ return m;
+}
+
+/* in order to conform with the specification, only the keys should be
+ tested and not the associated values. */
+int js_module_check_attributes(JSContext *ctx, void *opaque,
+ JSValueConst attributes)
+{
+ JSPropertyEnum *tab;
+ uint32_t i, len;
+ int ret;
+ const char *cstr;
+ size_t cstr_len;
+
+ if (JS_GetOwnPropertyNames(ctx, &tab, &len, attributes, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK))
+ return -1;
+ ret = 0;
+ for(i = 0; i < len; i++) {
+ cstr = JS_AtomToCStringLen(ctx, &cstr_len, tab[i].atom);
+ if (!cstr) {
+ ret = -1;
+ break;
+ }
+ if (!(cstr_len == 4 && !memcmp(cstr, "type", cstr_len))) {
+ JS_ThrowTypeError(ctx, "import attribute '%s' is not supported", cstr);
+ ret = -1;
+ }
+ JS_FreeCString(ctx, cstr);
+ if (ret)
+ break;
+ }
+ JS_FreePropertyEnum(ctx, tab, len);
+ return ret;
+}
+/* return > 0 if the attributes indicate a JSON module */
+int js_module_test_json(JSContext *ctx, JSValueConst attributes)
+{
+ JSValue str;
+ const char *cstr;
+ size_t len;
+ BOOL res;
+
+ if (JS_IsUndefined(attributes))
+ return FALSE;
+ str = JS_GetPropertyStr(ctx, attributes, "type");
+ if (!JS_IsString(str))
+ return FALSE;
+ cstr = JS_ToCStringLen(ctx, &len, str);
+ JS_FreeValue(ctx, str);
+ if (!cstr)
+ return FALSE;
+ /* XXX: raise an error if unknown type ? */
+ if (len == 4 && !memcmp(cstr, "json", len)) {
+ res = 1;
+ } else if (len == 5 && !memcmp(cstr, "json5", len)) {
+ res = 2;
+ } else {
+ res = 0;
+ }
+ JS_FreeCString(ctx, cstr);
+ return res;
+}
+
+JSModuleDef *js_module_loader(JSContext *ctx,
+ const char *module_name, void *opaque,
+ 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;
- JSValue func_val;
buf = js_load_file(ctx, &buf_len, module_name);
if (!buf) {
@@ -609,18 +693,36 @@ JSModuleDef *js_module_loader(JSContext *ctx,
module_name);
return NULL;
}
-
- /* 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;
- /* 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);
+ 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;
+ } 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;
+ /* 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;
}
@@ -3478,7 +3580,7 @@ static void *worker_func(void *opaque)
JS_SetStripInfo(rt, args->strip_flags);
js_std_init_handlers(rt);
- JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
+ JS_SetModuleLoaderFunc2(rt, NULL, js_module_loader, js_module_check_attributes, NULL);
/* set the pipe to communicate with the parent */
ts = JS_GetRuntimeOpaque(rt);
@@ -4221,3 +4323,22 @@ void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
JS_FreeValue(ctx, val);
}
}
+
+void js_std_eval_binary_json_module(JSContext *ctx,
+ const uint8_t *buf, size_t buf_len,
+ const char *module_name)
+{
+ JSValue obj;
+ JSModuleDef *m;
+
+ obj = JS_ReadObject(ctx, buf, buf_len, 0);
+ if (JS_IsException(obj))
+ goto exception;
+ m = create_json_module(ctx, module_name, obj);
+ if (!m) {
+ exception:
+ js_std_dump_error(ctx);
+ exit(1);
+ }
+}
+