JS: First batch of OFW PR review changes

This commit is contained in:
Willy-JL
2024-10-18 04:35:27 +01:00
parent ba74e953c4
commit 4a0dfa8de9
9 changed files with 86 additions and 105 deletions
+12 -3
View File
@@ -8,32 +8,41 @@
- Non-exhaustive list of changes to help you fix your scripts:
- `badusb`:
- `setup()`: `mfr_name`, `prod_name`, `layout_path` parameters renamed to `mfrName`, `prodName`, `layoutPath`
- existing scripts using badusb will need to simply rename these
- effort required to update old scripts using badusb: very minimal
- `dialog`:
- removed, now replaced by `gui/dialog` and `gui/file_picker` (see below)
- `event_loop`:
- new module, allows timer functionality, callbacks and event-driven programming, used heavily alongside gpio and gui modules
- `gpio`:
- fully overhauled, now you `get()` pin instances and perform actions on them like `.init()`
- existing scripts using gpio will need some reworking
- now supports interrupts, callbacks and more cool things
- effort required to update old scripts using gpio: moderate
- `gui`:
- new module, fully overhauled, replaces dialog, keyboard, submenu, textbox modules
- higher barrier to entry than older modules (requires usage of `event_loop` and `gui.viewDispatcher`), but much more flexible, powerful and easier to extend
- includes all previously available js gui functionality (except `widget`), and also adds `gui/loading` and `gui/empty_screen` views
- existing scripts using gui in any way will need a huge amount of reworking
- effort required to update old scripts using gui: extensive
- `keyboard`:
- removed, now replaced by `gui/text_input` and `gui/byte_input` (see above)
- `storage`:
- fully overhauled, now you `openFile()`s and perform actions on them like `.read()`
- now supports many more operations including different open modes, directories and much more
- `virtualInit()`, `virtualMount()`, `virtualQuit()` still work the same
- existing scripts using storage will need some reworking
- effort required to update old scripts using storage: moderate
- `submenu`:
- removed, now replaced by `gui/submenu` (see above)
- `textbox`:
- removed, now replace by `gui/text_box` (see above)
- `widget`:
- only gui functionality not ported to new gui module, remains unchanged for now but likely to be ported later on
- globals:
- `__filepath` and `__dirpath` renamed to `__filename` and `__dirname` like in nodejs
- `to_string()` renamed to `toString()`, now supports optional base parameter
- `to_hex_string()` removed, now use `toString(num, 16)`
- `parse_int()` renamed to `parseInt()`, now supports optional base parameter
- `to_upper_case()` and `to_lower_case()` renamed and moved to string class as `"".toUpperCase()` and `"".toLowerCase()`
- effort required to update old scripts using these: minimal
- Added type definitions (typescript files for type checking in IDE, Flipper does not run typescript, and you code in javascript)
- Documentation is incomplete and deprecated, from now on you should refer to type definitions (`applications/system/js_app/types`), those will always be correct
- Type definitions for extra modules we have that OFW doesn't will come later
@@ -1,3 +1,3 @@
let math = load(__dirpath + "/load_api.js");
let math = load(__dirname + "/load_api.js");
let result = math.add(5, 10);
print(result);
@@ -1,8 +1,8 @@
let storage = require("storage");
print("script has __dirpath of" + __dirpath);
print("script has __filepath of" + __filepath);
if (storage.fileExists(__dirpath + "/math.js")) {
print("script has __dirname of" + __dirname);
print("script has __filename of" + __filename);
if (storage.fileExists(__dirname + "/math.js")) {
print("math.js exist here.");
} else {
print("math.js does not exist here.");
@@ -12,8 +12,8 @@ let searchStr = "World";
let result2 = toString(sampleText.indexOf(searchStr));
print(result2);
let upperCaseText = "Text in upper case: " + toUpperCase(sampleText);
let upperCaseText = "Text in upper case: " + sampleText.toUpperCase();
print(upperCaseText);
let lowerCaseText = "Text in lower case: " + toLowerCase(sampleText);
let lowerCaseText = "Text in lower case: " + sampleText.toLowerCase();
print(lowerCaseText);
+12 -80
View File
@@ -1,6 +1,7 @@
#include <common/cs_dbg.h>
#include <toolbox/path.h>
#include <toolbox/stream/file_stream.h>
#include <toolbox/strint.h>
#include <loader/firmware_api/firmware_api.h>
#include <flipper_application/api_hashtable/api_hashtable.h>
#include <flipper_application/plugins/composite_resolver.h>
@@ -206,87 +207,20 @@ static void js_global_to_string(struct mjs* mjs) {
}
static void js_parse_int(struct mjs* mjs) {
mjs_val_t arg = mjs_arg(mjs, 0);
if(!mjs_is_string(arg)) {
mjs_return(mjs, mjs_mk_number(mjs, 0));
return;
const char* str;
int32_t base = 10;
if(mjs_nargs(mjs) == 1) {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&str));
} else {
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&str), JS_ARG_INT32(&base));
}
size_t str_len = 0;
const char* str = mjs_get_string(mjs, &arg, &str_len);
if((str_len == 0) || (str == NULL)) {
mjs_return(mjs, mjs_mk_number(mjs, 0));
return;
int32_t num;
if(strint_to_int32(str, NULL, &num, base) != StrintParseNoError) {
num = 0;
}
int32_t num = 0;
int32_t sign = 1;
size_t i = 0;
if(str[0] == '-') {
sign = -1;
i = 1;
} else if(str[0] == '+') {
i = 1;
}
for(; i < str_len; i++) {
if(str[i] >= '0' && str[i] <= '9') {
num = num * 10 + (str[i] - '0');
} else {
break;
}
}
num *= sign;
mjs_return(mjs, mjs_mk_number(mjs, num));
}
static void js_to_upper_case(struct mjs* mjs) {
mjs_val_t arg0 = mjs_arg(mjs, 0);
size_t str_len;
const char* str = NULL;
if(mjs_is_string(arg0)) {
str = mjs_get_string(mjs, &arg0, &str_len);
}
if(!str) {
mjs_return(mjs, MJS_UNDEFINED);
return;
}
char* upperStr = strdup(str);
for(size_t i = 0; i < str_len; i++) {
upperStr[i] = toupper(upperStr[i]);
}
mjs_val_t resultStr = mjs_mk_string(mjs, upperStr, ~0, true);
free(upperStr);
mjs_return(mjs, resultStr);
}
static void js_to_lower_case(struct mjs* mjs) {
mjs_val_t arg0 = mjs_arg(mjs, 0);
size_t str_len;
const char* str = NULL;
if(mjs_is_string(arg0)) {
str = mjs_get_string(mjs, &arg0, &str_len);
}
if(!str) {
mjs_return(mjs, MJS_UNDEFINED);
return;
}
char* lowerStr = strdup(str);
for(size_t i = 0; i < str_len; i++) {
lowerStr[i] = tolower(lowerStr[i]);
}
mjs_val_t resultStr = mjs_mk_string(mjs, lowerStr, ~0, true);
free(lowerStr);
mjs_return(mjs, resultStr);
}
#ifdef JS_DEBUG
static void js_dump_write_callback(void* ctx, const char* format, ...) {
File* file = ctx;
@@ -320,14 +254,14 @@ static int32_t js_thread(void* arg) {
mjs_set(
mjs,
global,
"__filepath",
"__filename",
~0,
mjs_mk_string(
mjs, furi_string_get_cstr(worker->path), furi_string_size(worker->path), true));
mjs_set(
mjs,
global,
"__dirpath",
"__dirname",
~0,
mjs_mk_string(mjs, furi_string_get_cstr(dirpath), furi_string_size(dirpath), true));
furi_string_free(dirpath);
@@ -338,8 +272,6 @@ static int32_t js_thread(void* arg) {
mjs_set(mjs, global, "ffi_address", ~0, MJS_MK_FN(js_ffi_address));
mjs_set(mjs, global, "require", ~0, MJS_MK_FN(js_require));
mjs_set(mjs, global, "parseInt", ~0, MJS_MK_FN(js_parse_int));
mjs_set(mjs, global, "toUpperCase", ~0, MJS_MK_FN(js_to_upper_case));
mjs_set(mjs, global, "toLowerCase", ~0, MJS_MK_FN(js_to_lower_case));
mjs_val_t console_obj = mjs_mk_object(mjs);
mjs_set(mjs, console_obj, "log", ~0, MJS_MK_FN(js_console_log));
+13 -16
View File
@@ -14,37 +14,26 @@ declare function print(...args: any[]): void;
/**
* @brief Converts a number to a string
* @param value The number to convert to a string
* @param base Integer base (`2`...`16`), default: 16
* @param base Integer base (`2`...`16`), default: 10
*/
declare function toString(value: number, base?: number): string;
/**
* @brief Converts a string to a number
* @param text The string to convert to a number
* @param base Integer base (`2`...`16`), default: 10
*/
declare function parseInt(text: string): number;
/**
* @brief Transforms a string to upper case
* @param text The string to transforms to upper case
*/
declare function toUpperCase(text: string): string;
/**
* @brief Transforms a string to lower case
* @param text The string to transforms to lower case
*/
declare function toLowerCase(text: string): string;
declare function parseInt(text: string, base?: number): number;
/**
* @brief Path to the directory containing the current script
*/
declare const __dirpath: string;
declare const __dirname: string;
/**
* @brief Path to the current script file
*/
declare const __filepath: string;
declare const __filename: string;
/**
* @brief Reads a JS value from a file
@@ -211,6 +200,14 @@ declare class String {
* @param end The index to end substring at
*/
slice(start: number, end?: number): string;
/**
* @brief Return this string transformed to upper case
*/
toUpperCase(): string;
/**
* @brief Return this string transformed to lower case
*/
toLowerCase(): string;
}
declare class Boolean { }
+6
View File
@@ -452,6 +452,12 @@ static int getprop_builtin_string(
} else if(strcmp(name, "slice") == 0) {
*res = mjs_mk_foreign_func(mjs, (mjs_func_ptr_t)mjs_string_slice);
return 1;
} else if(strcmp(name, "toUpperCase") == 0) {
*res = mjs_mk_foreign_func(mjs, (mjs_func_ptr_t)mjs_string_to_upper_case);
return 1;
} else if(strcmp(name, "toLowerCase") == 0) {
*res = mjs_mk_foreign_func(mjs, (mjs_func_ptr_t)mjs_string_to_lower_case);
return 1;
} else if(isnum) {
/*
* string subscript: return a new one-byte string if the index
+35
View File
@@ -286,6 +286,41 @@ MJS_PRIVATE mjs_val_t s_concat(struct mjs* mjs, mjs_val_t a, mjs_val_t b) {
return res;
}
MJS_PRIVATE void mjs_string_to_case(struct mjs* mjs, bool upper) {
mjs_val_t ret = MJS_UNDEFINED;
size_t size;
const char* s = NULL;
/* get string from `this` */
if(!mjs_check_arg(mjs, -1 /*this*/, "this", MJS_TYPE_STRING, NULL)) {
goto clean;
}
s = mjs_get_string(mjs, &mjs->vals.this_obj, &size);
if(size == 0) {
ret = mjs_mk_string(mjs, "", 0, 1);
goto clean;
}
char* tmp = malloc(size);
for(size_t i = 0; i < size; i++) {
tmp[i] = upper ? toupper(s[i]) : tolower(s[i]);
}
ret = mjs_mk_string(mjs, tmp, size, 1);
free(tmp);
clean:
mjs_return(mjs, ret);
}
MJS_PRIVATE void mjs_string_to_lower_case(struct mjs* mjs) {
mjs_string_to_case(mjs, false);
}
MJS_PRIVATE void mjs_string_to_upper_case(struct mjs* mjs) {
mjs_string_to_case(mjs, true);
}
MJS_PRIVATE void mjs_string_slice(struct mjs* mjs) {
int nargs = mjs_nargs(mjs);
mjs_val_t ret = mjs_mk_number(mjs, 0);
+2
View File
@@ -33,6 +33,8 @@ MJS_PRIVATE void embed_string(
MJS_PRIVATE void mjs_mkstr(struct mjs* mjs);
MJS_PRIVATE void mjs_string_to_lower_case(struct mjs* mjs);
MJS_PRIVATE void mjs_string_to_upper_case(struct mjs* mjs);
MJS_PRIVATE void mjs_string_slice(struct mjs* mjs);
MJS_PRIVATE void mjs_string_index_of(struct mjs* mjs);
MJS_PRIVATE void mjs_string_char_code_at(struct mjs* mjs);