diff --git a/.gitignore b/.gitignore index aefef5d5..7cfed59d 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,9 @@ #Kate .kate-swp +#Visual Studio Code +.vscode + *~ build/* diff --git a/.gitmodules b/.gitmodules index 898c0cb0..c21fc4fa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "lib/libpebble2"] path = lib/libpebble2 url = ../../pebble-dev/libpebble2 +[submodule "lib/jerryscript"] + path = lib/jerryscript + url = https://github.com/UDXS/jerryscript.git diff --git a/AUTHORS b/AUTHORS index 3451d06d..f6562dec 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,5 +3,6 @@ The RebbleOS Authors are: Barry Carter Joshua Wise NiVZ + Davit Markarian (UDXS) If you contribute code to RebbleOS, please add your name to this file. diff --git a/config.mk b/config.mk index 46b7b0f4..66429d7c 100644 --- a/config.mk +++ b/config.mk @@ -28,6 +28,7 @@ CFLAGS_all += -Irwatch/ui/animation CFLAGS_all += -Irwatch/input CFLAGS_all += -Irwatch/graphics CFLAGS_all += -Irwatch/event +CFLAGS_all += -Irwatch/js CFLAGS_all += -Ihw/platform/qemu CFLAGS_all += -DNGFX_IS_CORE -DREBBLEOS @@ -155,6 +156,7 @@ SRCS_all += rwatch/ui/notifications/notification_window.c SRCS_all += rwatch/ui/notifications/battery_overlay.c SRCS_all += rwatch/ui/notifications/mini_message.c SRCS_all += rwatch/ui/vibes.c +SRCS_all += rwatch/js/rocky_js.c SRCS_all += Watchfaces/simple.c SRCS_all += Watchfaces/nivz.c diff --git a/hw/platform/snowy_family/config.mk b/hw/platform/snowy_family/config.mk index 4de5c469..855fb078 100644 --- a/hw/platform/snowy_family/config.mk +++ b/hw/platform/snowy_family/config.mk @@ -9,6 +9,23 @@ CFLAGS_snowy_family += $(CFLAGS_driver_stm32_rtc) CFLAGS_snowy_family += $(CFLAGS_driver_stm32_backlight) CFLAGS_snowy_family += -Ihw/platform/snowy_family +CFLAGS_snowy_family += -Irwatch/js +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/ecma +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/debugger +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/ecma/base +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/ecma/builtin-objects +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/ecma/operations +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/jcontext +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/jmem +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/jrt +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/lit +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/parser/js +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/parser/regexp +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-core/vm +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-libm +CFLAGS_snowy_family += -Ilib/jerryscript/jerry-libm/include + SRCS_snowy_family = $(SRCS_stm32f4xx) SRCS_snowy_family += $(SRCS_driver_stm32_usart) SRCS_snowy_family += $(SRCS_driver_stm32_dma) @@ -26,6 +43,134 @@ SRCS_snowy_family += hw/platform/snowy_family/snowy_ambient.c SRCS_snowy_family += hw/platform/snowy_family/snowy_ext_flash.c SRCS_snowy_family += hw/platform/snowy_family/snowy_common.c +# Note: rocky_js.c is added to all platforms. +SRCS_snowy_family += rwatch/js/rocky_setjmp.c +SRCS_snowy_family += rwatch/js/rocky_port.c +SRCS_snowy_family += rwatch/js/rocky_canvas.c +SRCS_snowy_family += rwatch/js/rocky_lib.c +SRCS_snowy_family += rwatch/js/rocky_event.c + +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-alloc.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-gc.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-conversion.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-errol.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-external-pointers.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-number.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-string.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-value.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers-values-collection.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-helpers.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-init-finalize.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-lcache.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-literal-storage.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/base/ecma-property-hashmap.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-array.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-date.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-error.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-function.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-global.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-date.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-error.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-json.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-json.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-math.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-number.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-string.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror-prototype.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/builtin-objects/ecma-builtins.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-array-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-boolean-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-comparison.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-conversion.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-eval.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-exceptions.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-function-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-get-put-value.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-lex-env.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-number-arithmetic.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-number-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-objects-arguments.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-objects-general.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-objects.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-reference.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-regexp-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/ecma/operations/ecma-string-object.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jcontext/jcontext.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jerry.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jmem/jmem-allocator.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jmem/jmem-heap.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jmem/jmem-poolman.c +SRCS_snowy_family += lib/jerryscript/jerry-core/jrt/jrt-fatals.c +SRCS_snowy_family += lib/jerryscript/jerry-core/lit/lit-char-helpers.c +SRCS_snowy_family += lib/jerryscript/jerry-core/lit/lit-magic-strings.c +SRCS_snowy_family += lib/jerryscript/jerry-core/lit/lit-strings.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/byte-code.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/common.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-lexer.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser-expr.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser-mem.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser-scanner.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser-statm.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser-util.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/js/js-parser.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/regexp/re-bytecode.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/regexp/re-compiler.c +SRCS_snowy_family += lib/jerryscript/jerry-core/parser/regexp/re-parser.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/opcodes-ecma-arithmetics.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/opcodes-ecma-bitwise.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/opcodes-ecma-equality.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/opcodes-ecma-relational.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/opcodes.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/vm-stack.c +SRCS_snowy_family += lib/jerryscript/jerry-core/vm/vm.c + +SRCS_snowy_family += lib/jerryscript/jerry-libm/acos.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/asin.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/atan.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/atan2.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/ceil.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/copysign.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/exp.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/fabs.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/finite.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/floor.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/fmod.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/isnan.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/log.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/nextafter.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/pow.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/scalbn.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/sqrt.c +SRCS_snowy_family += lib/jerryscript/jerry-libm/trig.c + + + + LDFLAGS_snowy_family = $(LDFLAGS_stm32f4xx) LIBS_snowy_family = $(LIBS_stm32f4xx) diff --git a/lib/jerryscript b/lib/jerryscript new file mode 160000 index 00000000..9bef6be1 --- /dev/null +++ b/lib/jerryscript @@ -0,0 +1 @@ +Subproject commit 9bef6be1875cb0e9221f56211bfd5bdee445776b diff --git a/lib/neographics b/lib/neographics index 0b74ee50..2996647d 160000 --- a/lib/neographics +++ b/lib/neographics @@ -1 +1 @@ -Subproject commit 0b74ee50784f55e90cdbbfcd90b937324938ef24 +Subproject commit 2996647d76bb2a64ebeb9a45ce9e37c01ab721ee diff --git a/rcore/api_func_symbols.h b/rcore/api_func_symbols.h index 3c3723de..972f1cae 100644 --- a/rcore/api_func_symbols.h +++ b/rcore/api_func_symbols.h @@ -3,6 +3,7 @@ #include "librebble.h" #include "graphics_wrapper.h" #include "battery_state_service.h" +#include "rocky_js.h" GBitmap *gbitmap_create_with_resource_proxy(uint32_t resource_id); bool persist_exists(void); diff --git a/rcore/appmanager.h b/rcore/appmanager.h index dd611506..e99c3ea2 100644 --- a/rcore/appmanager.h +++ b/rcore/appmanager.h @@ -16,6 +16,7 @@ #include "node_list.h" #include #include "uuid.h" +#include "rocky_js.h" // TODO Make this dynamic. hacky #define NUM_APPS 3 @@ -148,6 +149,7 @@ typedef struct app_running_thread_t { struct CoreTimer *timer_head; qarena_t *arena; struct n_GContext *graphics_context; + rocky_thread_state rocky_state; } app_running_thread; /* in appmanager.c */ @@ -187,6 +189,4 @@ TickType_t appmanager_timer_get_next_expiry(app_running_thread *thread); App *appmanager_get_app(char *app_name); void appmanager_app_loader_init(void); -void rocky_event_loop_with_resource(uint16_t resource_id); - void timer_init(void); diff --git a/rcore/appmanager_app_runloop.c b/rcore/appmanager_app_runloop.c index 34c1541f..80415921 100644 --- a/rcore/appmanager_app_runloop.c +++ b/rcore/appmanager_app_runloop.c @@ -86,11 +86,6 @@ bool appmanager_is_app_shutting_down(void) return _this_thread->status == AppThreadUnloading; } -void rocky_event_loop_with_resource(uint16_t resource_id) -{ - app_event_loop(); -} - static void _draw(uint8_t force_draw) { /* Request a draw. This is mostly from an app invalidating something */ diff --git a/rcore/log.c b/rcore/log.c index 873e10c8..c212a82f 100644 --- a/rcore/log.c +++ b/rcore/log.c @@ -34,7 +34,7 @@ void log_printf_to_ar(const char *layer, const char *module, uint8_t level, cons // NOTE Probably shouldn't use from an ISR or it'll likely lock -#define PRBUFSIZ 160 +#define PRBUFSIZ 256 void log_printf(const char *layer, const char *module, uint8_t level, const char *filename, uint32_t line_no, const char *fmt, va_list ar) { uint8_t interrupt_set = 0; diff --git a/res b/res index 264a389c..7d16060d 160000 --- a/res +++ b/res @@ -1 +1 @@ -Subproject commit 264a389c031a5d3a5f5e568d62e59e1c347bb2c1 +Subproject commit 7d16060dd33914274c545cfde57b4bc9a6bae3aa diff --git a/rwatch/js/rocky_canvas.c b/rwatch/js/rocky_canvas.c new file mode 100644 index 00000000..04485cbc --- /dev/null +++ b/rwatch/js/rocky_canvas.c @@ -0,0 +1,4 @@ +#include +#include "rocky_canvas.h" + +bool rocky_font_parse(char* fontStr, RockyCanvasFont* outFont); diff --git a/rwatch/js/rocky_canvas.h b/rwatch/js/rocky_canvas.h new file mode 100644 index 00000000..827c3e03 --- /dev/null +++ b/rwatch/js/rocky_canvas.h @@ -0,0 +1,98 @@ +#pragma once +/* rockyjs.h + * + * Rocky.js (On-watch JavaScript) Implementation + * Rocky/JavaScript Canvas Library + * + * RebbleOS + * + * Author: Davit Markarian + */ + +#include "rebbleos.h" +#include "node_list.h" + +typedef uint8_t RockyCanvasFontSize; + +typedef enum +{ + RockyCanvasFontVariant_Normal, + RockyCanvasFontVariant_Light, + RockyCanvasFontVariant_Bold, + RockyCanvasFontVariant_Bolder +} RockyCanvasFontWeight; + +typedef enum +{ + RockyCanvasFontVariant_Default, + RockyCanvasFontVariant_Numbers +} RockyCanvasFontVariant; + +typedef enum +{ + RockyCanvasFontFamily_Gothic, + RockyCanvasFontFamily_Bitham, + RockyCanvasFontFamily_Bitham_numeric, + RockyCanvasFontFamily_Roboto, + RockyCanvasFontFamily_Roboto_subset, + RockyCanvasFontFamily_Droid_serif, + RockyCanvasFontFamily_Leco_numbers, + RockyCanvasFontFamily_Leco_numbers_am_pm, +} RockyCanvasFontFamily; + +// px [Weight] [Variant] +typedef struct +{ + RockyCanvasFontSize size; + RockyCanvasFontVariant weight; + RockyCanvasFontVariant variant; + RockyCanvasFontFamily family; +} RockyCanvasFont; + +bool rocky_font_parse(char *fontStr, RockyCanvasFont *outFont); + +typedef enum +{ + RockyCanvasPathPartType_Arc +} RockyCanvasPathPartType; + +typedef struct +{ + RockyCanvasPathPartType type; + int32_t x; + int32_t y; + union { + struct + { // Arc + int32_t radius; + float startAngle; + float endAngle; + }; + struct + { // Rectangle + int32_t width; + int32_t height; + }; + struct // Point (moveTo/lineTo) + { + }; + }; +} RockyCanvasPathPart; + +typedef struct +{ + int32_t currentX; + int32_t currentY; + list_head parts; +} RockyCanvasPath; + +typedef struct +{ + RockyCanvasPath path; + list_node node; +} RockyCanvasState; + +typedef struct +{ + RockyCanvasState state; +} RockyCanvas; \ No newline at end of file diff --git a/rwatch/js/rocky_event.c b/rwatch/js/rocky_event.c new file mode 100644 index 00000000..e6f681a6 --- /dev/null +++ b/rwatch/js/rocky_event.c @@ -0,0 +1,205 @@ +#include "rocky_lib.h" +#include "connection_service.h" +#include "rebble_time.h" +#include + +const char *const rocky_eventListenerTypeStrings[] = { + "UNKNOWN", + "draw", + "secondchange", + "minutechange", + "hourchange", + "daychange", + "memorypressure", + "message", + "postmessageconnected", + "postmessagedisconnected", + "postmessageerror" + +}; + +// TODO: Move to thread state +static list_head rocky_eventList = LIST_HEAD(rocky_eventList); + +#define ROCKY_EVENT_TYPES_COUNT (sizeof(rocky_eventListenerTypeStrings) / sizeof(char *)) + +int rocky_eventList_count(rocky_eventListenerType type) +{ + int count = 0; + rocky_eventListener *listener; + list_foreach(listener, &rocky_eventList, rocky_eventListener, node) + { + if (listener->type == type) + count++; + } + + return count; +} + +void rocky_eventHandleConnection(bool connected) +{ + return; + jerry_value_t undef = jerry_create_undefined(); + if (connected) + rocky_eventHandle(rocky_eventListenerType_postMessageConnected, undef); + else + rocky_eventHandle(rocky_eventListenerType_postMessageDisconnected, undef); + jerry_release_value(undef); +} + +void rocky_eventHandleTickTimer(struct tm *tick_time, TimeUnits units_changed) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Tick Timer event fired with flags 0x%x", units_changed); + + // TODO: better Date assembly + /* + jerry_value_t global = jerry_get_global_object(); + jerry_value_t jsDateName = jerry_create_string("Date"); + jerry_value_t jsDate = jerry_get_property(global, jsDateName); + jerry_release_value(jsDateName); + jerry_release_value(global); + + if (jerry_value_is_undefined(jsDate)) + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Date bad!"); + + jerry_value_t time = jerry_create_object(); + jerry_release_value(jsDate); */ + + jerry_value_t time = jerry_create_undefined(); + if ((units_changed & SECOND_UNIT) != 0) + rocky_eventHandle(rocky_eventListenerType_secondChange, time); + if ((units_changed & MINUTE_UNIT) != 0) + rocky_eventHandle(rocky_eventListenerType_minuteChange, time); + if ((units_changed & HOUR_UNIT) != 0) + rocky_eventHandle(rocky_eventListenerType_hourChange, time); + if ((units_changed & DAY_UNIT) != 0) + rocky_eventHandle(rocky_eventListenerType_dayChange, time); + + jerry_release_value(time); +} + +void rocky_eventManageConnections(rocky_eventListener *event) +{ + if (rocky_eventList_count(rocky_eventListenerType_postMessageConnected) + rocky_eventList_count(rocky_eventListenerType_postMessageDisconnected) == 1) + { + connection_service_subscribe((ConnectionHandlers){.pebble_app_connection_handler = NULL, .pebblekit_connection_handler = rocky_eventHandleConnection}); + bool connected = connection_service_peek_pebblekit_connection(); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Subscribing to Connection Service. Running Callback..."); + if (connected && event->type == rocky_eventListenerType_postMessageConnected) + jerry_run(event->callback); + else if (!connected && event->type == rocky_eventListenerType_postMessageDisconnected) + jerry_run(event->callback); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "'%s' callback executed immediately.", rocky_eventListenerTypeStrings[event->type]); + } + else if (rocky_eventList_count(rocky_eventListenerType_postMessageConnected) + rocky_eventList_count(rocky_eventListenerType_postMessageDisconnected) == 0) + { + connection_service_unsubscribe(); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Unsubscribed from Connection Service."); + } +} + +void rocky_eventManageTickTimer(rocky_eventListener *event) +{ + TimeUnits units = 0; + if (rocky_eventList_count(rocky_eventListenerType_secondChange) != 0) + units |= SECOND_UNIT; + if (rocky_eventList_count(rocky_eventListenerType_minuteChange) != 0) + units |= MINUTE_UNIT; + if (rocky_eventList_count(rocky_eventListenerType_hourChange) != 0) + units |= HOUR_UNIT; + if (rocky_eventList_count(rocky_eventListenerType_dayChange) != 0) + units |= DAY_UNIT; + + if (units != 0) + { + tick_timer_service_subscribe(units, rocky_eventHandleTickTimer); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Subscribed to Tick Timer Service with flags 0x%x.", units); + } + else + { + tick_timer_service_unsubscribe(); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Unsubscribed from Tick Timer Service."); + } +} + +rocky_eventListener *rocky_eventRegister(char *type, jerry_value_t callback) +{ + rocky_eventListener *event = app_malloc(sizeof(rocky_eventListener)); + if (event == NULL) + { + return NULL; + } + + event->type = rocky_eventListenerType_UNKNOWN; + + for (int i = 1; i < ROCKY_EVENT_TYPES_COUNT; i++) + { + if (strcmp(type, rocky_eventListenerTypeStrings[i]) == 0) + { + event->type = i; + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Event listener type matched as rocky_eventListenerType[%d].", i); + } + } + + if (event->type == rocky_eventListenerType_UNKNOWN) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Event listener type unknown."); + app_free(event); + return NULL; + } + + if (!jerry_value_is_function(callback)) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Event listener callback not a function."); + app_free(event); + return NULL; + } + + event->callback = jerry_acquire_value(callback); + + list_insert_tail(&rocky_eventList, &event->node); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Event listener added to list."); + + switch (event->type) + { + case rocky_eventListenerType_postMessageConnected: + case rocky_eventListenerType_postMessageDisconnected: + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Running message connection callback setup..."); + rocky_eventManageConnections(event); + case rocky_eventListenerType_secondChange: + case rocky_eventListenerType_minuteChange: + case rocky_eventListenerType_hourChange: + case rocky_eventListenerType_dayChange: + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Running tick timer callback setup..."); + rocky_eventManageTickTimer(event); + break; + default: + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "No additional work required."); + break; + } + + return event; +} + +void rocky_eventHandle(rocky_eventListenerType type, jerry_value_t arg) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Running handlers for event '%s'...", rocky_eventListenerTypeStrings[type]); + + rocky_eventListener *listener; + int count = 0; + list_foreach(listener, &rocky_eventList, rocky_eventListener, node) + { + if (listener->type == type) + { + count++; + APP_LOG("rocky", APP_LOG_LEVEL_INFO, " - Handler 0x%x", (uint32_t)listener->callback); + + jerry_value_t jsThis = jerry_create_undefined(); + jerry_value_t args[] = {arg}; + jerry_call_function(listener->callback, jsThis, args, 1); + //jerry_release_value(jsThis); + } + } + //jerry_cleanup(); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "%d handler(s) for '%s' executed.", count, rocky_eventListenerTypeStrings[type]); +} \ No newline at end of file diff --git a/rwatch/js/rocky_js.c b/rwatch/js/rocky_js.c new file mode 100644 index 00000000..427aef90 --- /dev/null +++ b/rwatch/js/rocky_js.c @@ -0,0 +1,176 @@ +#include "rebbleos.h" +#include "rocky_js.h" + +// TODO: Change the other 'defined' to match chalk, diorite +#if defined(REBBLE_PLATFORM_SNOWY) || defined(REBBLE_PLATFORM_SNOWY) || defined(REBBLE_PLATFORM_SNOWY) + +#include "jerry-api.h" +#include "jcontext.h" +#include "jmem-allocator.h" + +#include "rocky_lib.h" + + +void rocky_loop() +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Starting graphics..."); + Window *wnd = window_create(); + window_stack_push(wnd, true); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Starting app loop..."); + app_event_loop(); + window_destroy(wnd); + appmanager_app_quit(); +} + +void rocky_event_loop_with_resource(uint32_t resource_id) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Starting Rocky.js with snapshot (resource #%u)...", resource_id); + ResHandle snapHandle = resource_get_handle(resource_id); + size_t snapSize = resource_size(snapHandle); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "JS Snapshot Resource Size: %d bytes", snapSize); + + if (snapSize < 16) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "This snapshot is invalid (too small)."); + return; + } + if (snapSize > 128 * 1024) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "This snapshot is invalid (too large)."); + return; + } + + uint8_t *snapBuffer = app_malloc(snapSize); + if (snapBuffer == NULL) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Failed to allocate memory for JS snapshot resource."); + return; + } + + resource_load(snapHandle, snapBuffer, snapSize); + // TODO: Fix resource_load signature + /* + if (resource_load(snapHandle, snapBuffer, snapSize) != snapSize) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Failed to load JS snapshot resource into allocated memory."); + app_free(snapBuffer); + return; + } + */ + + if (memcmp("PJS", snapBuffer, 4) != 0) + { // Check for magic: 'PJS\0' + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Snapshot resource is not of valid format (invalid magic)."); + app_free(snapBuffer); + return; + } + + uint32_t snapVersion = *(snapBuffer + 4); + if (snapVersion != 1) + { // Check for the only version ever made: 0x1 + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Snapshot resource is not of valid format (invalid version)."); + app_free(snapBuffer); + return; + } + + // Skip ahead to actual JerryScript snapshot(format v6). + uint32_t *snapshot = (uint32_t *)(snapBuffer + 8); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "JS Snapshot Resource loaded successfully.", *snapshot); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Creating JerryScript Context..."); + jerry_global_context = app_calloc(1, sizeof(jerry_context_t)); + + if (jerry_global_context == NULL) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "JavaScript Context creation failed."); + app_free(snapBuffer); + return; + } + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Allocating JerryScript Heap..."); + uint8_t *heap_loc = app_calloc(1, sizeof(jmem_heap_t) + JMEM_ALIGNMENT); // Extra space needed in case of alignment + if (heap_loc == NULL) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Heap allocation failed."); + app_free(snapBuffer); + app_free(jerry_global_context); + return; + } + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Aligning JerryScript Heap to %d bytes from 0x%p...", JMEM_ALIGNMENT, heap_loc); + uint8_t *aligned_loc = heap_loc; + while ((uint32_t)aligned_loc % JMEM_ALIGNMENT != 0) + aligned_loc += 1; + jerry_global_heap = (jmem_heap_t *)aligned_loc; + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Aligned by %d bytes to 0x%p.", aligned_loc - heap_loc, aligned_loc); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Allocating JerryScript Hash Table..."); + jerry_global_hash_table = app_calloc(1, sizeof(jerry_hash_table_t)); + if (jerry_global_hash_table == NULL) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Global hash table allocation failed."); + app_free(snapBuffer); + app_free(jerry_global_context); + app_free(heap_loc); + return; + } + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Starting JavaScript..."); + jerry_init(JERRY_INIT_EMPTY); + + rocky_lib_build(); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Running JavaScript Snapshot:"); + jerry_value_t out = jerry_exec_snapshot(snapshot, snapSize - 8, false); + if (jerry_value_has_error_flag(out)) + { + char error[128]; + if (jerry_value_is_undefined(out)) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "UNDEF", error); + } + jerry_value_t msg = jerry_get_property(out, jerry_create_string("message")); + jerry_string_to_char_buffer(msg, error, 256); + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "JavaScript program errored out: %s", error); + + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Cleaning up..."); + jerry_cleanup(); + app_free(snapBuffer); + app_free(jerry_global_context); + app_free(heap_loc); + app_free(jerry_global_hash_table); + appmanager_app_quit(); + return; + } + char snapOut[128]; + jerry_string_to_char_buffer(jerry_value_to_string(out), snapOut, 256); + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "JavaScript program result: %s", snapOut); + + if (appmanager_get_current_thread()->rocky_state.fataled) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "JavaScript Engine fatal error."); + + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Cleaning up..."); + jerry_cleanup(); + app_free(snapBuffer); + app_free(jerry_global_context); + app_free(heap_loc); + app_free(jerry_global_hash_table); + appmanager_app_quit(); + return; + } + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Snapshot execution successful."); + + rocky_loop(); + + app_free(snapBuffer); + app_free(jerry_global_context); + app_free(heap_loc); + app_free(jerry_global_hash_table); +} +#else +void rocky_event_loop_with_resource(uint32_t resource_id) +{ + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Attempted to execute Rocky.js with resource %u. Rocky is not available on this platform. Exiting.", resource_id); +} +#endif \ No newline at end of file diff --git a/rwatch/js/rocky_js.h b/rwatch/js/rocky_js.h new file mode 100644 index 00000000..1afbee1f --- /dev/null +++ b/rwatch/js/rocky_js.h @@ -0,0 +1,21 @@ +#pragma once +/* rockyjs.h + * + * Rocky.js (On-watch JavaScript) Implementation + * + * RebbleOS + * + * Author: Davit Markarian + */ + +#include +//#include "window.h" +//#include "rocky_lib.h" + +typedef struct { + int fataled; + // TODO: Move eventList, window here. +} rocky_thread_state; + + +void rocky_event_loop_with_resource(uint32_t resource_id); \ No newline at end of file diff --git a/rwatch/js/rocky_lib.c b/rwatch/js/rocky_lib.c new file mode 100644 index 00000000..62e1ba1b --- /dev/null +++ b/rwatch/js/rocky_lib.c @@ -0,0 +1,162 @@ +#include "rebbleos.h" +#include "rocky_lib.h" + +#include "jcontext.h" + +#define ROCKY_TYPE_SPEC_PRINT(val, type) \ + if (jerry_value_is_##type((val))) \ + { \ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Variable " #val " is " #type "."); \ + } +#define ROCKY_TYPE_PRINT(val) \ + ROCKY_TYPE_SPEC_PRINT(val, array); \ + ROCKY_TYPE_SPEC_PRINT(val, boolean); \ + ROCKY_TYPE_SPEC_PRINT(val, constructor); \ + ROCKY_TYPE_SPEC_PRINT(val, function); \ + ROCKY_TYPE_SPEC_PRINT(val, number); \ + ROCKY_TYPE_SPEC_PRINT(val, null); \ + ROCKY_TYPE_SPEC_PRINT(val, object); \ + ROCKY_TYPE_SPEC_PRINT(val, string); \ + ROCKY_TYPE_SPEC_PRINT(val, undefined); + +jerry_value_t rocky_lib_on(jerry_value_t func, jerry_value_t this, jerry_value_t *args, jerry_length_t count) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Call to rocky.on / rocky.addEventListener with %d args.", count); + + if (count < 2) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Event listener argument count invalid."); + return jerry_create_error(JERRY_ERROR_TYPE, jerry_create_string("Event Invalid")); + } + + char type[33]; + for (int i = 0; i < 33; i++) + type[i] = '\0'; + + int typeLen = jerry_string_to_char_buffer(args[0], type, 32); + if (typeLen == 0) + { + APP_LOG("rocky", APP_LOG_LEVEL_ERROR, "Event listener type invalid."); + return jerry_create_error(JERRY_ERROR_TYPE, jerry_create_string("Event Invalid")); + } + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Event listener for '%s' requested.", type); + + rocky_eventListener *event = rocky_eventRegister(type, args[1]); + if (event == NULL) + { + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Event listener addition failed.", type); + return jerry_create_error(JERRY_ERROR_TYPE, jerry_create_string("Event Invalid")); + } + + return jerry_create_undefined(); +} + +jerry_value_t rocky_lib_off(jerry_value_t func, jerry_value_t this, jerry_value_t *args, jerry_length_t count) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Call to rocky.off / rocky.removeEventListener with %d args.", count); +} + +jerry_value_t rocky_lib_postMessage(jerry_value_t func, jerry_value_t this, jerry_value_t *args, jerry_length_t count) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Call to rocky.postMessage with %d args.", count); +} + +jerry_value_t rocky_lib_requestDraw(jerry_value_t func, jerry_value_t this, jerry_value_t *args, jerry_length_t count) +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Call to rocky.requestDraw with %d args.", count); +} + +void rocky_lib_addWatchInfo(jerry_value_t rocky) +{ + jerry_value_t objectName = jerry_create_string("watchInfo"); + jerry_value_t object = jerry_create_object(); + jerry_set_property(rocky, objectName, object); + jerry_release_value(objectName); + + jerry_value_t modelName = jerry_create_string("model"); + jerry_value_t model = jerry_create_string("pebble_time_steel_black_22mm"); + jerry_set_property(object, modelName, model); + jerry_release_value(modelName); + jerry_release_value(model); + + jerry_value_t platformName = jerry_create_string("platform"); + jerry_value_t platform = jerry_create_string("basalt"); // TODO: The other platforms (chalk, diorite) + jerry_set_property(object, platformName, platform); + jerry_release_value(platformName); + jerry_release_value(platform); + + jerry_value_t languageName = jerry_create_string("language"); + jerry_value_t language = jerry_create_string("en-US"); // TODO: Actually implement this, unlike Pebble + jerry_set_property(object, languageName, language); + jerry_release_value(languageName); + jerry_release_value(language); + + //jerry_value_t firmwareName = jerry_create_string("firmware"); + //jerry_value_t firmwareObject = jerry_create_object(); + + //jerry_set_property(object, platformName, platform); + //jerry_release_value(platformName); + //jerry_release_value(platform); + + jerry_release_value(object); +} + +void rocky_lib_build() +{ + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Creating Rocky Library..."); + jerry_value_t global = jerry_get_global_object(); + jerry_value_t libName = jerry_create_string((const jerry_char_t *)"_rocky"); + jerry_value_t libObject = jerry_create_object(); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Committing to JavaScript Global Environment..."); + jerry_set_property(global, libName, libObject); + jerry_release_value(global); + jerry_release_value(libName); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding function 'rocky.on'..."); + jerry_value_t libOnName = jerry_create_string((const jerry_char_t *)"on"); + jerry_value_t libOnFunc = jerry_create_external_function(rocky_lib_on); + jerry_set_property(libObject, libOnName, libOnFunc); + jerry_release_value(libOnName); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding alias 'rocky.addEventListener'..."); + jerry_value_t libAddEventListenerName = jerry_create_string((const jerry_char_t *)"addEventListener"); + jerry_set_property(libObject, libAddEventListenerName, libOnFunc); + jerry_release_value(libAddEventListenerName); + jerry_release_value(libOnFunc); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding function 'rocky.off'..."); + jerry_value_t libOffName = jerry_create_string((const jerry_char_t *)"off"); + jerry_value_t libOffFunc = jerry_create_external_function(rocky_lib_off); + jerry_set_property(libObject, libOffName, libOffFunc); + jerry_release_value(libOffName); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding alias 'rocky.removeEventListener'..."); + jerry_value_t libRemoveEventListenerName = jerry_create_string((const jerry_char_t *)"removeEventListener"); + jerry_set_property(libObject, libRemoveEventListenerName, libOffFunc); + jerry_release_value(libRemoveEventListenerName); + jerry_release_value(libOffFunc); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding function 'rocky.postMessage'..."); + jerry_value_t libPostMessageName = jerry_create_string((const jerry_char_t *)"postMessage"); + jerry_value_t libPostMessageFunc = jerry_create_external_function(rocky_lib_postMessage); + jerry_set_property(libObject, libPostMessageName, libPostMessageFunc); + jerry_release_value(libPostMessageName); + jerry_release_value(libPostMessageFunc); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding function 'rocky.requestDraw'..."); + jerry_value_t libRequestDrawName = jerry_create_string((const jerry_char_t *)"requestDraw"); + jerry_value_t libRequestDrawFunc = jerry_create_external_function(rocky_lib_requestDraw); + jerry_set_property(libObject, libRequestDrawName, libRequestDrawFunc); + jerry_release_value(libRequestDrawName); + jerry_release_value(libRequestDrawFunc); + + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Adding object 'rocky.watchInfo'..."); + rocky_lib_addWatchInfo(libObject); + + //TODO: userPreferences + + jerry_release_value(libObject); + APP_LOG("rocky", APP_LOG_LEVEL_INFO, "Done building Rocky library."); +} diff --git a/rwatch/js/rocky_lib.h b/rwatch/js/rocky_lib.h new file mode 100644 index 00000000..ef2c2a64 --- /dev/null +++ b/rwatch/js/rocky_lib.h @@ -0,0 +1,44 @@ +#pragma once +/* rocky_lib.h + * + * Rocky.js (On-watch JavaScript) Implementation + * Rocky API Library + * RebbleOS + * + * Author: Davit Markarian + */ + +#include "jerry-api.h" +#include "node_list.h" +#include "rocky_canvas.h" + +typedef enum +{ + rocky_eventListenerType_UNKNOWN, + rocky_eventListenerType_draw, + rocky_eventListenerType_secondChange, + rocky_eventListenerType_minuteChange, + rocky_eventListenerType_hourChange, + rocky_eventListenerType_dayChange, + rocky_eventListenerType_memoryPressure, + rocky_eventListenerType_message, + rocky_eventListenerType_postMessageConnected, + rocky_eventListenerType_postMessageDisconnected, + rocky_eventListenerType_postMessageError, + +} rocky_eventListenerType; + +extern const char* const rocky_eventListenerTypeStrings[]; + +typedef struct +{ + rocky_eventListenerType type; + jerry_value_t callback; + list_node node; +} rocky_eventListener; + +rocky_eventListener *rocky_eventRegister(char *type, jerry_value_t callback); +rocky_eventListener *rocky_eventRemove(char *type, jerry_value_t callback); +void rocky_eventHandle(rocky_eventListenerType type, jerry_value_t arg); + +void rocky_lib_build(); \ No newline at end of file diff --git a/rwatch/js/rocky_port.c b/rwatch/js/rocky_port.c new file mode 100644 index 00000000..7653368c --- /dev/null +++ b/rwatch/js/rocky_port.c @@ -0,0 +1,72 @@ +#include "jerry-api.h" +#include "jerry-port.h" +#include "rebbleos.h" +#include +#include + +void jerry_port_fatal(jerry_fatal_code_t code) +{ + SYS_LOG("rocky", APP_LOG_LEVEL_ERROR, "VM Fatal Error Code %d. Quitting.", code); + appmanager_get_current_thread()->rocky_state.fataled = true; + appmanager_app_quit(); +} + +const char *logLevelString[] = { + [JERRY_LOG_LEVEL_ERROR] = "error", + [JERRY_LOG_LEVEL_WARNING] = "warning", + [JERRY_LOG_LEVEL_DEBUG] = "debug", + [JERRY_LOG_LEVEL_TRACE] = "trace", +}; + +extern int vsfmt(char *buf, unsigned int len, const char *ifmt, va_list ap); + +void jerry_port_log(jerry_log_level_t level, const char *fmt, ...) +{ + LogLevel appLevel; + switch (level) + { + case JERRY_LOG_LEVEL_ERROR: + appLevel = APP_LOG_LEVEL_ERROR; + break; + case JERRY_LOG_LEVEL_WARNING: + appLevel = APP_LOG_LEVEL_WARNING; + break; + case JERRY_LOG_LEVEL_DEBUG: + appLevel = APP_LOG_LEVEL_DEBUG; + break; + case JERRY_LOG_LEVEL_TRACE: + appLevel = APP_LOG_LEVEL_DEBUG_VERBOSE; + break; + default: + appLevel = APP_LOG_LEVEL_INFO; + } + + va_list parts; + va_start(parts, fmt); + char outBuffer[256]; + vsfmt(outBuffer, 256, fmt, parts); + SYS_LOG("rocky", appLevel, "js:%s> %s", logLevelString[level], outBuffer); + va_end(parts); +} + +void jerry_port_console(const char *fmt, ...) +{ + va_list parts; + va_start(parts, fmt); + char outBuffer[256]; + vsfmt(outBuffer, 256, fmt, parts); + SYS_LOG("rocky", APP_LOG_LEVEL_INFO, "js> %s", outBuffer); + va_end(parts); +} + +bool jerry_port_get_time_zone(jerry_time_zone_t *tz) +{ + tz->offset = 0; + tz->daylight_saving_time = rebble_time_get_tm()->tm_isdst; + return true; +} + +double jerry_port_get_current_time() +{ + return (double)rcore_get_time(); +} \ No newline at end of file diff --git a/rwatch/js/rocky_setjmp.c b/rwatch/js/rocky_setjmp.c new file mode 100644 index 00000000..ef436bbf --- /dev/null +++ b/rwatch/js/rocky_setjmp.c @@ -0,0 +1,13 @@ +#include +#include + +int setjmp(jmp_buf env) +{ + KERN_LOG("rocky", APP_LOG_LEVEL_ERROR, "Called setjmp. This should not be possible. Expect instability."); + return 0; +} + +void longjmp(jmp_buf env, int val) +{ + KERN_LOG("rocky", APP_LOG_LEVEL_ERROR, "Called longjmp. This should not be possible. Definitely unstable."); +} \ No newline at end of file