mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-07 19:01:54 -07:00
JS: Second batch of OFW PR changes
This commit is contained in:
+3
-3
@@ -21,7 +21,7 @@
|
||||
- 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
|
||||
- currently `gui/file_picker` works different than other new view objects, it is a simple `.pickFile()` synchronous function, but this [may change later](https://github.com/flipperdevices/flipperzero-firmware/pull/3961#discussion_r1805579153)
|
||||
- effort required to update old scripts using gui: extensive
|
||||
- `keyboard`:
|
||||
- removed, now replaced by `gui/text_input` and `gui/byte_input` (see above)
|
||||
@@ -38,10 +38,10 @@
|
||||
- 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_string()` renamed and moved to number class as `n.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()`
|
||||
- `to_upper_case()` and `to_lower_case()` renamed and moved to string class as `s.toUpperCase()` and `s.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
|
||||
|
||||
@@ -53,7 +53,7 @@ App(
|
||||
appid="js_gui",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_gui_ep",
|
||||
requires=["js_app", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/js_gui.c", "modules/js_gui/js_gui_api_table.cpp"],
|
||||
)
|
||||
|
||||
@@ -61,7 +61,7 @@ App(
|
||||
appid="js_gui__loading",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_view_loading_ep",
|
||||
requires=["js_app", "js_gui", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/loading.c"],
|
||||
)
|
||||
|
||||
@@ -69,7 +69,7 @@ App(
|
||||
appid="js_gui__empty_screen",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_view_empty_screen_ep",
|
||||
requires=["js_app", "js_gui", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/empty_screen.c"],
|
||||
)
|
||||
|
||||
@@ -77,7 +77,7 @@ App(
|
||||
appid="js_gui__submenu",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_view_submenu_ep",
|
||||
requires=["js_app", "js_gui"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/submenu.c"],
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ App(
|
||||
appid="js_gui__text_input",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_view_text_input_ep",
|
||||
requires=["js_app", "js_gui", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/text_input.c"],
|
||||
)
|
||||
|
||||
@@ -93,7 +93,7 @@ App(
|
||||
appid="js_gui__byte_input",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_view_byte_input_ep",
|
||||
requires=["js_app", "js_gui", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gui/byte_input.c"],
|
||||
)
|
||||
|
||||
@@ -149,7 +149,7 @@ App(
|
||||
appid="js_gpio",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="js_gpio_ep",
|
||||
requires=["js_app", "js_event_loop"],
|
||||
requires=["js_app"],
|
||||
sources=["modules/js_gpio.c"],
|
||||
)
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ eventLoop.subscribe(views.dialog.input, function (_sub, button, eventLoop, gui)
|
||||
|
||||
badusb.println("Flipper Model: " + flipper.getModel());
|
||||
badusb.println("Flipper Name: " + flipper.getName());
|
||||
badusb.println("Battery level: " + toString(flipper.getBatteryCharge()) + "%");
|
||||
badusb.println("Battery level: " + flipper.getBatteryCharge().toString() + "%");
|
||||
|
||||
// Alt+Numpad method works only on Windows!!!
|
||||
badusb.altPrintln("This was printed with Alt+Numpad method!");
|
||||
|
||||
@@ -45,7 +45,7 @@ function sendRandomModelAdvertisement() {
|
||||
|
||||
blebeacon.start();
|
||||
|
||||
print("Sent data for model ID " + toString(model));
|
||||
print("Sent data for model ID " + model.toString());
|
||||
|
||||
currentIndex = (currentIndex + 1) % watchValues.length;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ eventLoop.subscribe(views.bytekb.input, function (_sub, data, gui, views) {
|
||||
let data_view = Uint8Array(data);
|
||||
let text = "0x";
|
||||
for (let i = 0; i < data_view.length; i++) {
|
||||
text += toString(data_view[i], 16);
|
||||
text += data_view[i].toString(16);
|
||||
}
|
||||
views.helloDialog.set("text", "You typed:\n" + text);
|
||||
views.helloDialog.set("center", "Cool!");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
let sampleText = "Hello, World!";
|
||||
|
||||
let lengthOfText = "Length of text: " + toString(sampleText.length);
|
||||
let lengthOfText = "Length of text: " + sampleText.length.toString();
|
||||
print(lengthOfText);
|
||||
|
||||
let start = 7;
|
||||
@@ -9,7 +9,7 @@ let substringResult = sampleText.slice(start, end);
|
||||
print(substringResult);
|
||||
|
||||
let searchStr = "World";
|
||||
let result2 = toString(sampleText.indexOf(searchStr));
|
||||
let result2 = sampleText.indexOf(searchStr).toString();
|
||||
print(result2);
|
||||
|
||||
let upperCaseText = "Text in upper case: " + sampleText.toUpperCase();
|
||||
|
||||
@@ -6,7 +6,7 @@ while (1) {
|
||||
if (rx_data !== undefined) {
|
||||
serial.write(rx_data);
|
||||
let data_view = Uint8Array(rx_data);
|
||||
print("0x" + toString(data_view[0], 16));
|
||||
print("0x" + data_view[0].toString(16));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ eventLoop.subscribe(views.dialog.input, function (_sub, button, gui, views) {
|
||||
eventLoop.subscribe(views.textInput.input, function (_sub, text, gui, views, ctx) {
|
||||
gui.viewDispatcher.switchTo(views.loading);
|
||||
|
||||
let path = ctx.tmpTemplate + toString(ctx.tmpNumber++);
|
||||
let path = ctx.tmpTemplate + (ctx.tmpNumber++).toString();
|
||||
let file = storage.openFile(path, "w", "create_always");
|
||||
file.write(text);
|
||||
file.close();
|
||||
@@ -58,7 +58,7 @@ eventLoop.subscribe(views.textInput.input, function (_sub, text, gui, views, ctx
|
||||
} else if (typeof result === "string") {
|
||||
result = "'" + result + "'";
|
||||
} else if (typeof result === "number") {
|
||||
result = toString(result);
|
||||
result = result.toString();
|
||||
} else if (typeof result === "bigint") { // mJS doesn't support BigInt() but might aswell check
|
||||
result = "bigint";
|
||||
} else if (typeof result === "boolean") {
|
||||
|
||||
@@ -196,16 +196,6 @@ static void js_require(struct mjs* mjs) {
|
||||
mjs_return(mjs, req_object);
|
||||
}
|
||||
|
||||
static void js_global_to_string(struct mjs* mjs) {
|
||||
int base = 10;
|
||||
if(mjs_nargs(mjs) > 1) base = mjs_get_int(mjs, mjs_arg(mjs, 1));
|
||||
double num = mjs_get_double(mjs, mjs_arg(mjs, 0));
|
||||
char tmp_str[] = "-2147483648";
|
||||
itoa(num, tmp_str, base);
|
||||
mjs_val_t ret = mjs_mk_string(mjs, tmp_str, ~0, true);
|
||||
mjs_return(mjs, ret);
|
||||
}
|
||||
|
||||
static void js_parse_int(struct mjs* mjs) {
|
||||
const char* str;
|
||||
int32_t base = 10;
|
||||
@@ -268,7 +258,6 @@ static int32_t js_thread(void* arg) {
|
||||
}
|
||||
mjs_set(mjs, global, "print", ~0, MJS_MK_FN(js_print));
|
||||
mjs_set(mjs, global, "delay", ~0, MJS_MK_FN(js_delay));
|
||||
mjs_set(mjs, global, "toString", ~0, MJS_MK_FN(js_global_to_string));
|
||||
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));
|
||||
|
||||
@@ -260,26 +260,6 @@ static void js_gui_view_set(struct mjs* mjs) {
|
||||
mjs_return(mjs, MJS_UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief `View.hasProperty`
|
||||
*/
|
||||
static void js_gui_view_has_property(struct mjs* mjs) {
|
||||
const char* name;
|
||||
JS_FETCH_ARGS_OR_RETURN(mjs, JS_EXACTLY, JS_ARG_STR(&name));
|
||||
JsGuiViewData* data = JS_GET_CONTEXT(mjs);
|
||||
const JsViewDescriptor* descriptor = data->descriptor;
|
||||
|
||||
for(size_t i = 0; i < descriptor->prop_cnt; i++) {
|
||||
JsViewPropDescriptor prop = descriptor->props[i];
|
||||
if(strcmp(prop.name, name) != 0) continue;
|
||||
|
||||
mjs_return(mjs, mjs_mk_boolean(mjs, true));
|
||||
return;
|
||||
}
|
||||
|
||||
mjs_return(mjs, mjs_mk_boolean(mjs, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief `View` destructor
|
||||
*/
|
||||
@@ -304,7 +284,6 @@ static mjs_val_t js_gui_make_view(struct mjs* mjs, const JsViewDescriptor* descr
|
||||
// generic view API
|
||||
mjs_val_t view_obj = mjs_mk_object(mjs);
|
||||
mjs_set(mjs, view_obj, "set", ~0, MJS_MK_FN(js_gui_view_set));
|
||||
mjs_set(mjs, view_obj, "hasProperty", ~0, MJS_MK_FN(js_gui_view_has_property));
|
||||
|
||||
// object data
|
||||
JsGuiViewData* data = malloc(sizeof(JsGuiViewData));
|
||||
|
||||
+7
-8
@@ -11,13 +11,6 @@ declare function delay(ms: number): void;
|
||||
*/
|
||||
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: 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
|
||||
@@ -214,7 +207,13 @@ declare class Boolean { }
|
||||
|
||||
declare class Function { }
|
||||
|
||||
declare class Number { }
|
||||
declare class Number {
|
||||
/**
|
||||
* @brief Converts this number to a string
|
||||
* @param base Integer base (`2`...`16`), default: 10
|
||||
*/
|
||||
toString(base?: number): string;
|
||||
}
|
||||
|
||||
declare class Object { }
|
||||
|
||||
|
||||
@@ -9,11 +9,6 @@ export declare class View<Props extends Properties> {
|
||||
* @param value Value to assign
|
||||
*/
|
||||
set<P extends keyof Props>(property: P, value: Props[P]): void;
|
||||
/**
|
||||
* Check if property is available
|
||||
* @param name Name of the property
|
||||
*/
|
||||
hasProperty(name: string): boolean;
|
||||
}
|
||||
|
||||
export declare class ViewFactory<Props extends Properties, V extends View<Props>> {
|
||||
|
||||
@@ -475,6 +475,22 @@ static int getprop_builtin_string(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getprop_builtin_number(
|
||||
struct mjs* mjs,
|
||||
mjs_val_t val,
|
||||
const char* name,
|
||||
size_t name_len,
|
||||
mjs_val_t* res) {
|
||||
if(strcmp(name, "toString") == 0) {
|
||||
*res = mjs_mk_foreign_func(mjs, (mjs_func_ptr_t)mjs_number_to_string);
|
||||
return 1;
|
||||
}
|
||||
|
||||
(void)val;
|
||||
(void)name_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int getprop_builtin_array(
|
||||
struct mjs* mjs,
|
||||
mjs_val_t val,
|
||||
@@ -589,6 +605,8 @@ static int getprop_builtin(struct mjs* mjs, mjs_val_t val, mjs_val_t name, mjs_v
|
||||
} else if(s != NULL && n == 5 && strncmp(s, "apply", n) == 0) {
|
||||
*res = mjs_mk_foreign_func(mjs, (mjs_func_ptr_t)mjs_apply_);
|
||||
handled = 1;
|
||||
} else if(mjs_is_number(val)) {
|
||||
handled = getprop_builtin_number(mjs, val, s, n, res);
|
||||
} else if(mjs_is_array(val)) {
|
||||
handled = getprop_builtin_array(mjs, val, s, n, res);
|
||||
} else if(mjs_is_foreign(val)) {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "mjs_core.h"
|
||||
#include "mjs_internal.h"
|
||||
#include "mjs_primitive.h"
|
||||
#include "mjs_string_public.h"
|
||||
#include "mjs_util.h"
|
||||
|
||||
mjs_val_t mjs_mk_null(void) {
|
||||
return MJS_NULL;
|
||||
@@ -158,3 +160,31 @@ MJS_PRIVATE void mjs_op_isnan(struct mjs* mjs) {
|
||||
|
||||
mjs_return(mjs, ret);
|
||||
}
|
||||
|
||||
MJS_PRIVATE void mjs_number_to_string(struct mjs* mjs) {
|
||||
mjs_val_t ret = MJS_UNDEFINED;
|
||||
mjs_val_t base_v = MJS_UNDEFINED;
|
||||
int32_t base = 10;
|
||||
int32_t num;
|
||||
|
||||
/* get number from `this` */
|
||||
if(!mjs_check_arg(mjs, -1 /*this*/, "this", MJS_TYPE_NUMBER, NULL)) {
|
||||
goto clean;
|
||||
}
|
||||
num = mjs_get_int32(mjs, mjs->vals.this_obj);
|
||||
|
||||
if(mjs_nargs(mjs) >= 1) {
|
||||
/* get base from arg 0 */
|
||||
if(!mjs_check_arg(mjs, 0, "base", MJS_TYPE_NUMBER, &base_v)) {
|
||||
goto clean;
|
||||
}
|
||||
base = mjs_get_int(mjs, base_v);
|
||||
}
|
||||
|
||||
char tmp_str[] = "-2147483648";
|
||||
itoa(num, tmp_str, base);
|
||||
ret = mjs_mk_string(mjs, tmp_str, ~0, true);
|
||||
|
||||
clean:
|
||||
mjs_return(mjs, ret);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ MJS_PRIVATE void* get_ptr(mjs_val_t v);
|
||||
*/
|
||||
MJS_PRIVATE void mjs_op_isnan(struct mjs* mjs);
|
||||
|
||||
/*
|
||||
* Implementation for JS Number.toString()
|
||||
*/
|
||||
MJS_PRIVATE void mjs_number_to_string(struct mjs* mjs);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Reference in New Issue
Block a user