[FL-3963] Move JS modules to new arg parser (#4139)

* js: value destructuring and tests

* js: temporary fix to see size impact

* js_val: reduce code size 1

* i may be stupid.

* test: js_value args

* Revert "js: temporary fix to see size impact"

This reverts commit f51d726dbafc4300d3552020de1c3b8f9ecd3ac1.

* pvs: silence warnings

* style: formatting

* pvs: silence warnings?

* pvs: silence warnings??

* js_value: redesign declaration types for less code

* js: temporary fix to see size impact

* style: formatting

* pvs: fix helpful warnings

* js_value: reduce .rodata size

* pvs: fix helpful warning

* js_value: reduce code size 1

* fix build error

* style: format

* Revert "js: temporary fix to see size impact"

This reverts commit d6a46f01794132e882e03fd273dec24386a4f8ba.

* style: format

* js: move to new arg parser

* style: format

---------

Co-authored-by: hedger <hedger@users.noreply.github.com>
This commit is contained in:
Anna Antonenko
2025-04-05 03:17:30 +04:00
committed by GitHub
parent 7192c9e68b
commit dac1457f0a
13 changed files with 525 additions and 620 deletions

View File

@@ -1,42 +1,79 @@
#include "../js_modules.h" // IWYU pragma: keep
#include <path.h>
// ---=== file ops ===---
// ==========================
// Common argument signatures
// ==========================
static const JsValueDeclaration js_storage_1_int_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeInt32),
};
static const JsValueArguments js_storage_1_int_args = JS_VALUE_ARGS(js_storage_1_int_arg_list);
static const JsValueDeclaration js_storage_1_str_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeString),
};
static const JsValueArguments js_storage_1_str_args = JS_VALUE_ARGS(js_storage_1_str_arg_list);
static const JsValueDeclaration js_storage_2_str_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeString),
JS_VALUE_SIMPLE(JsValueTypeString),
};
static const JsValueArguments js_storage_2_str_args = JS_VALUE_ARGS(js_storage_2_str_arg_list);
// ======================
// File object operations
// ======================
static void js_storage_file_close(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_close(file)));
}
static void js_storage_file_is_open(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_is_open(file)));
}
static void js_storage_file_read(struct mjs* mjs) {
enum {
ReadModeAscii,
ReadModeBinary,
} read_mode;
JS_ENUM_MAP(read_mode, {"ascii", ReadModeAscii}, {"binary", ReadModeBinary});
typedef enum {
JsStorageReadModeAscii,
JsStorageReadModeBinary,
} JsStorageReadMode;
static const JsValueEnumVariant js_storage_read_mode_variants[] = {
{"ascii", JsStorageReadModeAscii},
{"binary", JsStorageReadModeBinary},
};
static const JsValueDeclaration js_storage_read_arg_list[] = {
JS_VALUE_ENUM(JsStorageReadMode, js_storage_read_mode_variants),
JS_VALUE_SIMPLE(JsValueTypeInt32),
};
static const JsValueArguments js_storage_read_args = JS_VALUE_ARGS(js_storage_read_arg_list);
JsStorageReadMode read_mode;
int32_t length;
JS_FETCH_ARGS_OR_RETURN(
mjs, JS_EXACTLY, JS_ARG_ENUM(read_mode, "ReadMode"), JS_ARG_INT32(&length));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_read_args, &read_mode, &length);
File* file = JS_GET_CONTEXT(mjs);
char buffer[length];
size_t actually_read = storage_file_read(file, buffer, length);
if(read_mode == ReadModeAscii) {
if(read_mode == JsStorageReadModeAscii) {
mjs_return(mjs, mjs_mk_string(mjs, buffer, actually_read, true));
} else if(read_mode == ReadModeBinary) {
} else if(read_mode == JsStorageReadModeBinary) {
mjs_return(mjs, mjs_mk_array_buf(mjs, buffer, actually_read));
}
}
static void js_storage_file_write(struct mjs* mjs) {
static const JsValueDeclaration js_storage_file_write_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeAny),
};
static const JsValueArguments js_storage_file_write_args =
JS_VALUE_ARGS(js_storage_file_write_arg_list);
mjs_val_t data;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_ANY(&data));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_file_write_args, &data);
const void* buf;
size_t len;
if(mjs_is_string(data)) {
@@ -52,52 +89,58 @@ static void js_storage_file_write(struct mjs* mjs) {
static void js_storage_file_seek_relative(struct mjs* mjs) {
int32_t offset;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_INT32(&offset));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_int_args, &offset);
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_seek(file, offset, false)));
}
static void js_storage_file_seek_absolute(struct mjs* mjs) {
int32_t offset;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_INT32(&offset));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_int_args, &offset);
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_seek(file, offset, true)));
}
static void js_storage_file_tell(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_number(mjs, storage_file_tell(file)));
}
static void js_storage_file_truncate(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_truncate(file)));
}
static void js_storage_file_size(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_number(mjs, storage_file_size(file)));
}
static void js_storage_file_eof(struct mjs* mjs) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY); // 0 args
File* file = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_eof(file)));
}
static void js_storage_file_copy_to(struct mjs* mjs) {
File* source = JS_GET_CONTEXT(mjs);
static const JsValueDeclaration js_storage_file_write_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeAny),
JS_VALUE_SIMPLE(JsValueTypeInt32),
};
static const JsValueArguments js_storage_file_write_args =
JS_VALUE_ARGS(js_storage_file_write_arg_list);
mjs_val_t dest_obj;
int32_t bytes;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_OBJ(&dest_obj), JS_ARG_INT32(&bytes));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_file_write_args, &dest_obj, &bytes);
File* source = JS_GET_CONTEXT(mjs);
File* destination = JS_GET_INST(mjs, dest_obj);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_copy_to_file(source, destination, bytes)));
}
// ---=== top-level file ops ===---
// =========================
// Top-level file operations
// =========================
// common destructor for file and dir objects
static void js_storage_file_destructor(struct mjs* mjs, mjs_val_t obj) {
@@ -106,23 +149,33 @@ static void js_storage_file_destructor(struct mjs* mjs, mjs_val_t obj) {
}
static void js_storage_open_file(struct mjs* mjs) {
const char* path;
FS_AccessMode access_mode;
FS_OpenMode open_mode;
JS_ENUM_MAP(access_mode, {"r", FSAM_READ}, {"w", FSAM_WRITE}, {"rw", FSAM_READ_WRITE});
JS_ENUM_MAP(
open_mode,
static const JsValueEnumVariant js_storage_fsam_variants[] = {
{"r", FSAM_READ},
{"w", FSAM_WRITE},
{"rw", FSAM_READ_WRITE},
};
static const JsValueEnumVariant js_storage_fsom_variants[] = {
{"open_existing", FSOM_OPEN_EXISTING},
{"open_always", FSOM_OPEN_ALWAYS},
{"open_append", FSOM_OPEN_APPEND},
{"create_new", FSOM_CREATE_NEW},
{"create_always", FSOM_CREATE_ALWAYS});
JS_FETCH_ARGS_OR_RETURN(
mjs,
JS_EXACTLY,
JS_ARG_STR(&path),
JS_ARG_ENUM(access_mode, "AccessMode"),
JS_ARG_ENUM(open_mode, "OpenMode"));
{"create_always", FSOM_CREATE_ALWAYS},
};
static const JsValueDeclaration js_storage_open_file_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeString),
JS_VALUE_ENUM(FS_AccessMode, js_storage_fsam_variants),
JS_VALUE_ENUM(FS_OpenMode, js_storage_fsom_variants),
};
static const JsValueArguments js_storage_open_file_args =
JS_VALUE_ARGS(js_storage_open_file_arg_list);
const char* path;
FS_AccessMode access_mode;
FS_OpenMode open_mode;
JS_VALUE_PARSE_ARGS_OR_RETURN(
mjs, &js_storage_open_file_args, &path, &access_mode, &open_mode);
Storage* storage = JS_GET_CONTEXT(mjs);
File* file = storage_file_alloc(storage);
@@ -152,16 +205,18 @@ static void js_storage_open_file(struct mjs* mjs) {
static void js_storage_file_exists(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_file_exists(storage, path)));
}
// ---=== dir ops ===---
// ====================
// Directory operations
// ====================
static void js_storage_read_directory(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
File* dir = storage_file_alloc(storage);
@@ -200,30 +255,32 @@ static void js_storage_read_directory(struct mjs* mjs) {
static void js_storage_directory_exists(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_dir_exists(storage, path)));
}
static void js_storage_make_directory(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_simply_mkdir(storage, path)));
}
// ---=== common ops ===---
// =================
// Common operations
// =================
static void js_storage_file_or_dir_exists(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_common_exists(storage, path)));
}
static void js_storage_stat(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
FileInfo file_info;
uint32_t timestamp;
@@ -244,21 +301,21 @@ static void js_storage_stat(struct mjs* mjs) {
static void js_storage_remove(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_simply_remove(storage, path)));
}
static void js_storage_rmrf(struct mjs* mjs) {
const char* path;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &path);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_simply_remove_recursive(storage, path)));
}
static void js_storage_rename(struct mjs* mjs) {
const char *old, *new;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&old), JS_ARG_STR(&new));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_2_str_args, &old, &new);
Storage* storage = JS_GET_CONTEXT(mjs);
FS_Error status = storage_common_rename(storage, old, new);
mjs_return(mjs, mjs_mk_boolean(mjs, status == FSE_OK));
@@ -266,7 +323,7 @@ static void js_storage_rename(struct mjs* mjs) {
static void js_storage_copy(struct mjs* mjs) {
const char *source, *dest;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&source), JS_ARG_STR(&dest));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_2_str_args, &source, &dest);
Storage* storage = JS_GET_CONTEXT(mjs);
FS_Error status = storage_common_copy(storage, source, dest);
mjs_return(mjs, mjs_mk_boolean(mjs, status == FSE_OK || status == FSE_EXIST));
@@ -274,7 +331,7 @@ static void js_storage_copy(struct mjs* mjs) {
static void js_storage_fs_info(struct mjs* mjs) {
const char* fs;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&fs));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_1_str_args, &fs);
Storage* storage = JS_GET_CONTEXT(mjs);
uint64_t total_space, free_space;
if(storage_common_fs_info(storage, fs, &total_space, &free_space) != FSE_OK) {
@@ -290,15 +347,19 @@ static void js_storage_fs_info(struct mjs* mjs) {
}
static void js_storage_next_available_filename(struct mjs* mjs) {
static const JsValueDeclaration js_storage_naf_arg_list[] = {
JS_VALUE_SIMPLE(JsValueTypeString),
JS_VALUE_SIMPLE(JsValueTypeString),
JS_VALUE_SIMPLE(JsValueTypeString),
JS_VALUE_SIMPLE(JsValueTypeInt32),
};
static const JsValueArguments js_storage_naf_args = JS_VALUE_ARGS(js_storage_naf_arg_list);
const char *dir_path, *file_name, *file_ext;
int32_t max_len;
JS_FETCH_ARGS_OR_RETURN(
mjs,
JS_EXACTLY,
JS_ARG_STR(&dir_path),
JS_ARG_STR(&file_name),
JS_ARG_STR(&file_ext),
JS_ARG_INT32(&max_len));
JS_VALUE_PARSE_ARGS_OR_RETURN(
mjs, &js_storage_naf_args, &dir_path, &file_name, &file_ext, &max_len);
Storage* storage = JS_GET_CONTEXT(mjs);
FuriString* next_name = furi_string_alloc();
storage_get_next_filename(storage, dir_path, file_name, file_ext, next_name, max_len);
@@ -306,23 +367,27 @@ static void js_storage_next_available_filename(struct mjs* mjs) {
furi_string_free(next_name);
}
// ---=== path ops ===---
// ===============
// Path operations
// ===============
static void js_storage_are_paths_equal(struct mjs* mjs) {
const char *path1, *path2;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&path1), JS_ARG_STR(&path2));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_2_str_args, &path1, &path2);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_common_equivalent_path(storage, path1, path2)));
}
static void js_storage_is_subpath_of(struct mjs* mjs) {
const char *parent, *child;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&parent), JS_ARG_STR(&child));
JS_VALUE_PARSE_ARGS_OR_RETURN(mjs, &js_storage_2_str_args, &parent, &child);
Storage* storage = JS_GET_CONTEXT(mjs);
mjs_return(mjs, mjs_mk_boolean(mjs, storage_common_is_subdir(storage, parent, child)));
}
// ---=== module ctor & dtor ===---
// ==================
// Module ctor & dtor
// ==================
static void* js_storage_create(struct mjs* mjs, mjs_val_t* object, JsModules* modules) {
UNUSED(modules);
@@ -363,7 +428,9 @@ static void js_storage_destroy(void* data) {
furi_record_close(RECORD_STORAGE);
}
// ---=== boilerplate ===---
// ===========
// Boilerplate
// ===========
static const JsModuleDescriptor js_storage_desc = {
"storage",