mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-09 23:18:10 -07:00
JS: First batch of OFW PR review changes
This commit is contained in:
+12
-3
@@ -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);
|
||||
|
||||
@@ -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
@@ -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 { }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user