diff options
author | James Prestwood <james.prestwood@intel.com> | 2017-04-21 14:24:49 -0700 |
---|---|---|
committer | Geoff Gustafson <geoff@linux.intel.com> | 2017-05-18 14:58:33 -0700 |
commit | ac7a7a2bde146f28ba10efd99018260c6b249fe5 (patch) | |
tree | 0f13ba07f2b81a5a1e34bb9e85edaf45bd5474b5 | |
parent | df4614cd7dd235f1bf47e7b57ad52a0bf733d927 (diff) |
[promise] Updated Jerryscript/ZJS to use promises
- Updated get/set native handle API's
- ZJS promise API's use JrS built in promises
Signed-off-by: James Prestwood <james.prestwood@intel.com>
38 files changed, 589 insertions, 746 deletions
@@ -60,7 +60,8 @@ JERRY_BASE ?= $(ZJS_BASE)/deps/jerryscript EXT_JERRY_FLAGS ?= -DENABLE_ALL_IN_ONE=ON \ -DFEATURE_PROFILE=$(ZJS_BASE)/outdir/$(BOARD)/jerry_feature.profile \ -DFEATURE_ERROR_MESSAGES=ON \ - -DJERRY_LIBM=OFF + -DJERRY_LIBM=OFF \ + -DJERRY_PORT_DEFAULT=OFF # Generate and run snapshot as byte code instead of running JS directly ifneq (,$(filter $(MAKECMDGOALS),ide ashell linux)) diff --git a/Makefile.linux b/Makefile.linux index 25ea8b4..f05453a 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -24,19 +24,20 @@ CORE_SRC += src/zjs_a101_pins.c \ src/main.c \ src/zjs_modules.c \ src/zjs_performance.c \ - src/zjs_promise.c \ src/zjs_script.c \ src/zjs_timers.c \ src/zjs_test_promise.c \ src/zjs_test_callbacks.c \ src/zjs_unit_tests.c \ - src/zjs_util.c + src/zjs_util.c \ + src/jerry-port/zjs_jerry_port.c CORE_OBJ = $(CORE_SRC:%.c=%.o) LINUX_INCLUDES += -Isrc/ \ -I$(ZJS_BASE)/outdir/include \ - -I$(JERRY_BASE)/jerry-core + -I$(JERRY_BASE)/jerry-core \ + -I$(JERRY_BASE)/jerry-core/jrt JERRY_LIBS += -l jerry-core -lm @@ -61,7 +62,8 @@ LINUX_DEFINES += -DZJS_LINUX_BUILD \ -DBUILD_MODULE_A101 \ -DBUILD_MODULE_GPIO \ -DZJS_GPIO_MOCK \ - -DZJS_FIND_FUNC_NAME + -DZJS_FIND_FUNC_NAME \ + -DJERRY_PORT_ENABLE_JOBQUEUE LINUX_FLAGS += -fno-asynchronous-unwind-tables \ -fno-omit-frame-pointer \ @@ -109,7 +111,7 @@ LINUX_INCLUDES += -I$(OCF_ROOT)/deps/tinydtls \ -I$(OCF_ROOT)/util \ -I$(OCF_ROOT)/messaging/coap \ -I$(OCF_ROOT)/api \ - -include $(ZJS_BASE)/src/zjs_ocf_config.h + -include $(ZJS_BASE)/src/zjs_ocf_config.h \ include Makefile.ocf_linux @@ -126,7 +128,12 @@ $(BUILD_DIR)/%.o:%.c .PHONY: linux linux: $(BUILD_OBJ) - @cd deps/jerryscript; python ./tools/build.py --error-messages ON $(VERBOSE) --mem-heap 16; + @cd deps/jerryscript; python ./tools/build.py --error-messages ON $(VERBOSE) \ + --mem-heap 16 \ + --profile=es2015-subset \ + --jerry-port-default=OFF \ + --jerry-cmdline OFF \ + --jerry-libc OFF; @echo [LD] $(BUILD_DIR)/jslinux @gcc $(LINUX_INCLUDES) $(JERRY_LIB_PATH) -o $(BUILD_DIR)/jslinux $(BUILD_OBJ) $(LINUX_FLAGS) $(CFLAGS) $(LINUX_DEFINES) $(LINUX_LIBS) diff --git a/deps/jerryscript b/deps/jerryscript -Subproject 4420401cf5c7810a8c5c9404e6921d88d30c16a +Subproject ede13835b2217c82a8c93808b731c4d47f9c683 diff --git a/samples/OcfClient.js b/samples/OcfClient.js index 53f6a6c..f0224f2 100644 --- a/samples/OcfClient.js +++ b/samples/OcfClient.js @@ -32,20 +32,17 @@ var lightOn = true; // TODO: Must save away the timer handle or else GC will destroy it after a few iterations var t1 = null; -function onfound(resource) { - t1 = setInterval(function() { +ocf.start(); + +client.findResources({ resourceType:"core.light" }).then(function(resource) { + console.log("findResources() was successful, deviceId=" + resource.deviceId); + t1 = setInterval(function(resource) { client.retrieve(resource.deviceId, { observable: false }).then(function(res) { console.log("retrieve() was successful, deviceId=" + res.deviceId); - }).catch(function(error) { + }, function(error) { console.log("retrieve() returned an error: " + error.name); }); - }, 1000); -} - -ocf.start(); - -client.findResources({ resourceType:"core.light" }, onfound).then(function(resource) { - console.log("findResources() was successful, deviceId=" + resource.deviceId); -}).catch(function(error) { + }, 1000, resource); +}, function(error) { console.log("findResources() returned an error: " + error.name); }); diff --git a/samples/OcfClientUpdate.js b/samples/OcfClientUpdate.js index 11e6a8a..c71f112 100644 --- a/samples/OcfClientUpdate.js +++ b/samples/OcfClientUpdate.js @@ -41,10 +41,10 @@ function onfound(resource) { console.log("update successful"); client.retrieve(resource.deviceId, { observable: false }).then(function(res) { console.log("retrieve() was successful, deviceId=" + res.deviceId); - }).catch(function(error) { + }, function(error) { console.log("retrieve() returned an error: " + error.name); }); - }).catch(function(error) { + }, function(error) { console.log("Error updating name='" + error.name + "' message='" + error.message + "' " + "code=" + error.errorCode); }); @@ -55,6 +55,6 @@ ocf.start(); client.findResources({ resourceType:"core.light" }, onfound).then(function(resource) { console.log("findResources() was successful, deviceId=" + resource.deviceId); -}).catch(function(error) { +}, function(error) { console.log("findResources() returned an error: " + error.name); }); diff --git a/samples/OcfDeviceInfo.js b/samples/OcfDeviceInfo.js index 5f3a90a..8ddf3ac 100644 --- a/samples/OcfDeviceInfo.js +++ b/samples/OcfDeviceInfo.js @@ -25,7 +25,7 @@ function found(resource) { client.getDeviceInfo(resource.deviceId).then(function(info) { console.log("Got device info for: " + info.uuid); - }).catch(function(error) { + }, function(error) { console.log("Error getting device info: " + error.name); }); } @@ -34,6 +34,6 @@ ocf.start(); client.findResources({ resourceType:"oic.r.light" }, found).then(function(resource) { console.log("findResources() was successful, deviceId=" + resource.deviceId); -}).catch(function(error) { +}, function(error) { console.log("findResources() returned an error: " + error.name); }); diff --git a/samples/OcfNotifyServer.js b/samples/OcfNotifyServer.js deleted file mode 100644 index 2616d86..0000000 --- a/samples/OcfNotifyServer.js +++ /dev/null @@ -1,38 +0,0 @@ -var server = require('ocf').server; - -console.log("Started OCF server"); - -var MyProperties = { - state: true -} - -var resourceInit = { - resourcePath: "/light/1", - resourceTypes: ["oic.r.light"], - interfaces: ["/oic/if/w"], - discoverable: true, - observable: true, - properties: MyProperties -} - -var MyResource = null; -var timer = null; - -server.on('retrieve', function(request, observe) { - console.log("retrieve"); - request.respond(MyProperties); -}); -server.on('update', function(request) { - console.log("update"); -}); - -server.register(resourceInit).then(function(resource) { - console.log("Registered resource"); - MyResource = resource; - timer = setInterval(function() { - MyProperties.state = (MyProperties.state) ? false : true; - server.notify(MyResource); - }, 1000); -}).catch(function(error) { - console.log("Error registering"); -}); diff --git a/samples/OcfPlatformInfo.js b/samples/OcfPlatformInfo.js index fd9060e..83c9960 100644 --- a/samples/OcfPlatformInfo.js +++ b/samples/OcfPlatformInfo.js @@ -24,7 +24,7 @@ function onfound(resource) { client.getPlatformInfo(resource.deviceId).then(function(info) { console.log("Got platform info for: " + info.id); - }).catch(function(error) { + }, function(error) { console.log("Error getting platform info: " + error.name); }); } @@ -33,6 +33,6 @@ ocf.start(); client.findResources({ resourceType:"oic.r.light" }, onfound).then(function(resource) { console.log("findResources() was successful, deviceId=" + resource.deviceId); -}).catch(function(error) { +}, function(error) { console.log("findResources() returned an error: " + error.name); }); diff --git a/samples/OcfSensorClient.js b/samples/OcfSensorClient.js index fad10cb..a4d0e6e 100644 --- a/samples/OcfSensorClient.js +++ b/samples/OcfSensorClient.js @@ -34,7 +34,7 @@ function onfound(resource) { t1 = setInterval(function() { client.retrieve(resource.deviceId, { observable: false }).then(function(res) { console.log("retrieve() was successful, deviceId=" + res.deviceId); - }).catch(function(error) { + }, function(error) { console.log("retrieve() returned an error: " + error.name); }); }, 1000); @@ -44,6 +44,6 @@ ocf.start(); client.findResources({ resourceType:"core.sensor" }, onfound).then(function(resource) { console.log("findResources() was successful, deviceId=" + resource.deviceId); -}).catch(function(error) { +}, function(error) { console.log("findResources() returned an error: " + error.name); }); diff --git a/samples/OcfSensorServer.js b/samples/OcfSensorServer.js index f472051..55cdb90 100644 --- a/samples/OcfSensorServer.js +++ b/samples/OcfSensorServer.js @@ -59,8 +59,8 @@ server.register(resourceInit).then(function(resource) { } request.respond(MyProperties); }); -}).catch(function(error) { - console.log('Error registering'); +}, function(error) { + console.log("Error registering"); }); ocf.start(); diff --git a/samples/OcfServer.js b/samples/OcfServer.js index d948799..c1f0277 100644 --- a/samples/OcfServer.js +++ b/samples/OcfServer.js @@ -47,7 +47,7 @@ server.register(resourceInit).then(function(resource) { request.target.resourcePath + " observe=" + observe); request.respond(MyProperties).then(function() { console.log("respond success"); - }).catch(function(error) { + }, function(error) { console.log("respond error: " + error.name); }); }); @@ -61,7 +61,7 @@ server.register(resourceInit).then(function(resource) { } request.respond(MyProperties); }); -}).catch(function(error) { +}, function(error) { console.log("Error registering"); }); diff --git a/scripts/analyze.sh b/scripts/analyze.sh index 032cdf5..2a42dd6 100755 --- a/scripts/analyze.sh +++ b/scripts/analyze.sh @@ -250,6 +250,7 @@ if check_for_require ocf || check_config_file ZJS_OCF; then MODULES+=" -DBUILD_MODULE_OCF" MODULES+=" -DBUILD_MODULE_EVENTS" MODULES+=" -DBUILD_MODULE_PROMISE" + MODULES+=" -DJERRY_PORT_ENABLE_JOBQUEUE" if grep -q "require *( *['\"]ocf['\"] *)*;" $SCRIPT; then OCF_OBJ=$(grep "require('ocf')" $SCRIPT | cut -d'=' -f1 | cut -d' ' -f2) if grep -q "$OCF_OBJ.client" $SCRIPT; then @@ -447,9 +448,12 @@ fi if check_for_require test_promise; then >&2 echo Using module: test_promise - MODULES+=" -DBUILD_MODULE_TEST_PROMISE -DBUILD_MODULE_PROMISE" + MODULES+=" -DBUILD_MODULE_TEST_PROMISE -DBUILD_MODULE_PROMISE -DJERRY_PORT_ENABLE_JOBQUEUE" echo "export ZJS_TEST_PROMISE=y" >> $CONFFILE echo "export ZJS_PROMISE=y" >> $CONFFILE + feature_on CONFIG_DISABLE_ES2015_PROMISE_BUILTIN + feature_on CONFIG_DISABLE_ES2015_BUILTIN + feature_on CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN fi if check_for_require test_callbacks; then @@ -548,6 +552,7 @@ fi if check_for_feature "Promise("; then >&2 echo Using JrS module: Promise + MODULES+=" -DJERRY_PORT_ENABLE_JOBQUEUE" feature_on CONFIG_DISABLE_ES2015_PROMISE_BUILTIN feature_on CONFIG_DISABLE_ES2015_BUILTIN feature_on CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN diff --git a/src/Makefile.base b/src/Makefile.base index 810ade6..4d0c4fb 100644 --- a/src/Makefile.base +++ b/src/Makefile.base @@ -14,6 +14,7 @@ ccflags-y += -Wno-error=format ccflags-y += -D_XOPEN_SOURCE=700 ccflags-y += -I$(JERRY_BASE)/jerry-core +ccflags-y += -I$(JERRY_BASE)/jerry-core/jrt ccflags-y += -I$(ZEPHYR_BASE)/drivers ccflags-y += -I$(ZJS_BASE)/outdir/include @@ -53,7 +54,8 @@ obj-y += main.o \ zjs_modules.o \ zjs_script.o \ zjs_timers.o \ - zjs_util.o + zjs_util.o \ + jerry-port/zjs_jerry_port.o obj-$(ZJS_BOARD) += zjs_board.o obj-$(ZJS_BUFFER) += zjs_buffer.o @@ -75,7 +77,6 @@ obj-$(ZJS_OCF) += zjs_ocf_client.o \ zjs_ocf_common.o obj-$(ZJS_TEST_PROMISE) += zjs_test_promise.o obj-$(ZJS_TEST_CALLBACKS) += zjs_test_callbacks.o -obj-$(ZJS_PROMISE) += zjs_promise.o obj-$(ZJS_NET_CONFIG) += zjs_net_config.o obj-$(ZJS_WS) += zjs_web_sockets.o diff --git a/src/ashell/jerry-code.c b/src/ashell/jerry-code.c index 11db50e..3a521c7 100644 --- a/src/ashell/jerry-code.c +++ b/src/ashell/jerry-code.c @@ -13,7 +13,7 @@ #include <ctype.h> /* JerryScript includes */ -#include "jerry-port.h" +#include "jerryscript-port.h" #include "jerry-code.h" #include "file-utils.h" @@ -26,8 +26,6 @@ #include "../zjs_timers.h" #include "../zjs_util.h" -void jerry_port_default_set_log_level(jerry_log_level_t level); /** Inside jerry-port-default.h */ - #include "comms-uart.h" static jerry_value_t parsed_code = 0; @@ -104,21 +102,21 @@ static void add_to_list(requires_list_t **list, const char *item) static void javascript_print_value(const jerry_value_t value) { if (jerry_value_is_undefined(value)) { - jerry_port_console("undefined"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "undefined"); } else if (jerry_value_is_null(value)) { - jerry_port_console("null"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "null"); } else if (jerry_value_is_boolean(value)) { if (jerry_get_boolean_value(value)) { - jerry_port_console("true"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "true"); } else { - jerry_port_console("false"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "false"); } } /* Float value */ else if (jerry_value_is_number(value)) { double val = jerry_get_number_value(value); // %lf prints an empty value :? - jerry_port_console("Number [%d]\n", (int) val); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "Number [%d]\n", (int) val); } /* String value */ else if (jerry_value_is_string(value)) { @@ -126,19 +124,19 @@ static void javascript_print_value(const jerry_value_t value) jerry_size_t size = 0; char *str = zjs_alloc_from_jstring(value, &size); if (str) { - jerry_port_console("%s", str); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "%s", str); zjs_free(str); } else { - jerry_port_console("[String too long]"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "[String too long]"); } } /* Object reference */ else if (jerry_value_is_object(value)) { - jerry_port_console("[JS object]"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "[JS object]"); } - jerry_port_console("\n"); + jerry_port_log(JERRY_LOG_LEVEL_TRACE, "\n"); } static char *read_file_alloc(const char *file_name, ssize_t *size) @@ -372,7 +370,6 @@ static void javascript_print_error(jerry_value_t error_value) void javascript_eval_code(const char *source_buffer, ssize_t size) { - jerry_port_default_set_log_level(JERRY_LOG_LEVEL_TRACE); ZVAL ret_val = jerry_eval((jerry_char_t *) source_buffer, size, false); if (jerry_value_has_error_flag(ret_val)) { @@ -419,7 +416,6 @@ int javascript_parse_code(const char *file_name) { int ret = -1; javascript_stop(); - jerry_port_default_set_log_level(JERRY_LOG_LEVEL_TRACE); char *buf = NULL; ssize_t size; diff --git a/src/ashell/shell-state.c b/src/ashell/shell-state.c index de6b957..c550aa6 100644 --- a/src/ashell/shell-state.c +++ b/src/ashell/shell-state.c @@ -13,7 +13,7 @@ #include <misc/printk.h> #include <misc/reboot.h> #include <ctype.h> -#include <jerry-port.h> +#include "jerryscript-port.h" #include "file-utils.h" #include "comms-uart.h" diff --git a/src/jerry-port/zjs_jerry_port.c b/src/jerry-port/zjs_jerry_port.c new file mode 100644 index 0000000..1459c97 --- /dev/null +++ b/src/jerry-port/zjs_jerry_port.c @@ -0,0 +1,71 @@ +// Copyright (c) 2017, Intel Corporation. + +#include "jerryscript.h" +#include "jerryscript-port.h" + +#include <stdarg.h> + +// Stubbed out functions for jerry-port features + +bool jerry_port_get_time_zone(jerry_time_zone_t *tz_p) +{ + (void)(tz_p); + return false; +} + +double jerry_port_get_current_time(void) +{ + return 0; +} + +void jerry_port_fatal(jerry_fatal_code_t code) +{ + printf("[FATAL]: %u\n", code); +} + +void jerry_port_console(const char *fmat, ...) +{ + va_list va; + va_start(va, fmat); + vprintf(fmat, va); + va_end(va); +} + +void jerry_port_log(jerry_log_level_t level, const char *fmat, ...) +{ + (void)(level); + va_list va; + va_start(va, fmat); + vprintf(fmat, va); + va_end(va); +} + +#ifdef JERRY_PORT_ENABLE_JOBQUEUE +#include "../zjs_callbacks.h" +#include "../zjs_util.h" +// The job queue is essentially C callbacks, this is a simple wrapper + +typedef struct job_wrapper { + jerry_job_handler_t handler; + void *job; + zjs_callback_id id; +} job_wrapper_t; + +static void job_callback(void *h, const void *args) +{ + (void)(args); + job_wrapper_t *wrapper = (job_wrapper_t *)h; + wrapper->handler(wrapper->job); + zjs_remove_callback(wrapper->id); + zjs_free(wrapper); +} + +void jerry_port_jobqueue_enqueue(jerry_job_handler_t handler, void *job_p) +{ + job_wrapper_t *wrapper = zjs_malloc(sizeof(job_wrapper_t)); + wrapper->handler = handler; + wrapper->job = job_p; + wrapper->id = zjs_add_c_callback(wrapper, job_callback); + zjs_signal_callback(wrapper->id, NULL, 0); +} +#endif diff --git a/src/zjs_aio.c b/src/zjs_aio.c index b78148b..b3ab736 100644 --- a/src/zjs_aio.c +++ b/src/zjs_aio.c @@ -34,7 +34,7 @@ static aio_handle_t *zjs_aio_alloc_handle() return handle; } -static void zjs_aio_free_cb(uintptr_t ptr) +static void zjs_aio_free_cb(void *ptr) { aio_handle_t *handle = (aio_handle_t *)ptr; zjs_remove_callback(handle->callback_id); @@ -43,9 +43,14 @@ static void zjs_aio_free_cb(uintptr_t ptr) static void zjs_aio_free_callback(void *ptr, jerry_value_t rval) { - zjs_aio_free_cb((uintptr_t)ptr); + zjs_aio_free_cb(ptr); } +static const jerry_object_native_info_t aio_type_info = +{ + .free_cb = zjs_aio_free_cb +}; + static bool zjs_aio_ipm_send_async(uint32_t type, uint32_t pin, void *data) { zjs_ipm_message_t msg; msg.id = MSG_ID_AIO; @@ -180,12 +185,14 @@ static ZJS_DECL_FUNC(zjs_aio_pin_close) zjs_obj_get_uint32(this, "pin", &pin); aio_handle_t *handle; - if (jerry_get_object_native_handle(this, (uintptr_t *)&handle) && handle) { - // remove existing onchange handler and unsubscribe - zjs_aio_ipm_send_async(TYPE_AIO_PIN_UNSUBSCRIBE, pin, handle); - zjs_remove_callback(handle->callback_id); - jerry_set_object_native_handle(this, 0, NULL); - zjs_free(handle); + const jerry_object_native_info_t *tmp; + if (jerry_get_object_native_pointer(this, (void **)&handle, &tmp)) { + if (tmp == &aio_type_info) { + // remove existing onchange handler and unsubscribe + zjs_aio_ipm_send_async(TYPE_AIO_PIN_UNSUBSCRIBE, pin, handle); + zjs_remove_callback(handle->callback_id); + zjs_free(handle); + } } return ZJS_UNDEFINED; @@ -206,16 +213,18 @@ static ZJS_DECL_FUNC(zjs_aio_pin_on) return zjs_error("zjs_aio_pin_on: unsupported event type"); aio_handle_t *handle; - if (jerry_get_object_native_handle(this, (uintptr_t *)&handle) && handle) { - if (jerry_value_is_null(argv[1])) { - // no change function, remove if one existed before - zjs_aio_ipm_send_async(TYPE_AIO_PIN_UNSUBSCRIBE, pin, handle); - zjs_remove_callback(handle->callback_id); - jerry_set_object_native_handle(this, 0, NULL); - zjs_free(handle); - } else { - // switch to new change function - zjs_edit_js_func(handle->callback_id, argv[1]); + const jerry_object_native_info_t *tmp; + if (jerry_get_object_native_pointer(this, (void **)&handle, &tmp)) { + if (tmp == &aio_type_info) { + if (jerry_value_is_null(argv[1])) { + // no change function, remove if one existed before + zjs_aio_ipm_send_async(TYPE_AIO_PIN_UNSUBSCRIBE, pin, handle); + zjs_remove_callback(handle->callback_id); + zjs_free(handle); + } else { + // switch to new change function + zjs_edit_js_func(handle->callback_id, argv[1]); + } } } else if (!jerry_value_is_null(argv[1])) { // new change function @@ -223,8 +232,7 @@ static ZJS_DECL_FUNC(zjs_aio_pin_on) if (!handle) return zjs_error("zjs_aio_pin_on: could not allocate handle"); - jerry_set_object_native_handle(this, (uintptr_t)handle, - zjs_aio_free_cb); + jerry_set_object_native_pointer(this, (void *)handle, &aio_type_info); handle->callback_id = zjs_add_callback(argv[1], this, handle, NULL); zjs_aio_ipm_send_async(TYPE_AIO_PIN_SUBSCRIBE, pin, handle); } @@ -248,7 +256,7 @@ static ZJS_DECL_FUNC(zjs_aio_pin_read_async) handle->callback_id = zjs_add_callback(argv[0], this, handle, zjs_aio_free_callback); - jerry_set_object_native_handle(this, (uintptr_t)handle, zjs_aio_free_cb); + jerry_set_object_native_pointer(this, (void *)handle, &aio_type_info); // send IPM message to the ARC side; response will come on an ISR zjs_aio_ipm_send_async(TYPE_AIO_PIN_READ, pin, handle); diff --git a/src/zjs_ble.c b/src/zjs_ble.c index fc94127..a58417a 100644 --- a/src/zjs_ble.c +++ b/src/zjs_ble.c @@ -95,6 +95,15 @@ static ble_handle_t *ble_handle = NULL; static zjs_callback_id connected_cb_id = -1; static zjs_callback_id disconnected_cb_id = -1; +static void free_handle(void *native_p) +{ +} + +static const jerry_object_native_info_t ble_type_info = +{ + .free_cb = free_handle +}; + struct bt_uuid *zjs_ble_new_uuid_16(uint16_t value) { struct bt_uuid_16 *uuid = zjs_malloc(sizeof(struct bt_uuid_16)); if (!uuid) { @@ -225,19 +234,16 @@ static ZJS_DECL_FUNC(zjs_ble_read_callback_function) return zjs_error("zjs_ble_read_attr_call_function_return: invalid arguments"); } - uintptr_t ptr; - if (jerry_get_object_native_handle(function_obj, &ptr)) { - // store the return value in the read_cb struct - struct zjs_ble_characteristic *chrc = (struct zjs_ble_characteristic *)ptr; - chrc->read_cb.error_code = (uint32_t)jerry_get_number_value(argv[0]); + ZJS_GET_HANDLE(this, struct zjs_ble_characteristic, chrc, ble_type_info); - zjs_buffer_t *buf = zjs_buffer_find(argv[1]); - if (buf) { - chrc->read_cb.buffer = buf->buffer; - chrc->read_cb.buffer_size = buf->bufsize; - } else { - ERR_PRINT("buffer not found\n"); - } + chrc->read_cb.error_code = (uint32_t)jerry_get_number_value(argv[0]); + + zjs_buffer_t *buf = zjs_buffer_find(argv[1]); + if (buf) { + chrc->read_cb.buffer = buf->buffer; + chrc->read_cb.buffer_size = buf->bufsize; + } else { + ERR_PRINT("buffer not found\n"); } // unblock fiber @@ -254,7 +260,7 @@ static void zjs_ble_read_c_callback(void *handle, const void *argv) ZVAL callback = jerry_create_external_function(zjs_ble_read_callback_function); - jerry_set_object_native_handle(callback, (uintptr_t)handle, NULL); + jerry_set_object_native_pointer(callback, (void *)handle, &ble_type_info); jerry_value_t args[2] = {offset, callback}; ZVAL rval = jerry_call_function(cb->js_callback, chrc->chrc_obj, args, 2); @@ -326,12 +332,10 @@ static ZJS_DECL_FUNC(zjs_ble_write_callback_function) return zjs_error("zjs_ble_write_attr_call_function_return: invalid arguments"); } - uintptr_t ptr; - if (jerry_get_object_native_handle(function_obj, &ptr)) { - // store the return value in the write_cb struct - struct zjs_ble_characteristic *chrc = (struct zjs_ble_characteristic *)ptr; - chrc->write_cb.error_code = (uint32_t)jerry_get_number_value(argv[0]); - } + ZJS_GET_HANDLE(this, struct zjs_ble_characteristic, chrc, ble_type_info); + + // store the return value in the write_cb struct + chrc->write_cb.error_code = (uint32_t)jerry_get_number_value(argv[0]); // unblock fiber k_sem_give(&ble_sem); @@ -365,7 +369,7 @@ static void zjs_ble_write_c_callback(void *handle, const void *argv) ZVAL callback = jerry_create_external_function(zjs_ble_write_callback_function); - jerry_set_object_native_handle(callback, (uintptr_t)handle, NULL); + jerry_set_object_native_pointer(callback, (void *)handle, &ble_type_info); jerry_value_t args[4] = {buf_obj, offset, without_response, callback}; ZVAL rval = jerry_call_function(cb->js_callback, chrc->chrc_obj, args, 4); @@ -418,22 +422,19 @@ static ZJS_DECL_FUNC(zjs_ble_update_value_callback_function) // args: buffer ZJS_VALIDATE_ARGS(Z_BUFFER); - uintptr_t ptr; - if (jerry_get_object_native_handle(this, &ptr)) { - ble_characteristic_t *chrc = (ble_characteristic_t *)ptr; - if (chrc->chrc_attr) { - zjs_buffer_t *buf = zjs_buffer_find(argv[0]); - if (buf) { - // loop through all the connections - ble_connection_t *conn = ble_handle->connections; - while (conn) { - bt_gatt_notify(conn->bt_conn, chrc->chrc_attr, - buf->buffer, buf->bufsize); - conn = conn->next; - } - } else { - return zjs_error("buffer not found"); + ZJS_GET_HANDLE(this, struct zjs_ble_characteristic, chrc, ble_type_info); + + if (chrc->chrc_attr) { + zjs_buffer_t *buf = zjs_buffer_find(argv[0]); + if (buf) { + ble_connection_t *conn = ble_handle->connections; + while (conn) { + bt_gatt_notify(conn->bt_conn, chrc->chrc_attr, + buf->buffer, buf->bufsize); + conn = conn->next; } + } else { + return zjs_error("buffer not found"); } } @@ -1001,7 +1002,8 @@ static bool zjs_ble_parse_service(ble_service_t *service) // transfer ownership of v_chrc to chrc struct chrc->chrc_obj = jerry_acquire_value(v_chrc); - jerry_set_object_native_handle(chrc->chrc_obj, (uintptr_t)chrc, NULL); + jerry_set_object_native_pointer(chrc->chrc_obj, (void *)chrc, + &ble_type_info); // FIXME: All the stuff above this in the loop should move into // parse_characteristic and it should take chrc_obj instead; it would @@ -1206,8 +1208,8 @@ static ZJS_DECL_FUNC(zjs_ble_set_services) // transfer ownership of v_service to service struct service->service_obj = jerry_acquire_value(v_service); - jerry_set_object_native_handle(service->service_obj, - (uintptr_t)service, NULL); + jerry_set_object_native_pointer(service->service_obj, + (void *)service, &ble_type_info); // FIXME: The parse_service should take the service_obj instead and do // all this above stuff in the loop, reducing error handling cruft. diff --git a/src/zjs_buffer.c b/src/zjs_buffer.c index 45fe970..8413da8 100644 --- a/src/zjs_buffer.c +++ b/src/zjs_buffer.c @@ -13,6 +13,21 @@ static jerry_value_t zjs_buffer_prototype; +static void zjs_buffer_callback_free(void *handle) +{ + // requires: handle is the native pointer we registered with + // jerry_set_object_native_handle + // effects: frees the buffer item + zjs_buffer_t *item = (zjs_buffer_t *)handle; + zjs_free(item->buffer); + zjs_free(item); +} + +static const jerry_object_native_info_t buffer_type_info = +{ + .free_cb = zjs_buffer_callback_free +}; + bool zjs_value_is_buffer(const jerry_value_t value) { if (jerry_value_is_object(value) && zjs_buffer_find(value)) { @@ -29,8 +44,9 @@ zjs_buffer_t *zjs_buffer_find(const jerry_value_t obj) // effects: looks up obj in our list of known buffer objects and returns // the associated list item struct, or NULL if not found uintptr_t handle; - if (jerry_get_object_native_handle(obj, &handle)) { - if (jerry_get_prototype(obj) == zjs_buffer_prototype) { + const jerry_object_native_info_t *tmp; + if (jerry_get_object_native_pointer(obj, (void **)&handle, &tmp)) { + if (tmp == &buffer_type_info) { return (zjs_buffer_t *)handle; } } @@ -230,16 +246,6 @@ static ZJS_DECL_FUNC(zjs_buffer_to_string) return zjs_error("zjs_buffer_to_string: buffer is empty"); } -static void zjs_buffer_callback_free(uintptr_t handle) -{ - // requires: handle is the native pointer we registered with - // jerry_set_object_native_handle - // effects: frees the buffer item - zjs_buffer_t *item = (zjs_buffer_t *)handle; - zjs_free(item->buffer); - zjs_free(item); -} - static ZJS_DECL_FUNC(zjs_buffer_write_string) { // requires: string - what will be written to buf @@ -348,8 +354,7 @@ jerry_value_t zjs_buffer_create(uint32_t size, zjs_buffer_t **ret_buf) zjs_obj_add_readonly_number(buf_obj, size, "length"); // watch for the object getting garbage collected, and clean up - jerry_set_object_native_handle(buf_obj, (uintptr_t)buf_item, - zjs_buffer_callback_free); + jerry_set_object_native_pointer(buf_obj, (void *)buf_item, &buffer_type_info); if (ret_buf) { *ret_buf = buf_item; } diff --git a/src/zjs_callbacks.h b/src/zjs_callbacks.h index 4b6dec4..e204e0d 100644 --- a/src/zjs_callbacks.h +++ b/src/zjs_callbacks.h @@ -91,7 +91,7 @@ void zjs_remove_callback(zjs_callback_id id); /* * Remove all callbacks from memory */ -void zjs_remove_all_callbacks(); +void zjs_remove_all_callbacks(void); void signal_callback_priv(zjs_callback_id id, const void *args, diff --git a/src/zjs_dgram.c b/src/zjs_dgram.c index d6bc983..9d6a714 100644 --- a/src/zjs_dgram.c +++ b/src/zjs_dgram.c @@ -33,16 +33,6 @@ typedef struct dgram_handle { zjs_copy_jstring(jval, buf, &str_sz); \ } -#define GET_HANDLE(type, var) \ - type *var; \ - { \ - uintptr_t native; \ - if (!jerry_get_object_native_handle(this, &native)) { \ - return zjs_error("no native handle"); \ - } \ - var = (type *)native; \ - } - // Parse textual address of given address family (IPv4/IPv6) and numeric // port and fill in sockaddr. Returns ZJS_UNDEFINED if everything is OK, // or error instance otherwise. @@ -66,7 +56,7 @@ static jerry_value_t get_addr(sa_family_t family, return ZJS_UNDEFINED; } -static void zjs_dgram_free_cb(const uintptr_t native) +static void zjs_dgram_free_cb(void *native) { dgram_handle_t *handle = (dgram_handle_t *)native; DBG_PRINT("zjs_dgram_free_cb: %p\n", handle); @@ -85,6 +75,11 @@ static void zjs_dgram_free_cb(const uintptr_t native) zjs_free(handle); } +static const jerry_object_native_info_t dgram_type_info = +{ + .free_cb = zjs_dgram_free_cb +}; + // Copy data from Zephyr net_buf chain into linear buffer static char *net_buf_gather(struct net_buf *buf, char *to) { @@ -180,7 +175,7 @@ static ZJS_DECL_FUNC(zjs_dgram_createSocket) handle->message_cb_id = -1; handle->error_cb_id = -1; - jerry_set_object_native_handle(sockobj, (uintptr_t)handle, zjs_dgram_free_cb); + jerry_set_object_native_pointer(sockobj, (void *)handle, &dgram_type_info); // Can't call this here due to bug in Zephyr - called in .bind() instead //CHECK(net_context_recv(udp_sock, udp_received, K_NO_WAIT, handle)); @@ -193,7 +188,7 @@ static ZJS_DECL_FUNC(zjs_dgram_sock_on) // args: event name, callback ZJS_VALIDATE_ARGS(Z_STRING, Z_FUNCTION Z_NULL); - GET_HANDLE(dgram_handle_t, handle); + ZJS_GET_HANDLE(this, dgram_handle_t, handle, dgram_type_info); jerry_size_t str_sz = 32; char event[str_sz]; @@ -249,7 +244,7 @@ static ZJS_DECL_FUNC(zjs_dgram_sock_send) int ret; - GET_HANDLE(dgram_handle_t, handle); + ZJS_GET_HANDLE(this, dgram_handle_t, handle, dgram_type_info); zjs_buffer_t *buf = zjs_buffer_find(argv[0]); int offset = (int)jerry_get_number_value(argv[1]); @@ -293,7 +288,7 @@ static ZJS_DECL_FUNC(zjs_dgram_sock_bind) int ret; - GET_HANDLE(dgram_handle_t, handle); + ZJS_GET_HANDLE(this, dgram_handle_t, handle, dgram_type_info); sa_family_t family = net_context_get_family(handle->udp_sock); struct sockaddr sockaddr_buf; @@ -311,9 +306,9 @@ static ZJS_DECL_FUNC(zjs_dgram_sock_bind) static ZJS_DECL_FUNC(zjs_dgram_sock_close) { - GET_HANDLE(dgram_handle_t, handle); - zjs_dgram_free_cb((uintptr_t)handle); - jerry_set_object_native_handle(this, (uintptr_t)NULL, NULL); + ZJS_GET_HANDLE(this, dgram_handle_t, handle, dgram_type_info); + zjs_dgram_free_cb((void *)handle); + //jerry_set_object_native_handle(this, (uintptr_t)NULL, NULL); return ZJS_UNDEFINED; } diff --git a/src/zjs_fs.c b/src/zjs_fs.c index ef6eeb9..893dbee 100644 --- a/src/zjs_fs.c +++ b/src/zjs_fs.c @@ -49,6 +49,19 @@ typedef struct file_handle { static file_handle_t *opened_handles = NULL; +static void free_stats(void *native) +{ + struct zfs_dirent *entry = (struct zfs_dirent *)native; + if (entry) { + zjs_free(entry); + } +} + +static const jerry_object_native_info_t stats_type_info = +{ + .free_cb = free_stats +}; + static jerry_value_t invalid_args(void) { return zjs_error("invalid arguments"); @@ -120,11 +133,7 @@ static uint16_t get_mode(char *str) static ZJS_DECL_FUNC(is_file) { - struct fs_dirent *entry; - - if (!jerry_get_object_native_handle(this, (uintptr_t *)&entry)) { - return zjs_error("native handle not found"); - } + ZJS_GET_HANDLE(this, struct fs_dirent, entry, stats_type_info); if (entry->type == FS_DIR_ENTRY_FILE) { return jerry_create_boolean(true); } else { @@ -134,11 +143,7 @@ static ZJS_DECL_FUNC(is_file) static ZJS_DECL_FUNC(is_directory) { - struct fs_dirent *entry; - - if (!jerry_get_object_native_handle(this, (uintptr_t *)&entry)) { - return zjs_error("native handle not found"); - } + ZJS_GET_HANDLE(this, struct fs_dirent, entry, stats_type_info); if (entry->type == FS_DIR_ENTRY_DIR) { return jerry_create_boolean(true); } else { @@ -146,14 +151,6 @@ static ZJS_DECL_FUNC(is_directory) } } -static void free_stats(const uintptr_t native) -{ - struct zfs_dirent *entry = (struct zfs_dirent *)native; - if (entry) { - zjs_free(entry); - } -} - static jerry_value_t create_stats_obj(struct fs_dirent *entry) { @@ -165,7 +162,7 @@ static jerry_value_t create_stats_obj(struct fs_dirent *entry) } memcpy(new_entry, entry, sizeof(struct fs_dirent)); - jerry_set_object_native_handle(stats_obj, (uintptr_t)new_entry, free_stats); + jerry_set_object_native_pointer(stats_obj, (void *)new_entry, &stats_type_info); zjs_obj_add_function(stats_obj, is_file, "isFile"); zjs_obj_add_function(stats_obj, is_directory, "isDirectory"); diff --git a/src/zjs_gpio.c b/src/zjs_gpio.c index f3eb57d..20e6b2d 100644 --- a/src/zjs_gpio.c +++ b/src/zjs_gpio.c @@ -41,12 +41,35 @@ typedef struct gpio_handle { bool closed; } gpio_handle_t; -void gpio_internal_lookup_pin(const jerry_value_t pin_obj, DEVICE *port, - int *pin) +static void zjs_gpio_close(gpio_handle_t *handle) { - uintptr_t ptr; - if (jerry_get_object_native_handle(pin_obj, &ptr)) { - gpio_handle_t *handle = (gpio_handle_t *)ptr; + zjs_remove_callback(handle->callbackId); + gpio_remove_callback(handle->port, &handle->callback); + handle->closed = true; +} + +static void zjs_gpio_free_cb(void *native) +{ + gpio_handle_t *handle = (gpio_handle_t *)native; + if (!handle->closed) + zjs_gpio_close(handle); + + zjs_free(handle); +} + +static const jerry_object_native_info_t gpio_type_info = +{ + .free_cb = zjs_gpio_free_cb +}; + +// non-static so that mock can access it, meant to be private though +void gpio_internal_lookup_pin(const jerry_value_t pin_obj, + DEVICE *port, int *pin) +{ + gpio_handle_t *handle; + jerry_object_native_info_t *tmp; + jerry_get_object_native_pointer(pin_obj, &handle, &tmp); + if (tmp == &gpio_type_info) { *port = handle->port; *pin = handle->pin; } @@ -98,13 +121,8 @@ static ZJS_DECL_FUNC(zjs_gpio_pin_read) { // requires: this is a GPIOPin object from zjs_gpio_open, takes no args // effects: reads a logical value from the pin and returns it in ret_val_p - uintptr_t ptr; - gpio_handle_t *handle; - if (!jerry_get_object_native_handle(this, &ptr)) { - return SYSTEM_ERROR("no handle found"); - } + ZJS_GET_HANDLE(this, gpio_handle_t, handle, gpio_type_info); - handle = (gpio_handle_t *)ptr; if (handle->closed) { return zjs_error("pin closed"); } @@ -132,13 +150,9 @@ static ZJS_DECL_FUNC(zjs_gpio_pin_write) // args: pin value ZJS_VALIDATE_ARGS(Z_BOOL Z_NUMBER); - uintptr_t ptr; - if (!jerry_get_object_native_handle(this, &ptr)) { - return SYSTEM_ERROR("no handle found"); - } - gpio_handle_t *handle = (gpio_handle_t *)ptr; + ZJS_GET_HANDLE(this, gpio_handle_t, handle, gpio_type_info); if (handle->closed) { - return zjs_error("pin closed"); + return zjs_error("zjs_gpio_pin_write: pin closed"); } uint32_t value; @@ -164,35 +178,14 @@ static ZJS_DECL_FUNC(zjs_gpio_pin_write) return ZJS_UNDEFINED; } -static void zjs_gpio_close(gpio_handle_t *handle) -{ - zjs_remove_callback(handle->callbackId); - gpio_remove_callback(handle->port, &handle->callback); - handle->closed = true; -} - static ZJS_DECL_FUNC(zjs_gpio_pin_close) { - uintptr_t ptr; - if (jerry_get_object_native_handle(this, &ptr)) { - gpio_handle_t *handle = (gpio_handle_t *)ptr; - if (handle->closed) - return zjs_error("zjs_gpio_pin_close: already closed"); + ZJS_GET_HANDLE(this, gpio_handle_t, handle, gpio_type_info); + if (handle->closed) + return zjs_error("zjs_gpio_pin_close: already closed"); - zjs_gpio_close(handle); - return ZJS_UNDEFINED; - } - - return zjs_error("zjs_gpio_pin_close: no native handle"); -} - -static void zjs_gpio_free_cb(const uintptr_t native) -{ - gpio_handle_t *handle = (gpio_handle_t *)native; - if (!handle->closed) - zjs_gpio_close(handle); - - zjs_free(handle); + zjs_gpio_close(handle); + return ZJS_UNDEFINED; } enum { @@ -316,8 +309,8 @@ static ZJS_DECL_FUNC(zjs_gpio_open) handle->callbackId = -1; handle->active_low = active_low; - jerry_set_object_native_handle(pin_obj, (uintptr_t)handle, - zjs_gpio_free_cb); + // Set the native handle so we can free it when close() is called + jerry_set_object_native_pointer(pin_obj, (void *)handle, &gpio_type_info); if (dir == ZJS_DIR_INPUT) { // Zephyr ISR callback init diff --git a/src/zjs_gpio_mock.c b/src/zjs_gpio_mock.c index 93caea4..a0b0582 100644 --- a/src/zjs_gpio_mock.c +++ b/src/zjs_gpio_mock.c @@ -11,6 +11,16 @@ // mock headers should be included last #include "zjs_gpio_mock.h" +static void free_handle(void *native) +{ +} + +static const jerry_object_native_info_t mock_type_info = +{ + .free_cb = free_handle +}; + + // specially declare this internal gpio function jerry_value_t gpio_internal_lookup_pin(const jerry_value_t pin_obj, DEVICE *port, int *pin); @@ -264,13 +274,11 @@ int mock_gpio_pin_write(DEVICE port, uint32_t pin, uint32_t value) && !new_level)) { // simulate onchange interrupt - uintptr_t ptr; - if (jerry_get_object_native_handle(connection, &ptr)) { - mock_cb_item_t *item = (mock_cb_item_t *)ptr; - if (BIT(conn_pin) & item->enabled_mask) { - item->handler(port, item->callback, - item->enabled_mask); - } + ZJS_GET_HANDLE(connection, mock_cb_item_t, item, mock_type_info); + + if (BIT(conn_pin) & item->enabled_mask) { + item->handler(port, item->callback, + item->enabled_mask); } } } @@ -370,7 +378,9 @@ int mock_gpio_pin_enable_callback(DEVICE port, uint32_t pin) uint32_t bit = BIT(pin); if (bit & item->pin_mask) { item->enabled_mask |= bit; - jerry_set_object_native_handle(pin_obj, (uintptr_t)item, NULL); + jerry_set_object_native_pointer(pin_obj, + (void *)item, + &mock_type_info); // FIXME: maybe need to clean up on re-open w/o close break; } diff --git a/src/zjs_net.c b/src/zjs_net.c index f07c718..6e63d2c 100644 --- a/src/zjs_net.c +++ b/src/zjs_net.c @@ -127,6 +127,20 @@ typedef struct sock_handle { static sock_handle_t *opened_sockets = NULL; +static void free_handle(void *native_p) +{ +} + +static const jerry_object_native_info_t socket_type_info = +{ + .free_cb = free_handle +}; + +static const jerry_object_native_info_t net_type_info = +{ + .free_cb = free_handle +}; + #define CHECK(x) \ ret = (x); if (ret < 0) { ERR_PRINT("Error in " #x ": %d\n", ret); return zjs_error(#x); } @@ -328,12 +342,8 @@ static jerry_value_t socket_write(const jerry_value_t function_obj, { ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_OBJECT, Z_OPTIONAL Z_FUNCTION); - sock_handle_t *handle = NULL; + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } start_socket_timeout(handle, handle->timeout); zjs_buffer_t *buf = zjs_buffer_find(argv[0]); @@ -388,11 +398,7 @@ static jerry_value_t socket_pause(const jerry_value_t function_obj, const jerry_value_t argv[], const jerry_length_t argc) { - sock_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); handle->paused = 1; return ZJS_UNDEFINED; } @@ -409,11 +415,7 @@ static jerry_value_t socket_resume(const jerry_value_t function_obj, const jerry_value_t argv[], const jerry_length_t argc) { - sock_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); handle->paused = 0; return ZJS_UNDEFINED; } @@ -430,11 +432,7 @@ static jerry_value_t socket_address(const jerry_value_t function_obj, const jerry_value_t argv[], const jerry_length_t argc) { - sock_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); jerry_value_t ret = jerry_create_object(); ZVAL port = zjs_get_property(this, "localPort"); ZVAL addr = zjs_get_property(this, "localAddress"); @@ -470,11 +468,7 @@ static jerry_value_t socket_set_timeout(const jerry_value_t function_obj, { ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_NUMBER, Z_OPTIONAL Z_FUNCTION); - sock_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); uint32_t time = (uint32_t)jerry_get_number_value(argv[0]); @@ -512,7 +506,7 @@ static jerry_value_t create_socket(uint8_t client, sock_handle_t **handle_out) zjs_obj_add_function(socket, socket_connect, "connect"); } - jerry_set_object_native_handle(socket, (uintptr_t)sock_handle, NULL); + jerry_set_object_native_pointer(socket, (uintptr_t)sock_handle, &socket_type_info); sock_handle->connect_listener = ZJS_UNDEFINED; sock_handle->socket = socket; sock_handle->tcp_connect_id = -1; @@ -538,11 +532,15 @@ static void add_socket_connection(jerry_value_t socket, struct sockaddr *remote) { sock_handle_t *handle = NULL; - jerry_get_object_native_handle(socket, (uintptr_t *)&handle); - if (!handle) { + const jerry_object_native_info_t *tmp; + if (!jerry_get_object_native_pointer(socket, (uintptr_t *)&handle, &tmp)) { ERR_PRINT("could not get socket handle\n"); return; } + if (tmp != &socket_type_info) { + ERR_PRINT("handle was incorrect type"); + return; + } memcpy(&handle->remote, remote, sizeof(struct sockaddr)); handle->handle = net; @@ -622,11 +620,8 @@ static jerry_value_t server_close(const jerry_value_t function_obj, { ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_OPTIONAL Z_FUNCTION); - net_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("server handle not found"); - } + ZJS_GET_HANDLE(this, net_handle_t, handle, net_type_info); + handle->listening = 0; zjs_obj_add_boolean(this, false, "listening"); @@ -656,11 +651,7 @@ static jerry_value_t server_get_connections(const jerry_value_t function_obj, ZJS_VALIDATE_ARGS(Z_FUNCTION); int count = 0; - net_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("server handle not found"); - } + ZJS_GET_HANDLE(this, net_handle_t, handle, net_type_info); sock_handle_t *cur = opened_sockets; while (cur) { @@ -696,6 +687,8 @@ static jerry_value_t server_listen(const jerry_value_t function_obj, // options object, optional function ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_OBJECT, Z_OPTIONAL Z_FUNCTION); + ZJS_GET_HANDLE(this, net_handle_t, handle, net_type_info); + int ret; double port = 0; double backlog = 0; @@ -710,13 +703,6 @@ static jerry_value_t server_listen(const jerry_value_t function_obj, zjs_add_event_listener(this, "listening", argv[1]); } - net_handle_t *handle = NULL; - - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("server handle not found"); - } - struct sockaddr_in6 my_addr6 = { 0 }; my_addr6.sin6_family = AF_INET6; @@ -783,7 +769,7 @@ static jerry_value_t net_create_server(const jerry_value_t function_obj, CHECK(net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &handle->tcp_sock)) - jerry_set_object_native_handle(server, (uintptr_t)handle, NULL); + jerry_set_object_native_pointer(server, (uintptr_t)handle, &net_type_info); handle->server = server; handle->listening = 0; @@ -848,11 +834,7 @@ static jerry_value_t socket_connect(const jerry_value_t function_obj, ZJS_VALIDATE_ARGS(Z_OBJECT, Z_OPTIONAL Z_FUNCTION); int ret; - sock_handle_t *handle = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&handle); - if (!handle) { - return zjs_error("socket handle not found"); - } + ZJS_GET_HANDLE(this, sock_handle_t, handle, socket_type_info); if (!handle->tcp_sock) { CHECK(net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &handle->tcp_sock)); diff --git a/src/zjs_ocf_client.c b/src/zjs_ocf_client.c index 283ffb3..574b4f4 100644 --- a/src/zjs_ocf_client.c +++ b/src/zjs_ocf_client.c @@ -18,7 +18,6 @@ #include "zjs_ocf_encoder.h" #include "zjs_event.h" -#include "zjs_promise.h" //#define USE_PROMISES @@ -274,7 +273,7 @@ static jerry_value_t create_resource(struct client_resource *client) return resource; } -static void free_client(const uintptr_t native_p) +static void free_client(void *native_p) { struct client_resource *client = (struct client_resource *)native_p; if (client) { @@ -301,6 +300,11 @@ static void free_client(const uintptr_t native_p) } } +static const jerry_object_native_info_t ocf_type_info = +{ + .free_cb = free_client +}; + /* * Add a discovered resource to the list of resource_list */ @@ -329,7 +333,7 @@ static void add_resource(char *id, char *type, char *path, jerry_value_t client, new->client = client; - jerry_set_object_native_handle(client, (uintptr_t)new, free_client); + jerry_set_object_native_pointer(client, (void *)new, &ocf_type_info); if (!jerry_value_is_undefined(listener)) { zjs_add_event_listener(new->client, "resourcefound", listener); @@ -339,14 +343,6 @@ static void add_resource(char *id, char *type, char *path, jerry_value_t client, resource_list = new; } -static void post_ocf_promise(void *handle) -{ - struct ocf_handler *h = (struct ocf_handler *)handle; - if (h) { - zjs_free(h); - } -} - /* * Callback to observe, does not do anything currently */ @@ -485,7 +481,7 @@ Found: ZVAL res = create_resource(cur); zjs_trigger_event(cur->client, "resourcefound", &res, 1, NULL, NULL); - zjs_fulfill_promise(h->promise_obj, &res, 1); + jerry_resolve_or_reject_promise(h->promise_obj, res, true); DBG_PRINT("resource found, id=%s, path=%s\n", cur->device_id, cur->resource_path); @@ -508,7 +504,6 @@ static jerry_value_t ocf_find_resources(const jerry_value_t function_val, char *device_id = NULL; char *resource_path = NULL; jerry_value_t listener = ZJS_UNDEFINED; - jerry_value_t promise = jerry_create_object(); if (argc > 0 && !jerry_value_is_function(argv[0])) { // has options parameter @@ -554,11 +549,10 @@ static jerry_value_t ocf_find_resources(const jerry_value_t function_val, zjs_free(resource_path); } + jerry_value_t promise = jerry_create_promise(); struct ocf_handler *h = new_ocf_handler(NULL); h->promise_obj = promise; - zjs_make_promise(promise, post_ocf_promise, h); - oc_do_ip_discovery(resource_type, discovery, h); if (resource_type) { @@ -581,7 +575,7 @@ static void ocf_get_handler(oc_client_response_t *data) zjs_set_property(resource_val, "properties", properties_val); zjs_trigger_event(resource->client, "update", &resource_val, 1, NULL, NULL); - zjs_fulfill_promise(h->promise_obj, &resource_val, 1); + jerry_resolve_or_reject_promise(h->promise_obj, resource_val, true); DBG_PRINT("GET response OK, device_id=%s\n", resource->device_id); @@ -592,7 +586,7 @@ static void ocf_get_handler(oc_client_response_t *data) */ ZVAL err = make_ocf_error("NetworkError", "Error code from GET", resource); - zjs_reject_promise(h->promise_obj, &err, 1); + jerry_resolve_or_reject_promise(h->promise_obj, err, false); ERR_PRINT("GET response code %d\n", data->code); } @@ -600,7 +594,7 @@ static void ocf_get_handler(oc_client_response_t *data) } } -static jerry_value_t ocf_retrieve(const jerry_value_t function_val, +static jerry_value_t ocf_retrieve(const jerry_value_t function_obj, const jerry_value_t this, const jerry_value_t argv[], const jerry_length_t argc) @@ -610,7 +604,6 @@ static jerry_value_t ocf_retrieve(const jerry_value_t function_val, jerry_value_t options = 0; jerry_value_t listener = 0; - jerry_value_t promise = jerry_create_object(); struct ocf_handler *h; ZJS_GET_STRING(argv[0], device_id, OCF_MAX_DEVICE_ID_LEN + 1); @@ -618,8 +611,7 @@ static jerry_value_t ocf_retrieve(const jerry_value_t function_val, struct client_resource *resource = find_resource_by_id(device_id); if (!resource) { ERR_PRINT("could not find resource %s\n", device_id); - REJECT(promise, "NotFoundError", "resource was not found", h); - return promise; + REJECT("NotFoundError", "resource was not found"); } if (argc > 1) { @@ -680,12 +672,11 @@ static jerry_value_t ocf_retrieve(const jerry_value_t function_val, DBG_PRINT("resource found in lookup: path=%s, id=%s\n", resource->resource_path, resource->device_id); + jerry_value_t promise = jerry_create_promise(); h = new_ocf_handler(resource); h->res = resource; h->promise_obj = promise; - zjs_make_promise(promise, post_ocf_promise, h); - if (!oc_do_get(resource->resource_path, &resource->server, NULL, @@ -694,7 +685,7 @@ static jerry_value_t ocf_retrieve(const jerry_value_t function_val, h)) { ZVAL err = make_ocf_error("NetworkError", "GET call failed", resource); - zjs_reject_promise(promise, &err, 1); + jerry_resolve_or_reject_promise(promise, err, false); } return promise; @@ -711,12 +702,12 @@ static void put_finished(oc_client_response_t *data) DBG_PRINT("PUT response OK, device_id=%s\n", resource->device_id); ZVAL resource_val = create_resource(resource); - zjs_fulfill_promise(h->promise_obj, &resource_val, 1); + jerry_resolve_or_reject_promise(h->promise_obj, resource_val, true); } else { ERR_PRINT("PUT response code %d\n", data->code); ZVAL err = make_ocf_error("NetworkError", "PUT response error code", resource); - zjs_reject_promise(h->promise_obj, &err, 1); + jerry_resolve_or_reject_promise(h->promise_obj, err, false); } } } @@ -730,7 +721,6 @@ static jerry_value_t ocf_update(const jerry_value_t function_val, // args: resource object ZJS_VALIDATE_ARGS(Z_OBJECT); - jerry_value_t promise = jerry_create_object(); struct ocf_handler *h; // Get device ID property from resource @@ -740,14 +730,13 @@ static jerry_value_t ocf_update(const jerry_value_t function_val, struct client_resource *resource = find_resource_by_id(device_id); if (!resource) { ERR_PRINT("could not find resource %s\n", device_id); - REJECT(promise, "NotFoundError", "resource was not found", h); - return promise; + REJECT("NotFoundError", "resource was not found"); } DBG_PRINT("update resource '%s'\n", resource->device_id); + jerry_value_t promise = jerry_create_promise(); h = new_ocf_handler(resource); - zjs_make_promise(promise, post_ocf_promise, h); h->res = resource; h->promise_obj = promise; @@ -770,12 +759,12 @@ static jerry_value_t ocf_update(const jerry_value_t function_val, ERR_PRINT("error sending PUT request\n"); ZVAL err = make_ocf_error("NetworkError", "PUT call failed", resource); - zjs_reject_promise(promise, &err, 1); + jerry_resolve_or_reject_promise(promise, err, false); } } else { ERR_PRINT("error initializing PUT\n"); ZVAL err = make_ocf_error("NetworkError", "PUT init failed", resource); - zjs_reject_promise(promise, &err, 1); + jerry_resolve_or_reject_promise(promise, err, false); } return promise; @@ -827,7 +816,7 @@ static jerry_value_t ocf_delete(const jerry_value_t function_val, } h = new_ocf_handler(resource); - zjs_make_promise(promise, post_ocf_promise, h); + jerry_create_promise(promise, post_ocf_promise, h); h->promise_obj = promise; if (!oc_do_delete(uri, &resource->server, delete_finished, LOW_QOS, h)) { @@ -918,7 +907,7 @@ static void ocf_get_platform_info_handler(oc_client_response_t *data) } zjs_trigger_event(resource->client, "platformfound", &platform_info, 1, NULL, NULL); - zjs_fulfill_promise(h->promise_obj, &platform_info, 1); + jerry_resolve_or_reject_promise(h->promise_obj, platform_info, true); } } @@ -930,19 +919,17 @@ static jerry_value_t ocf_get_platform_info(const jerry_value_t function_val, // args: device ide ZJS_VALIDATE_ARGS(Z_STRING); struct ocf_handler *h; - jerry_value_t promise = jerry_create_object(); ZJS_GET_STRING(argv[0], device_id, OCF_MAX_DEVICE_ID_LEN + 1); struct client_resource *resource = find_resource_by_id(device_id); if (!resource) { ERR_PRINT("resource was not found: %s\n", device_id); - REJECT(promise, "NotFoundError", "resource was not found", h); - return promise; + REJECT("NotFoundError", "resource was not found"); } + jerry_value_t promise = jerry_create_promise(); h = new_ocf_handler(resource); - zjs_make_promise(promise, post_ocf_promise, h); h->promise_obj = promise; DBG_PRINT("sending GET to /oic/p\n"); @@ -954,7 +941,7 @@ static jerry_value_t ocf_get_platform_info(const jerry_value_t function_val, LOW_QOS, h)) { jerry_value_t err = make_ocf_error("NetworkError", "GET call failed", resource); - zjs_reject_promise(promise, &err, 1); + jerry_resolve_or_reject_promise(promise, err, false); } return promise; @@ -1017,7 +1004,7 @@ static void ocf_get_device_info_handler(oc_client_response_t *data) } zjs_trigger_event(resource->client, "devicefound", &device_info, 1, NULL, NULL); - zjs_fulfill_promise(h->promise_obj, &device_info, 1); + jerry_resolve_or_reject_promise(h->promise_obj, device_info, true); } } @@ -1030,19 +1017,17 @@ static jerry_value_t ocf_get_device_info(const jerry_value_t function_val, ZJS_VALIDATE_ARGS(Z_STRING); struct ocf_handler *h; - jerry_value_t promise = jerry_create_object(); ZJS_GET_STRING(argv[0], device_id, OCF_MAX_DEVICE_ID_LEN + 1); struct client_resource *resource = find_resource_by_id(device_id); if (!resource) { ERR_PRINT("resource was not found: %s\n", device_id); - REJECT(promise, "NotFoundError", "resource was not found", h); - return promise; + REJECT("NotFoundError", "resource was not found"); } + jerry_value_t promise = jerry_create_promise(); h = new_ocf_handler(resource); - zjs_make_promise(promise, post_ocf_promise, h); h->promise_obj = promise; DBG_PRINT("sending GET to /oic/d\n"); @@ -1053,8 +1038,8 @@ static jerry_value_t ocf_get_device_info(const jerry_value_t function_val, &ocf_get_device_info_handler, LOW_QOS, h)) { - jerry_value_t err = make_ocf_error("NetworkError", "GET call failed", resource); - zjs_reject_promise(promise, &err, 1); + ZVAL err = make_ocf_error("NetworkError", "GET call failed", resource); + jerry_resolve_or_reject_promise(promise, err, false); } return promise; @@ -1097,8 +1082,6 @@ jerry_value_t zjs_ocf_client_init() { jerry_value_t ocf_client = jerry_create_object(); - zjs_make_event(ocf_client, ZJS_UNDEFINED); - zjs_obj_add_function(ocf_client, ocf_find_resources, "findResources"); zjs_obj_add_function(ocf_client, ocf_retrieve, "retrieve"); zjs_obj_add_function(ocf_client, ocf_update, "update"); @@ -1111,6 +1094,8 @@ jerry_value_t zjs_ocf_client_init() zjs_obj_add_function(ocf_client, ocf_find_platforms, "findPlatforms"); #endif + zjs_make_event(ocf_client, ZJS_UNDEFINED); + return ocf_client; } diff --git a/src/zjs_ocf_common.h b/src/zjs_ocf_common.h index 9e3abe0..5c63774 100644 --- a/src/zjs_ocf_common.h +++ b/src/zjs_ocf_common.h @@ -35,12 +35,11 @@ struct props_handle { char name[name##_size]; \ zjs_copy_jstring(jval, name, &name##_size); -#define REJECT(promise, err_name, err_msg, handler) \ - handler = new_ocf_handler(NULL); \ - zjs_make_promise(promise, post_ocf_promise, handler); \ - jerry_value_t error = make_ocf_error(err_name, err_msg, NULL); \ - zjs_reject_promise(promise, &error, 1); \ - jerry_release_value(error); +#define REJECT(err_name, err_msg) \ + jerry_value_t promise = jerry_create_promise(); \ + ZVAL error = make_ocf_error(err_name, err_msg, NULL); \ + jerry_resolve_or_reject_promise(promise, error, false); \ + return promise; /* * Test if value at index is a double or integer diff --git a/src/zjs_ocf_server.c b/src/zjs_ocf_server.c index 87130e8..ec7201d 100644 --- a/src/zjs_ocf_server.c +++ b/src/zjs_ocf_server.c @@ -15,7 +15,6 @@ #include "zjs_ocf_common.h" #include "zjs_event.h" -#include "zjs_promise.h" struct server_resource { /* @@ -52,6 +51,15 @@ struct ocf_handler { struct server_resource *res; }; +static void free_handle(void *native_p) +{ +} + +static const jerry_object_native_info_t ocf_type_info = +{ + .free_cb = free_handle +}; + static resource_list_t *res_list = NULL; #define FLAG_OBSERVE 1 << 0 @@ -72,17 +80,6 @@ static struct ocf_handler *new_ocf_handler(struct server_resource *res) return h; } -static void post_ocf_promise(void *handle) -{ - struct ocf_handler *h = (struct ocf_handler *)handle; - if (h) { - if (h->resp) { - zjs_free(h->resp); - } - zjs_free(h); - } -} - static jerry_value_t make_ocf_error(const char *name, const char *msg, struct server_resource *res) { @@ -237,18 +234,9 @@ static jerry_value_t ocf_respond(const jerry_value_t function_val, // args: properties object ZJS_VALIDATE_ARGS(Z_OBJECT); - jerry_value_t promise = jerry_create_object(); - struct ocf_handler *h; - jerry_value_t request = this; - jerry_value_t data = argv[0]; - if (!jerry_get_object_native_handle(request, (uintptr_t *)&h)) { - ERR_PRINT("native handle not found\n"); - REJECT(promise, "TypeMismatchError", "native handle not found", h); - oc_send_response(h->req, OC_STATUS_INTERNAL_SERVER_ERROR); - return promise; - } + ZJS_GET_HANDLE(this, struct ocf_handler, h, ocf_type_info); void *ret; // Start the root encoding object @@ -271,9 +259,9 @@ static jerry_value_t ocf_respond(const jerry_value_t function_val, } DBG_PRINT("responding to method type=%u, properties=%lu\n", h->resp->method, data); - zjs_make_promise(promise, NULL, NULL); + jerry_value_t promise = jerry_create_promise(); - zjs_fulfill_promise(promise, NULL, 0); + jerry_resolve_or_reject_promise(promise, ZJS_UNDEFINED, true); return promise; } @@ -303,7 +291,7 @@ static jerry_value_t create_request(struct server_resource *resource, zjs_obj_add_function(object, ocf_respond, "respond"); - jerry_set_object_native_handle(object, (uintptr_t)handler, NULL); + jerry_set_object_native_pointer(object, (void *)handler, &ocf_type_info); return object; } @@ -400,11 +388,8 @@ static jerry_value_t ocf_notify(const jerry_value_t function_val, // args: resource object ZJS_VALIDATE_ARGS(Z_OBJECT); - struct server_resource *resource; - if (!jerry_get_object_native_handle(argv[0], (uintptr_t *)&resource)) { - DBG_PRINT("native handle not found\n"); - return ZJS_UNDEFINED; - } + ZJS_GET_HANDLE(this, struct server_resource, resource, ocf_type_info); + DBG_PRINT("path=%s\n", resource->resource_path); oc_notify_observers(resource->res); @@ -422,24 +407,19 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, struct server_resource *resource; int i; - jerry_value_t promise = jerry_create_object(); - struct ocf_handler *h = NULL; // Required ZVAL resource_path_val = zjs_get_property(argv[0], "resourcePath"); if (!jerry_value_is_string(resource_path_val)) { ERR_PRINT("resourcePath not found\n"); - REJECT(promise, "TypeMismatchError", "resourcePath not found", h); - return promise; + REJECT("TypeMismatchError", "resourcePath not found"); } ZJS_GET_STRING(resource_path_val, resource_path, OCF_MAX_RES_PATH_LEN); ZVAL res_type_array = zjs_get_property(argv[0], "resourceTypes"); if (!jerry_value_is_array(res_type_array)) { ERR_PRINT("resourceTypes array not found\n"); - REJECT(promise, "TypeMismatchError", "resourceTypes array not found", - h); - return promise; + REJECT("TypeMismatchError", "resourceTypes array not found"); } // Optional @@ -474,13 +454,11 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, resource_list_t *new = zjs_malloc(sizeof(resource_list_t)); if (!new) { - REJECT(promise, "InternalError", "Could not allocate resource list", h); - return promise; + REJECT("InternalError", "Could not allocate resource list"); } resource = new_server_resource(resource_path); if (!resource) { - REJECT(promise, "InternalError", "Could not allocate resource", h); - return promise; + REJECT("InternalError", "Could not allocate resource"); } new->resource = resource; new->next = res_list; @@ -491,8 +469,7 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, resource->num_types = jerry_get_array_length(res_type_array); resource->resource_types = zjs_malloc(sizeof(char *) * resource->num_types); if (!resource->resource_types) { - REJECT(promise, "InternalError", "resourceType alloc failed", h); - return promise; + REJECT("InternalError", "resourceType alloc failed"); } for (i = 0; i < resource->num_types; ++i) { @@ -500,24 +477,20 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, uint32_t size = OCF_MAX_RES_TYPE_LEN; resource->resource_types[i] = zjs_alloc_from_jstring(type_val, &size); if (!resource->resource_types[i]) { - REJECT(promise, "InternalError", "resourceType alloc failed", h); - return promise; + REJECT("InternalError", "resourceType alloc failed"); } } ZVAL iface_array = zjs_get_property(argv[0], "interfaces"); if (!jerry_value_is_array(iface_array)) { ERR_PRINT("interfaces array not found\n"); - REJECT(promise, "TypeMismatchError", "resourceTypes array not found", - h); - return promise; + REJECT("TypeMismatchError", "resourceTypes array not found"); } resource->num_ifaces = jerry_get_array_length(iface_array); resource->resource_ifaces = zjs_malloc(sizeof(char *) * resource->num_ifaces); if (!resource->resource_ifaces) { - REJECT(promise, "InternalError", "interfaces alloc failed", h); - return promise; + REJECT("InternalError", "interfaces alloc failed"); } for (i = 0; i < resource->num_ifaces; ++i) { @@ -525,18 +498,20 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, uint32_t size = OCF_MAX_RES_TYPE_LEN; resource->resource_ifaces[i] = zjs_alloc_from_jstring(val, &size); if (!resource->resource_ifaces[i]) { - REJECT(promise, "InternalError", "resourceType alloc failed", h); - return promise; + REJECT("InternalError", "resourceType alloc failed"); } } - h = new_ocf_handler(resource); - zjs_make_promise(promise, post_ocf_promise, h); - /* - * Find lifetime of resource, free in post promise - */ + // Get UUID and set it in the ocf.device object + oc_uuid_t *id = oc_core_get_device_id(resource->res->device); + char uuid[37]; + oc_uuid_to_str(id, uuid, 37); + zjs_set_uuid(uuid); + jerry_value_t res = create_resource(resource_path, argv[0]); - zjs_fulfill_promise(promise, &res, 1); + + jerry_value_t promise = jerry_create_promise(); + jerry_resolve_or_reject_promise(promise, res, true); /* * TODO: Add native handle to ensure it gets freed, @@ -544,7 +519,7 @@ static jerry_value_t ocf_register(const jerry_value_t function_val, */ resource->object = this; - jerry_set_object_native_handle(res, (uintptr_t)resource, NULL); + jerry_set_object_native_pointer(res, (void *)resource, &ocf_type_info); DBG_PRINT("registered resource, path=%s\n", resource_path); diff --git a/src/zjs_promise.c b/src/zjs_promise.c deleted file mode 100644 index 251bdab..0000000 --- a/src/zjs_promise.c +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2016-2017, Intel Corporation. - -#include <string.h> -#include "zjs_util.h" -#include "zjs_common.h" -#include "zjs_promise.h" -#include "zjs_callbacks.h" - -typedef struct zjs_promise { - zjs_callback_id then_id; // Callback ID for then JS callback - zjs_callback_id catch_id; // Callback ID for catch JS callback - void *user_handle; - zjs_post_promise_func post; -} zjs_promise_t; - -zjs_promise_t *new_promise(void) -{ - zjs_promise_t *new = zjs_malloc(sizeof(zjs_promise_t)); - memset(new, 0, sizeof(zjs_promise_t)); - new->catch_id = -1; - new->then_id = -1; - return new; -} - -static void post_promise(void *h, jerry_value_t ret_val) -{ - zjs_promise_t *handle = (zjs_promise_t *)h; - if (handle) { - if (handle->post) { - handle->post(handle->user_handle); - } - zjs_free(handle); - } -} - -static ZJS_DECL_FUNC_ARGS(promise_resolve, uint8_t fulfill) -{ - // args: callback - ZJS_VALIDATE_ARGS(Z_FUNCTION); - - zjs_promise_t *handle = NULL; - ZVAL promise_obj = zjs_get_property(this, "promise"); - jerry_get_object_native_handle(promise_obj, (uintptr_t *)&handle); - - if (!handle) { - return zjs_error("promise handle not found"); - } - // we don't need to check the return of edit because either fulfill or - // reject will have removed then_id or catch_id callback - if (fulfill) { - zjs_edit_js_func(handle->then_id, argv[0]); - } else { - zjs_edit_js_func(handle->catch_id, argv[0]); - } - - return jerry_acquire_value(this); -} - -static ZJS_DECL_FUNC(promise_then) -{ - return ZJS_CHAIN_FUNC_ARGS(promise_resolve, 1); -} - -static ZJS_DECL_FUNC(promise_catch) -{ - return ZJS_CHAIN_FUNC_ARGS(promise_resolve, 0); -} - -void zjs_make_promise(jerry_value_t obj, zjs_post_promise_func post, - void *handle) -{ - zjs_promise_t *new = new_promise(); - if (!new) { - ERR_PRINT("could not allocate new promise\n"); - return; - } - - zjs_obj_add_function(obj, promise_then, "then"); - zjs_obj_add_function(obj, promise_catch, "catch"); - - ZVAL promise_obj = jerry_create_object(); - jerry_set_object_native_handle(promise_obj, (uintptr_t)new, NULL); - - new->user_handle = handle; - new->post = post; - - new->then_id = zjs_add_callback_once(ZJS_UNDEFINED, - obj, - new, - post_promise); - - new->catch_id = zjs_add_callback_once(ZJS_UNDEFINED, - obj, - new, - post_promise); - - // Add the "promise" object to the object passed as a property, because the - // object being made to a promise may already have a native handle. - zjs_obj_add_object(obj, promise_obj, "promise"); - - DBG_PRINT("created promise, obj=%lu, promise=%p, handle=%p\n", obj, new, - handle); -} - -void zjs_fulfill_promise(jerry_value_t obj, const jerry_value_t argv[], - uint32_t argc) -{ - zjs_promise_t *handle = NULL; - ZVAL promise_obj = zjs_get_property(obj, "promise"); - - if (!jerry_value_is_object(promise_obj)) { - ERR_PRINT("'promise' not found in object\n"); - return; - } - - jerry_get_object_native_handle(promise_obj, (uintptr_t *)&handle); - if (handle) { - zjs_signal_callback(handle->then_id, argv, - argc * sizeof(jerry_value_t)); - zjs_remove_callback(handle->catch_id); - handle->catch_id = -1; - DBG_PRINT("fulfilling promise, obj=%lu, then_id=%d, argv=%p, nargs=%lu\n", - obj, handle->then_id, argv, argc); - } else { - ERR_PRINT("native handle not found\n"); - } -} - -void zjs_reject_promise(jerry_value_t obj, const jerry_value_t argv[], - uint32_t argc) -{ - zjs_promise_t *handle = NULL; - ZVAL promise_obj = zjs_get_property(obj, "promise"); - - if (!jerry_value_is_object(promise_obj)) { - ERR_PRINT("'promise' not found in object\n"); - return; - } - - jerry_get_object_native_handle(promise_obj, (uintptr_t *)&handle); - if (handle) { - zjs_signal_callback(handle->catch_id, argv, - argc * sizeof(jerry_value_t)); - zjs_remove_callback(handle->then_id); - handle->then_id = -1; - DBG_PRINT("rejecting promise, obj=%lu, catch_id=%d, argv=%p, nargs=%lu\n", - obj, handle->catch_id, argv, argc); - } else { - ERR_PRINT("native handle not found\n"); - } -} diff --git a/src/zjs_promise.h b/src/zjs_promise.h deleted file mode 100644 index 0790b45..0000000 --- a/src/zjs_promise.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2016, Intel Corporation. - -#ifndef __zjs_promises_h__ -#define __zjs_promises_h__ - -#include "zjs_util.h" - -/* - * Function called after a promise has been fulfilled or rejected - * - * @param handle Handle given to zjs_make_promise() - */ -typedef void (*zjs_post_promise_func)(void *handle); - -/* - * Turn an object into a promise - * - * @param obj Object to make a promise - * @param post Function to be called when the promise has been fulfilled/rejected - * @param handle Handle passed to post function - */ -void zjs_make_promise(jerry_value_t obj, zjs_post_promise_func post, - void *handle); - -/* - * Fulfill a promise - * - * @param obj Promise object - * @param args Array of args that will be given to then() - * @param argc Number of arguments in args - */ -void zjs_fulfill_promise(jerry_value_t obj, const jerry_value_t args[], - uint32_t argc); - -/* - * Reject a promise - * - * @param obj Promise object - * @param args Array of args that will be given to catch() - * @param argc Number of arguments in args - */ -void zjs_reject_promise(jerry_value_t obj, const jerry_value_t args[], - uint32_t argc); - -#endif /* __zjs_promises_h__ */ diff --git a/src/zjs_sensor.c b/src/zjs_sensor.c index 7d6f22d..9799d0d 100644 --- a/src/zjs_sensor.c +++ b/src/zjs_sensor.c @@ -30,16 +30,6 @@ #define ZJS_SENSOR_TIMEOUT_TICKS 5000 -#define SENSOR_GET_HANDLE(obj, type, var) \ - type *var; \ - { \ - uintptr_t native; \ - if (!jerry_get_object_native_handle(obj, &native)) { \ - return zjs_error("native handle not found"); \ - } \ - var = (type *)native; \ - } - static struct k_sem sensor_sem; static jerry_value_t zjs_sensor_prototype; @@ -69,6 +59,15 @@ sensor_module_t sensor_modules[] = { #endif }; +static void free_handle(void *native_p) +{ +} + +static const jerry_object_native_info_t sensor_type_info = +{ + .free_cb = free_handle +}; + sensor_instance_t *zjs_sensor_create_instance(const char *name, void *func) { ZVAL global_obj = jerry_get_global_object(); @@ -218,12 +217,7 @@ void zjs_sensor_set_state(jerry_value_t obj, sensor_state_t state) } } - uintptr_t ptr; - sensor_handle_t *handle = NULL; - if (!jerry_get_object_native_handle(obj, &ptr)) { - ERR_PRINT("native handle not found"); - return; - } + ZJS_GET_HANDLE(obj, sensor_handle_t, handle, sensor_type_info); handle = (sensor_handle_t *)ptr; handle->state = state; } @@ -311,22 +305,9 @@ static void ipm_msg_receive_callback(void *context, uint32_t id, volatile void * } } -static void zjs_sensor_callback_free(uintptr_t handle) -{ - sensor_handle_t *tmp = (sensor_handle_t *)handle; - if (tmp->controller) { - zjs_free(tmp->controller); - } - zjs_remove_callback(tmp->onchange_cb_id); - zjs_remove_callback(tmp->onstart_cb_id); - zjs_remove_callback(tmp->onstop_cb_id); - zjs_free(tmp); - DBG_PRINT("sensor handle %p freed\n", (void *)handle); -} - jerry_value_t zjs_sensor_start_sensor(jerry_value_t obj) { - SENSOR_GET_HANDLE(obj, sensor_handle_t, handle); + ZJS_GET_HANDLE(obj, sensor_handle_t, handle, sensor_type_info); zjs_ipm_message_t send; send.type = TYPE_SENSOR_START; @@ -353,7 +334,7 @@ jerry_value_t zjs_sensor_start_sensor(jerry_value_t obj) jerry_value_t zjs_sensor_stop_sensor(jerry_value_t obj) { - SENSOR_GET_HANDLE(obj, sensor_handle_t, handle); + ZJS_GET_HANDLE(obj, sensor_handle_t, handle, sensor_type_info); zjs_ipm_message_t send; send.type = TYPE_SENSOR_STOP; @@ -386,7 +367,7 @@ static ZJS_DECL_FUNC(zjs_sensor_start) return ZJS_UNDEFINED; } - SENSOR_GET_HANDLE(this, sensor_handle_t, handle); + ZJS_GET_HANDLE(this, sensor_handle_t, handle, sensor_type_info); zjs_sensor_set_state(this, SENSOR_STATE_ACTIVATING); if (jerry_value_has_error_flag(zjs_sensor_start_sensor(this))) { @@ -406,7 +387,7 @@ static ZJS_DECL_FUNC(zjs_sensor_stop) return ZJS_UNDEFINED; } - SENSOR_GET_HANDLE(this, sensor_handle_t, handle); + ZJS_GET_HANDLE(this, sensor_handle_t, handle, sensor_type_info); if (jerry_value_has_error_flag(zjs_sensor_start_sensor(this))) { zjs_sensor_trigger_error(this, "SensorError", "start failed"); @@ -508,8 +489,8 @@ ZJS_DECL_FUNC_ARGS(zjs_sensor_create, instance->handles = handle; // watch for the object getting garbage collected, and clean up - jerry_set_object_native_handle(sensor_obj, (uintptr_t)handle, - zjs_sensor_callback_free); + jerry_set_object_native_pointer(sensor_obj, (void *)handle, + &sensor_type_info); DBG_PRINT("sensor driver %s initialized\n", handle->controller->name); DBG_PRINT("sensor frequency %u\n", handle->frequency); diff --git a/src/zjs_test_promise.c b/src/zjs_test_promise.c index 61f324f..f7a14ac 100644 --- a/src/zjs_test_promise.c +++ b/src/zjs_test_promise.c @@ -2,39 +2,14 @@ #ifdef BUILD_MODULE_TEST_PROMISE +#include "jerryscript.h" #include "zjs_common.h" #include "zjs_callbacks.h" -#include "zjs_promise.h" #include "zjs_util.h" -typedef struct dummy_handle { - uint32_t value; -} dummy_handle_t; - -#define TEST_VAL 42 - -static void post_promise(void *handle) -{ - if (handle) { - dummy_handle_t *h = (dummy_handle_t *)handle; - if (h->value != TEST_VAL) { - ERR_PRINT("Handle was not valid!!!\n"); - } - zjs_free(h); - } -} - static ZJS_DECL_FUNC(create_promise) { - dummy_handle_t *handle = zjs_malloc(sizeof(dummy_handle_t)); - handle->value = TEST_VAL; - - jerry_value_t promise = jerry_create_object(); - ZJS_PRINT("Testing promise, object = %u\n", (unsigned int)promise); - - zjs_make_promise(promise, post_promise, handle); - - return promise; + return jerry_create_promise(); } static ZJS_DECL_FUNC(test_fulfill) @@ -42,7 +17,11 @@ static ZJS_DECL_FUNC(test_fulfill) // args: promise object ZJS_VALIDATE_ARGS(Z_OBJECT); - zjs_fulfill_promise(argv[0], NULL, 0); + if (argc > 1) { + jerry_resolve_or_reject_promise(argv[0], argv[1], true); + } else { + jerry_resolve_or_reject_promise(argv[0], ZJS_UNDEFINED, true); + } return ZJS_UNDEFINED; } @@ -51,7 +30,11 @@ static ZJS_DECL_FUNC(test_reject) // args: promise object ZJS_VALIDATE_ARGS(Z_OBJECT); - zjs_reject_promise(argv[0], NULL, 0); + if (argc > 1) { + jerry_resolve_or_reject_promise(argv[0], argv[1], false); + } else { + jerry_resolve_or_reject_promise(argv[0], ZJS_UNDEFINED, false); + } return ZJS_UNDEFINED; } diff --git a/src/zjs_timers.c b/src/zjs_timers.c index e930f18..2b0d12d 100644 --- a/src/zjs_timers.c +++ b/src/zjs_timers.c @@ -30,6 +30,13 @@ typedef struct zjs_timer { static zjs_timer_t *zjs_timers = NULL; +static void free_handle(void *native_p) {} + +static const jerry_object_native_info_t timer_type_info = +{ + .free_cb = free_handle +}; + jerry_value_t *pre_timer(void *h, uint32_t *argc) { zjs_timer_t *handle = (zjs_timer_t *)h; @@ -133,7 +140,7 @@ static ZJS_DECL_FUNC_ARGS(add_timer_helper, bool repeat) argc - 2, argv); if (handle->callback_id == -1) return zjs_error("native_set_interval_handler: timer alloc failed"); - jerry_set_object_native_handle(timer_obj, (uintptr_t)handle, NULL); + jerry_set_object_native_pointer(timer_obj, (void *)handle, &timer_type_info); return timer_obj; } @@ -157,12 +164,7 @@ static ZJS_DECL_FUNC(native_clear_interval_handler) // FIXME: timers should be ints, not objects! ZJS_VALIDATE_ARGS(Z_OBJECT); - jerry_value_t timer_obj = argv[0]; - zjs_timer_t *handle; - - if (!jerry_get_object_native_handle(timer_obj, (uintptr_t *)&handle)) { - return zjs_error("native_clear_interval_handler(): native handle not found"); - } + ZJS_GET_HANDLE(argv[0], zjs_timer_t, handle, timer_type_info); if (!delete_timer(handle->callback_id)) return zjs_error("native_clear_interval_handler: timer not found"); diff --git a/src/zjs_util.h b/src/zjs_util.h index 97feca2..734ccc1 100644 --- a/src/zjs_util.h +++ b/src/zjs_util.h @@ -463,4 +463,18 @@ void zjs_loop_init(void); ret; \ }) +#define ZJS_GET_HANDLE(obj, type, var, info) \ + type *var; \ + { \ + void *native; \ + const jerry_object_native_info_t *tmp; \ + if (!jerry_get_object_native_pointer(obj, &native, &tmp)) { \ + return zjs_error("no native handle"); \ + } \ + if (tmp != &info) { \ + return zjs_error("handle was incorrect type"); \ + } \ + var = (type *)native; \ + } + #endif // __zjs_util_h__ diff --git a/src/zjs_web_sockets.c b/src/zjs_web_sockets.c index 1ec365a..f1c95ce 100644 --- a/src/zjs_web_sockets.c +++ b/src/zjs_web_sockets.c @@ -28,6 +28,8 @@ #include "zjs_net_config.h" #include "zjs_zephyr_port.h" +#include "jerryscript.h" + /* * TODO: * - Implement WebSocket client side @@ -90,6 +92,31 @@ typedef struct ws_packet { uint8_t mask_bit; } ws_packet_t; +static void free_handle(void *native_p) +{ +} + +static const jerry_object_native_info_t ws_type_info = +{ + .free_cb = free_handle +}; + +static void free_server(void *native) +{ + server_handle_t *handle = (server_handle_t *)native; + if (handle) { + jerry_release_value(handle->accept_handler); + net_context_put(handle->tcp_sock); + zjs_free(handle); + } +} + +static const jerry_object_native_info_t server_type_info = +{ + .free_cb = free_server +}; + + // start of header preceding accept key static char accept_header[] = "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" @@ -452,8 +479,7 @@ static jerry_value_t ws_send_data(const jerry_value_t function_obj, { ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_OBJECT, Z_OPTIONAL Z_BOOL); bool mask = 0; - ws_connection_t *con = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&con); + ZJS_GET_HANDLE(this, ws_connection_t, con, ws_type_info); zjs_buffer_t *buf = zjs_buffer_find(argv[0]); if (!buf) { ERR_PRINT("buffer not found\n"); @@ -494,8 +520,7 @@ static ZJS_DECL_FUNC(ws_send) static ZJS_DECL_FUNC(ws_terminate) { - ws_connection_t *con = NULL; - jerry_get_object_native_handle(this, (uintptr_t *)&con); + ZJS_GET_HANDLE(this, ws_connection_t, con, ws_type_info); DBG_PRINT("closing connection\n"); close_connection(con); return ZJS_UNDEFINED; @@ -508,7 +533,7 @@ static jerry_value_t create_ws_connection(ws_connection_t *con) zjs_obj_add_function(conn, ws_ping, "ping"); zjs_obj_add_function(conn, ws_pong, "pong"); zjs_obj_add_function(conn, ws_terminate, "terminate"); - jerry_set_object_native_handle(conn, (uintptr_t)con, NULL); + jerry_set_object_native_pointer(conn, (void *)con, &ws_type_info); zjs_make_event(conn, ZJS_UNDEFINED); if (con->server_handle->track) { ZVAL clients = zjs_get_property(con->server_handle->server, "clients"); @@ -787,16 +812,6 @@ static void tcp_accepted(struct net_context *context, } } -static void free_server(uintptr_t native) -{ - server_handle_t *handle = (server_handle_t *)native; - if (handle) { - jerry_release_value(handle->accept_handler); - net_context_put(handle->tcp_sock); - zjs_free(handle); - } -} - static ZJS_DECL_FUNC(ws_server) { ZJS_VALIDATE_ARGS_OPTCOUNT(optcount, Z_OBJECT, Z_OPTIONAL Z_FUNCTION); @@ -847,7 +862,7 @@ static ZJS_DECL_FUNC(ws_server) zjs_make_event(server, ZJS_UNDEFINED); - jerry_set_object_native_handle(server, (uintptr_t)handle, free_server); + jerry_set_object_native_pointer(server, (void *)handle, &server_type_info); return server; } diff --git a/tests/stress/test-promise-stress.js b/tests/stress/test-promise-stress.js index 884cd68..c0ac35c 100644 --- a/tests/stress/test-promise-stress.js +++ b/tests/stress/test-promise-stress.js @@ -12,7 +12,7 @@ setInterval(function() { var p = test.create_promise(); p.then(function() { console.log("fulfilled sync"); - }).catch(function() { + }, function() { console.log("rejected sync"); }); if (sync_toggle) { @@ -29,7 +29,7 @@ setInterval(function() { var p = test.create_promise(); p.then(function() { console.log("fulfilled async"); - }).catch(function() { + }, function() { console.log("rejected async"); }); setTimeout(function() { diff --git a/tests/test-promise.js b/tests/test-promise.js index 0d42e1c..290aa16 100644 --- a/tests/test-promise.js +++ b/tests/test-promise.js @@ -1,58 +1,110 @@ // Copyright (c) 2017, Intel Corporation. var test = require('test_promise'); +var assert = require('Assert.js'); -var sync_toggle = 0; -var async_toggle = 0; +// test if instance is correct +var p = test.create_promise(); +assert(p instanceof Promise, "instance of promise"); + +// resolve a promise syncrounously var sync_fulfilled = false; -var sync_rejected = false; +p.then(function() { + sync_fulfilled = true; +}, function() { + assert(false, "promise should be fulfilled"); +}); +test.fulfill(p); +setTimeout(function() { + assert(sync_fulfilled, "syncronous promise fulfilled"); + // reject a promise syncronously + var p1 = test.create_promise(); + var sync_rejected = false; + p1.then(function() { + assert(false, "promise should be rejected"); + }, function() { + sync_rejected = true; + }); + test.reject(p1); + setTimeout(function() { + assert(sync_rejected, "syncrounous promise rejected"); + }, 100); +}, 100); + +// fulfill/reject a promise asyncronously +var pasync_ful = test.create_promise(); +var pasync_rej = test.create_promise(); var async_fulfilled = false; var async_rejected = false; +pasync_ful.then(function() { + async_fulfilled = true; +}, function() { + assert(false, "promise should be fulfilled"); +}); +pasync_rej.then(function() { + assert(false, "promise should be rejected"); +}, function() { + async_rejected = true; +}); +setTimeout(function() { + test.fulfill(pasync_ful); + test.reject(pasync_rej); +}, 0); +setTimeout(function() { + assert(async_fulfilled, "async promise was fulfilled"); + assert(async_rejected, "async promise was rejected"); +}, 100); -var sync_int = setInterval(function() { - console.log("calling promise"); - var p = test.create_promise(); - p.then(function() { - console.log("fulfilled sync"); - sync_fulfilled = true; - clearInterval(sync_int); - }).catch(function() { - console.log("rejected sync"); - sync_rejected = true; - }); - if (sync_toggle) { - test.fulfill(p); - } else { - test.reject(p); - } - sync_toggle = (sync_toggle) ? 0 : 1; +// test that arguments are passed correctly +var pargs = test.create_promise(); +var pargs_fulfilled = false; +pargs.then(function(arg) { + assert(arg === "fulfilled", "argument was correct"); + pargs_fulfilled = true; +}, function(arg) { + assert(false, "promise should be fulfilled"); +}); +test.fulfill(pargs, "fulfilled"); +setTimeout(function() { + assert(pargs_fulfilled, "argument promise fulfilled"); }, 100); +// test promies chaining +var pchain = test.create_promise(); +pchain.then(function(arg) { + assert(arg === "chain1", "first chain argument correct"); + if (arg === "chain1") { + return "chain2"; + } +}).then(function(arg) { + assert(arg === "chain2", "second chain argument correct"); + if (arg === "chain2") { + return "chain3"; + } +}).then(function(arg) { + assert(arg === "chain3", "third chain argument correct"); +}); +test.fulfill(pchain, "chain1"); -var async_int = setInterval(function() { - var p = test.create_promise(); - p.then(function() { - console.log("fulfilled async"); - async_fulfilled = true; - clearInterval(async_int); - }).catch(function() { - console.log("rejected async"); - async_rejected = true; - }); - setTimeout(function() { - if (async_toggle) { - test.fulfill(p); - } else { - test.reject(p); - } - async_toggle = (async_toggle) ? 0 : 1; - }, 100); -}, 200); +// test reject in middle of chain +var pchain1 = test.create_promise(); +pchain1.then(function(arg) { + assert(arg === "chain1", "first chain argument correct"); + if (arg === "chain1") { + return "chain2"; + } +}).then(function(arg) { + assert(arg === "chain2", "second chain argument correct"); + if (arg === "chain2") { + throw Error("rejecting at chain2"); + } +}).then(function(arg) { + assert(false, "previous promise was fulfilled, not rejected"); +}, function(error) { + assert(error.message === "rejecting at chain2", "promise rejected correctly") +}); +test.fulfill(pchain1, "chain1"); setTimeout(function() { - if (sync_fulfilled && sync_rejected && async_fulfilled && async_rejected) { - console.log("\033[1m\033[32mPASS\033[0m"); - } else { - console.log("\033[1m\033[31mFAIL\033[0m"); - } -}, 2000); + assert.result(); +}, 1000); diff --git a/tools/Makefile.snapshot b/tools/Makefile.snapshot index 624e02e..126900f 100644 --- a/tools/Makefile.snapshot +++ b/tools/Makefile.snapshot @@ -26,7 +26,8 @@ setup: CORE_SRC += tools/snapshot.c \ src/zjs_common.c \ - src/zjs_script.c + src/zjs_script.c \ + src/jerry-port/zjs_jerry_port.c CORE_OBJ = $(CORE_SRC:%.c=%.o) |