MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add support for JSON arrays in yyjson_to_jsval

+185 -11
+2 -2
.github/workflows/build.yml
··· 94 94 mkdir -p zipped 95 95 for dir in artifacts/*/; do 96 96 name=$(basename "$dir") 97 - (cd "$dir" && zip -r "../../zipped/${name}.zip" .) 97 + (cd "$dir" && zip -rX "../../zipped/${name}.zip" .) 98 98 done 99 - (cd zipped && zip -r ../ant-all-platforms.zip .) 99 + (cd zipped && zip -rX ../ant-all-platforms.zip .) 100 100 - uses: actions/upload-artifact@v4 101 101 with: 102 102 name: ant-all-platforms
+55
examples/jsondb/index.js
··· 1 + import JSONdb from './jsondb.js'; 2 + import { unlinkSync } from 'fs'; 3 + 4 + const db = new JSONdb('./mydata.json'); 5 + 6 + db.set('username', 'alice'); 7 + db.set('score', 42); 8 + db.set('settings', { 9 + theme: 'dark', 10 + notifications: true, 11 + language: 'en' 12 + }); 13 + db.set('tags', ['javascript', 'nodejs', 'database']); 14 + 15 + console.log('Username:', db.get('username')); 16 + console.log('Score:', db.get('score')); 17 + console.log('Settings:', db.get('settings')); 18 + 19 + console.log('Has username?', db.has('username')); 20 + console.log('Has email?', db.has('email')); 21 + 22 + console.log('Email:', db.get('email')); 23 + 24 + db.set('score', 100); 25 + console.log('New score:', db.get('score')); 26 + 27 + db.delete('tags'); 28 + console.log('Has tags?', db.has('tags')); 29 + 30 + const snapshot = db.JSON(); 31 + console.log('Full DB:', snapshot); 32 + 33 + db.JSON({ fresh: 'start', count: 1 }); 34 + console.log('After replace:', db.JSON()); 35 + 36 + db.deleteAll(); 37 + console.log('After deleteAll:', db.JSON()); // {} 38 + 39 + const customDb = new JSONdb('./custom.json', { 40 + asyncWrite: false, 41 + syncOnWrite: false, 42 + jsonSpaces: 2 43 + }); 44 + 45 + customDb.set('key1', 'value1'); 46 + customDb.set('key2', 'value2'); 47 + customDb.sync(); 48 + 49 + try { 50 + unlinkSync('./mydata.json'); 51 + unlinkSync('./custom.json'); 52 + console.log('\nTest files cleaned up successfully.'); 53 + } catch (err) { 54 + console.error('Cleanup error:', err.message); 55 + }
+113
examples/jsondb/jsondb.js
··· 1 + import fs from 'fs'; 2 + 3 + const defaultOptions = { 4 + asyncWrite: false, 5 + syncOnWrite: true, 6 + jsonSpaces: 4, 7 + stringify: JSON.stringify, 8 + parse: JSON.parse 9 + }; 10 + 11 + class JSONdb { 12 + #filePath; 13 + #options; 14 + #storage; 15 + 16 + constructor(filePath, options) { 17 + if (!filePath || !filePath.length) { 18 + throw new Error('Missing file path argument.'); 19 + } 20 + this.#filePath = filePath; 21 + this.#options = { ...defaultOptions, ...options }; 22 + this.#storage = {}; 23 + 24 + let stats; 25 + try { 26 + stats = fs.statSync(filePath); 27 + } catch (err) { 28 + if (err.code === 'ENOENT') return; 29 + if (err.code === 'EACCES') throw new Error(`Cannot access path "${filePath}".`); 30 + throw new Error(`Error while checking for existence of path "${filePath}": ${err}`); 31 + } 32 + 33 + try { 34 + fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK); 35 + } catch (err) { 36 + throw new Error(`Cannot read & write on path "${filePath}". Check permissions!`); 37 + } 38 + 39 + if (stats.size > 0) { 40 + const data = fs.readFileSync(filePath); 41 + this.#validateJSON(data); 42 + this.#storage = this.#options.parse(data); 43 + } 44 + } 45 + 46 + #validateJSON(fileContent) { 47 + try { 48 + this.#options.parse(fileContent); 49 + } catch (e) { 50 + console.error('Given filePath is not empty and its content is not valid JSON.'); 51 + throw e; 52 + } 53 + return true; 54 + } 55 + 56 + set(key, value) { 57 + this.#storage[key] = value; 58 + if (this.#options.syncOnWrite) this.sync(); 59 + } 60 + 61 + get(key) { 62 + return Object.hasOwn(this.#storage, key) ? this.#storage[key] : undefined; 63 + } 64 + 65 + has(key) { 66 + return Object.hasOwn(this.#storage, key); 67 + } 68 + 69 + delete(key) { 70 + const existed = Object.hasOwn(this.#storage, key); 71 + if (!existed) return undefined; 72 + delete this.#storage[key]; 73 + if (this.#options.syncOnWrite) this.sync(); 74 + return true; 75 + } 76 + 77 + deleteAll() { 78 + for (const key of Object.keys(this.#storage)) { 79 + this.delete(key); 80 + } 81 + return this; 82 + } 83 + 84 + sync() { 85 + const data = this.#options.stringify(this.#storage, null, this.#options.jsonSpaces); 86 + if (this.#options.asyncWrite) { 87 + fs.writeFile(this.#filePath, data, err => { 88 + if (err) throw err; 89 + }); 90 + } else { 91 + try { 92 + fs.writeFileSync(this.#filePath, data); 93 + } catch (err) { 94 + if (err.code === 'EACCES') throw new Error(`Cannot access path "${this.#filePath}".`); 95 + throw new Error(`Error while writing to path "${this.#filePath}": ${err}`); 96 + } 97 + } 98 + } 99 + 100 + JSON(storage) { 101 + if (storage) { 102 + try { 103 + JSON.parse(this.#options.stringify(storage)); 104 + this.#storage = storage; 105 + } catch (err) { 106 + throw new Error('Given parameter is not a valid JSON object.'); 107 + } 108 + } 109 + return JSON.parse(this.#options.stringify(this.#storage)); 110 + } 111 + } 112 + 113 + export default JSONdb;
+1
include/ant.h
··· 82 82 const char *js_sym_key(jsval_t sym); 83 83 84 84 jsval_t js_mkobj(struct js *); 85 + jsval_t js_newobj(struct js *); 85 86 jsval_t js_mkarr(struct js *); 86 87 void js_arr_push(struct js *, jsval_t arr, jsval_t val); 87 88 jsval_t js_mkstr(struct js *, const void *, size_t);
+10 -1
src/ant.c
··· 2966 2966 return mkval(T_ARR, vdata(arr)); 2967 2967 } 2968 2968 2969 - jsval_t js_mkarr(struct js *js) { return mkarr(js); } 2969 + jsval_t js_mkarr(struct js *js) { 2970 + return mkarr(js); 2971 + } 2972 + 2973 + jsval_t js_newobj(struct js *js) { 2974 + jsval_t obj = mkobj(js, 0); 2975 + jsval_t proto = get_ctor_proto(js, "Object", 6); 2976 + if (vtype(proto) == T_OBJ) set_proto(js, obj, proto); 2977 + return obj; 2978 + } 2970 2979 2971 2980 static jsoff_t arr_length(struct js *js, jsval_t arr) { 2972 2981 if (vtype(arr) != T_ARR) return 0;
+4 -8
src/modules/json.c
··· 23 23 return js_mkstr(js, yyjson_get_str(val), yyjson_get_len(val)); 24 24 25 25 case YYJSON_TYPE_ARR: { 26 - jsval_t arr = js_mkobj(js); 26 + jsval_t arr = js_mkarr(js); 27 27 size_t idx, max; 28 28 yyjson_val *item; 29 29 30 - yyjson_arr_foreach(val, idx, max, item) { 31 - char idxstr[32]; 32 - snprintf(idxstr, sizeof(idxstr), "%zu", idx); 33 - js_set(js, arr, idxstr, yyjson_to_jsval(js, item)); 34 - } 30 + yyjson_arr_foreach(val, idx, max, item) 31 + js_arr_push(js, arr, yyjson_to_jsval(js, item)); 35 32 36 - js_set(js, arr, "length", js_mknum((double)yyjson_arr_size(val))); 37 33 return arr; 38 34 } 39 35 40 36 case YYJSON_TYPE_OBJ: { 41 - jsval_t obj = js_mkobj(js); 37 + jsval_t obj = js_newobj(js); 42 38 size_t idx, max; 43 39 yyjson_val *key, *item; 44 40