diff --git a/applications/system/js_app/js_thread.c b/applications/system/js_app/js_thread.c index d26fe1fb0..31e9f721e 100644 --- a/applications/system/js_app/js_thread.c +++ b/applications/system/js_app/js_thread.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -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)); diff --git a/applications/system/js_app/modules/js_gui/js_gui.c b/applications/system/js_app/modules/js_gui/js_gui.c index 4bd4ccc31..cd87e5c4b 100644 --- a/applications/system/js_app/modules/js_gui/js_gui.c +++ b/applications/system/js_app/modules/js_gui/js_gui.c @@ -260,6 +260,26 @@ 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 */ @@ -284,6 +304,7 @@ 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)); diff --git a/applications/system/js_app/modules/js_gui/text_input.c b/applications/system/js_app/modules/js_gui/text_input.c index f68978e2d..d2bf4a8f9 100644 --- a/applications/system/js_app/modules/js_gui/text_input.c +++ b/applications/system/js_app/modules/js_gui/text_input.c @@ -49,7 +49,6 @@ static bool max_len_assign( JsViewPropValue value, JsKbdContext* context) { UNUSED(mjs); - UNUSED(input); context->buffer_size = (size_t)(value.number + 1); context->buffer = realloc(context->buffer, context->buffer_size); //-V701 text_input_set_result_callback( diff --git a/applications/system/js_app/types/badusb/index.d.ts b/applications/system/js_app/types/badusb/index.d.ts index 872b8fe04..4fbda5ef8 100644 --- a/applications/system/js_app/types/badusb/index.d.ts +++ b/applications/system/js_app/types/badusb/index.d.ts @@ -14,6 +14,9 @@ export type MainKey = "F11" | "F12" | "F13" | "F14" | "F15" | "F16" | "F17" | "F18" | "F19" | "F20" | "F21" | "F22" | "F23" | "F24" | + "NUM0" | "NUM1" | "NUM2" | "NUM3" | "NUM4" | "NUM5" | "NUM6" | "NUM7" | + "NUM8" | "NUM9" | + "\n" | " " | "!" | "\"" | "#" | "$" | "%" | "&" | "'" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | ">" | "=" | "?" | "@" | "[" | "]" | "\\" | "^" | "_" | "`" | "{" | "}" | "|" | "~" | @@ -99,6 +102,6 @@ export declare function altPrint(string: string, delay?: number): void; export declare function altPrintln(string: string, delay?: number): void; /** - * @brief Releases usb, optional, but allows to interchange with usbdisk + * @brief Releases usb, optional, but allows to switch usb profile */ export declare function quit(): void; diff --git a/applications/system/js_app/types/global.d.ts b/applications/system/js_app/types/global.d.ts index 01a8fbcef..052a2bb6a 100644 --- a/applications/system/js_app/types/global.d.ts +++ b/applications/system/js_app/types/global.d.ts @@ -14,47 +14,37 @@ 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 * * Reads a file at the specified path, interprets it as a JS value and returns - * said value. + * the last value pushed on the stack. * * @param path The path to the file + * @param scope An object to use as global scope while running this file */ -declare function load(path: string): any; +declare function load(path: string, scope?: object): any; /** * @brief Return 1-byte string whose ASCII code is the integer `n` @@ -210,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 { } diff --git a/applications/system/js_app/types/gui/index.d.ts b/applications/system/js_app/types/gui/index.d.ts index 85f191059..5efcfdc03 100644 --- a/applications/system/js_app/types/gui/index.d.ts +++ b/applications/system/js_app/types/gui/index.d.ts @@ -3,11 +3,28 @@ import type { Contract } from "../event_loop"; type Properties = { [K: string]: any }; export declare class View { + /** + * Assign value to property by name + * @param property Name of the property + * @param value Value to assign + */ set

(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> { + /** + * Create view instance with default values, can be changed later with set() + */ make(): V; + /** + * Create view instance with custom values, can be changed later with set() + * @param initial Dictionary of property names to values + */ makeWith(initial: Partial): V; }