JS: Fourth batch of OFW PR changes

This commit is contained in:
Willy-JL
2024-10-25 17:27:41 +01:00
parent 56332919de
commit 96e5b24a71
9 changed files with 64 additions and 28 deletions

View File

@@ -17,18 +17,16 @@ let views = {
empty: emptyView.make(),
keyboard: textInputView.makeWith({
header: "Enter your name",
defaultText: flipper.getName(),
defaultTextClear: true,
// Props for makeWith() are passed in reverse order, so maxLength must be after defaultText
minLength: 0,
maxLength: 32,
defaultText: flipper.getName(),
defaultTextClear: true,
}),
helloDialog: dialogView.make(),
bytekb: byteInputView.makeWith({
header: "Look ma, I'm a header text!",
defaultData: Uint8Array([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]),
// Props for makeWith() are passed in reverse order, so length must be after defaultData
length: 8,
defaultData: Uint8Array([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]),
}),
longText: textBoxView.makeWith({
text: "This is a very long string that demonstrates the TextBox view. Use the D-Pad to scroll backwards and forwards.\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse rhoncus est malesuada quam egestas ultrices. Maecenas non eros a nulla eleifend vulputate et ut risus. Quisque in mauris mattis, venenatis risus eget, aliquam diam. Fusce pretium feugiat mauris, ut faucibus ex volutpat in. Phasellus volutpat ex sed gravida consectetur. Aliquam sed lectus feugiat, tristique lectus et, bibendum lacus. Ut sit amet augue eu sapien elementum aliquam quis vitae tortor. Vestibulum quis commodo odio. In elementum fermentum massa, eu pellentesque nibh cursus at. Integer eleifend lacus nec purus elementum sodales. Nulla elementum neque urna, non vulputate massa semper sed. Fusce ut nisi vitae dui blandit congue pretium vitae turpis.",

View File

@@ -24,11 +24,10 @@ let views = {
}),
textInput: textInput.makeWith({
header: "Type JavaScript Code:",
defaultText: "2+2",
defaultTextClear: true,
// Props for makeWith() are passed in reverse order, so maxLength must be after defaultText
minLength: 0,
maxLength: 256,
defaultText: "2+2",
defaultTextClear: true,
}),
loading: loading.make(),
};

View File

@@ -198,12 +198,18 @@ static void js_require(struct mjs* mjs) {
static void js_parse_int(struct mjs* mjs) {
const char* str;
JS_FETCH_ARGS_OR_RETURN(mjs, JS_AT_LEAST, JS_ARG_STR(&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));
if(mjs_nargs(mjs) >= 2) {
mjs_val_t base_arg = mjs_arg(mjs, 1);
if(!mjs_is_number(base_arg)) {
mjs_prepend_errorf(mjs, MJS_BAD_ARGS_ERROR, "Base must be a number");
mjs_return(mjs, MJS_UNDEFINED);
}
base = mjs_get_int(mjs, base_arg);
}
int32_t num;
if(strint_to_int32(str, NULL, &num, base) != StrintParseNoError) {
num = 0;

View File

@@ -8,6 +8,7 @@
typedef struct {
uint8_t* buffer;
size_t buffer_size;
size_t default_data_size;
FuriString* header;
FuriSemaphore* input_semaphore;
JsEventLoopContract contract;
@@ -38,7 +39,14 @@ static bool
len_assign(struct mjs* mjs, ByteInput* input, JsViewPropValue value, JsByteKbContext* context) {
UNUSED(mjs);
UNUSED(input);
context->buffer_size = (size_t)(value.number);
size_t new_buffer_size = value.number;
if(new_buffer_size < context->default_data_size) {
// Avoid confusing parameters from user
mjs_prepend_errorf(
mjs, MJS_BAD_ARGS_ERROR, "length must be larger than defaultData length");
return false;
}
context->buffer_size = new_buffer_size;
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
byte_input_set_result_callback(
input,
@@ -57,16 +65,24 @@ static bool default_data_assign(
JsByteKbContext* context) {
UNUSED(mjs);
mjs_val_t array_buf = value.array;
mjs_val_t array_buf = value.term;
if(mjs_is_data_view(array_buf)) {
array_buf = mjs_dataview_get_buf(mjs, array_buf);
}
size_t default_data_len = 0;
char* default_data = mjs_array_buf_get_ptr(mjs, array_buf, &default_data_len);
memcpy(
context->buffer,
(uint8_t*)default_data,
MIN((size_t)context->buffer_size, default_data_len));
char* default_data = mjs_array_buf_get_ptr(mjs, array_buf, &context->default_data_size);
if(context->buffer_size < context->default_data_size) {
// Ensure buffer is large enough for defaultData
context->buffer_size = context->default_data_size;
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
}
memcpy(context->buffer, (uint8_t*)default_data, context->default_data_size);
if(context->buffer_size > context->default_data_size) {
// Reset previous data after defaultData
memset(
context->buffer + context->default_data_size,
0x00,
context->buffer_size - context->default_data_size);
}
byte_input_set_result_callback(
input,

View File

@@ -216,14 +216,14 @@ static bool
expected_type = "array";
break;
}
c_value = (JsViewPropValue){.array = value};
c_value = (JsViewPropValue){.term = value};
} break;
case JsViewPropTypeTypedArr: {
if(!mjs_is_typed_array(value)) {
expected_type = "typed_array";
break;
}
c_value = (JsViewPropValue){.array = value};
c_value = (JsViewPropValue){.term = value};
} break;
case JsViewPropTypeBool: {
if(!mjs_is_boolean(value)) {

View File

@@ -16,8 +16,8 @@ typedef enum {
typedef union {
const char* string;
int32_t number;
mjs_val_t array;
bool boolean;
mjs_val_t term;
} JsViewPropValue;
/**

View File

@@ -33,9 +33,9 @@ static bool
static bool items_assign(struct mjs* mjs, Submenu* submenu, JsViewPropValue value, void* context) {
UNUSED(mjs);
submenu_reset(submenu);
size_t len = mjs_array_length(mjs, value.array);
size_t len = mjs_array_length(mjs, value.term);
for(size_t i = 0; i < len; i++) {
mjs_val_t item = mjs_array_get(mjs, value.array, i);
mjs_val_t item = mjs_array_get(mjs, value.term, i);
if(!mjs_is_string(item)) return false;
submenu_add_item(submenu, mjs_get_string(mjs, &item, NULL), i, choose_callback, context);
}

View File

@@ -8,6 +8,7 @@
typedef struct {
char* buffer;
size_t buffer_size;
size_t default_text_size;
FuriString* header;
bool default_text_clear;
FuriSemaphore* input_semaphore;
@@ -49,7 +50,14 @@ static bool max_len_assign(
JsViewPropValue value,
JsKbdContext* context) {
UNUSED(mjs);
context->buffer_size = (size_t)(value.number + 1);
size_t new_buffer_size = value.number + 1;
if(new_buffer_size < context->default_text_size) {
// Avoid confusing parameters from user
mjs_prepend_errorf(
mjs, MJS_BAD_ARGS_ERROR, "maxLength must be larger than defaultText length");
return false;
}
context->buffer_size = new_buffer_size;
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
text_input_set_result_callback(
input,
@@ -70,6 +78,13 @@ static bool default_text_assign(
UNUSED(input);
if(value.string) {
context->default_text_size = strlen(value.string) + 1;
if(context->buffer_size < context->default_text_size) {
// Ensure buffer is large enough for defaultData
context->buffer_size = context->default_text_size;
context->buffer = realloc(context->buffer, context->buffer_size); //-V701
}
// Also trim excess previous data with strlcpy()
strlcpy(context->buffer, value.string, context->buffer_size);
text_input_set_result_callback(
input,

View File

@@ -31,8 +31,10 @@ 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
* the last value pushed on the stack.
* Reads a file at the specified path and runs it as JS, returning the last evaluated value.
*
* The result is cached and this filepath will not re-evaluated on future
* load() calls for this session.
*
* @param path The path to the file
* @param scope An object to use as global scope while running this file