#include "cell.h" #include /* JSON uses JS_KEY_empty for reviver — define locally from public constants */ #ifndef JS_KEY_empty #define JS_KEY_empty ((JSValue)JS_TAG_STRING_IMM) #endif static JSValue js_cell_json_encode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { if (argc < 1) return JS_RaiseDisrupt (ctx, "json.encode requires at least 1 argument"); int pretty = argc <= 1 || JS_ToBool (ctx, argv[1]); JSValue space = pretty ? JS_NewInt32 (ctx, 2) : JS_NULL; JSValue replacer = JS_NULL; if (argc > 2 && JS_IsFunction (argv[2])) replacer = argv[2]; else if (argc > 3 && JS_IsArray (argv[3])) replacer = argv[3]; JSValue result = JS_JSONStringify (ctx, argv[0], replacer, space, pretty); return result; } static JSValue js_cell_json_decode (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) { if (argc < 1) return JS_RaiseDisrupt (ctx, "json.decode requires at least 1 argument"); if (!JS_IsText (argv[0])) return JS_RaiseDisrupt (ctx, "couldn't parse text: not a string"); const char *str = JS_ToCString (ctx, argv[0]); if (!str) return JS_EXCEPTION; size_t len = strlen (str); JSValue result = JS_ParseJSON (ctx, str, len, ""); JS_FreeCString (ctx, str); /* Apply reviver if provided */ if (argc > 1 && JS_IsFunction (argv[1]) && !JS_IsException (result)) { /* Create wrapper object to pass to reviver */ JSValue wrapper = JS_NewObject (ctx); JS_SetPropertyStr (ctx, wrapper, "", result); JSValue holder = wrapper; JSValue key = JS_KEY_empty; JSValue args[2] = { key, JS_GetProperty (ctx, holder, key) }; JSValue final = JS_Call (ctx, argv[1], holder, 2, args); result = final; } return result; } static const JSCFunctionListEntry js_cell_json_funcs[] = { JS_CFUNC_DEF ("encode", 4, js_cell_json_encode), JS_CFUNC_DEF ("decode", 2, js_cell_json_decode), }; JSValue js_core_json_use (JSContext *ctx) { JSGCRef obj_ref; JS_PushGCRef (ctx, &obj_ref); obj_ref.val = JS_NewObject (ctx); JS_SetPropertyFunctionList (ctx, obj_ref.val, js_cell_json_funcs, countof (js_cell_json_funcs)); JSValue result = obj_ref.val; JS_PopGCRef (ctx, &obj_ref); return result; }