From d377c1426ab0acebc9cb40661d9bc444a81ad8e5 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Tue, 17 Oct 2023 03:25:17 +0100 Subject: [PATCH] Remove custom gpp_rethrow wrapper Upstream Emscripten now natively propagates exception messages to JS. --- src/api.cpp | 228 ++++++++++++++++++++++------------------------------ 1 file changed, 97 insertions(+), 131 deletions(-) diff --git a/src/api.cpp b/src/api.cpp index 9e7679b..0c42504 100644 --- a/src/api.cpp +++ b/src/api.cpp @@ -50,24 +50,6 @@ void gpp_log_error(GPContext *context, const char *text, void *data) { OUT; \ }) -EM_JS([[noreturn]] void, throw_msg, (const char *msg), - { throw new Error(UTF8ToString(msg)); }); - -// This is workaround for Emscripten throwing C++ exceptions as meaningless -// numbers (pointers) instead of actual messages. -// To rethrow actual message, we manually wrap all Embind exports into -// callbacks, those callbacks are passed to this function, -// it ensures that all destructors are executed correctly, catches C++ exception -// if any, extracts the message and rethrows it as a JS one. Easy-peasy... -template -auto gpp_rethrow(Func func) { - try { - return func(); - } catch (std::exception &e) { - throw_msg(e.what()); - } -} - const thread_local val Uint8Array = val::global("Uint8Array"); const thread_local val Blob = val::global("Blob"); const thread_local val File = val::global("File"); @@ -75,150 +57,134 @@ const thread_local val arrayOf = val::global("Array")["of"]; class Context { public: - Context() : camera(nullptr), context(nullptr) { - gpp_rethrow([=]() { - camera.reset(GPP_CALL(Camera *, gp_camera_new(_))); - context.reset(gp_context_new()); - gp_context_set_error_func(context.get(), gpp_log_error, nullptr); - gpp_try(gp_camera_init(camera.get(), context.get())); - }); + Context() + : camera(GPP_CALL(Camera *, gp_camera_new(_))), + context(gp_context_new()) { + gp_context_set_error_func(context.get(), gpp_log_error, nullptr); + gpp_try(gp_camera_init(camera.get(), context.get())); } val supportedOps() { - return gpp_rethrow([=]() { - auto ops = - GPP_CALL(CameraAbilities, gp_camera_get_abilities(camera.get(), _)) - .operations; + auto ops = + GPP_CALL(CameraAbilities, gp_camera_get_abilities(camera.get(), _)) + .operations; - val result = val::object(); - result.set("captureImage", (ops & GP_OPERATION_CAPTURE_IMAGE) != 0); - result.set("captureVideo", (ops & GP_OPERATION_CAPTURE_VIDEO) != 0); - result.set("captureAudio", (ops & GP_OPERATION_CAPTURE_AUDIO) != 0); - result.set("capturePreview", (ops & GP_OPERATION_CAPTURE_PREVIEW) != 0); - result.set("config", (ops & GP_OPERATION_CONFIG) != 0); - result.set("triggerCapture", (ops & GP_OPERATION_TRIGGER_CAPTURE) != 0); - return result; - }); + val result = val::object(); + result.set("captureImage", (ops & GP_OPERATION_CAPTURE_IMAGE) != 0); + result.set("captureVideo", (ops & GP_OPERATION_CAPTURE_VIDEO) != 0); + result.set("captureAudio", (ops & GP_OPERATION_CAPTURE_AUDIO) != 0); + result.set("capturePreview", (ops & GP_OPERATION_CAPTURE_PREVIEW) != 0); + result.set("config", (ops & GP_OPERATION_CONFIG) != 0); + result.set("triggerCapture", (ops & GP_OPERATION_TRIGGER_CAPTURE) != 0); + return result; } bool consumeEvents() { - return gpp_rethrow([=]() { - bool had_events = false; - for (;;) { - CameraEventType event_type = GP_EVENT_UNKNOWN; - gpp_unique_ptr event_data(GPP_CALL( - void *, gp_camera_wait_for_event(camera.get(), 0, &event_type, _, - context.get()))); - if (event_type == GP_EVENT_TIMEOUT) { - break; - } - if (event_type == GP_EVENT_UNKNOWN) { - // EM_ASM({ console.log(UTF8ToString($0)); }, event_data.get()); - } - had_events = true; + bool had_events = false; + for (;;) { + CameraEventType event_type = GP_EVENT_UNKNOWN; + gpp_unique_ptr event_data(GPP_CALL( + void *, gp_camera_wait_for_event(camera.get(), 0, &event_type, _, + context.get()))); + if (event_type == GP_EVENT_TIMEOUT) { + break; } - return had_events; - }); + if (event_type == GP_EVENT_UNKNOWN) { + // EM_ASM({ console.log(UTF8ToString($0)); }, event_data.get()); + } + had_events = true; + } + return had_events; } val configToJS() { - return gpp_rethrow([=]() { - GPPWidget config( - GPP_CALL(CameraWidget *, - gp_camera_get_config(camera.get(), _, context.get()))); - return walk_config(config.get()).second; - }); + GPPWidget config(GPP_CALL( + CameraWidget *, gp_camera_get_config(camera.get(), _, context.get()))); + return walk_config(config.get()).second; } void setConfigValue(std::string name, val value) { - gpp_rethrow([=]() { - GPPWidget widget(GPP_CALL( - CameraWidget *, gp_camera_get_single_config( - camera.get(), name.c_str(), _, context.get()))); - auto type = - GPP_CALL(CameraWidgetType, gp_widget_get_type(widget.get(), _)); - switch (type) { - case GP_WIDGET_RANGE: { - float number = value.as(); - gpp_try(gp_widget_set_value(widget.get(), &number)); - break; - } - case GP_WIDGET_MENU: - case GP_WIDGET_RADIO: - case GP_WIDGET_TEXT: { - auto str = value.as(); - gpp_try(gp_widget_set_value(widget.get(), str.c_str())); - break; - } - case GP_WIDGET_TOGGLE: { - int on = value.as() ? 1 : 0; - gpp_try(gp_widget_set_value(widget.get(), &on)); - break; - } - case GP_WIDGET_DATE: { - auto seconds = static_cast(value.as() / 1000); - gpp_try(gp_widget_set_value(widget.get(), &seconds)); - break; - } - default: { - throw std::logic_error("unimplemented"); - } + GPPWidget widget(GPP_CALL( + CameraWidget *, gp_camera_get_single_config(camera.get(), name.c_str(), + _, context.get()))); + auto type = GPP_CALL(CameraWidgetType, gp_widget_get_type(widget.get(), _)); + switch (type) { + case GP_WIDGET_RANGE: { + float number = value.as(); + gpp_try(gp_widget_set_value(widget.get(), &number)); + break; } - gpp_try(gp_camera_set_single_config(camera.get(), name.c_str(), - widget.get(), context.get())); - }); + case GP_WIDGET_MENU: + case GP_WIDGET_RADIO: + case GP_WIDGET_TEXT: { + auto str = value.as(); + gpp_try(gp_widget_set_value(widget.get(), str.c_str())); + break; + } + case GP_WIDGET_TOGGLE: { + int on = value.as() ? 1 : 0; + gpp_try(gp_widget_set_value(widget.get(), &on)); + break; + } + case GP_WIDGET_DATE: { + auto seconds = static_cast(value.as() / 1000); + gpp_try(gp_widget_set_value(widget.get(), &seconds)); + break; + } + default: { + throw std::logic_error("unimplemented"); + } + } + gpp_try(gp_camera_set_single_config(camera.get(), name.c_str(), + widget.get(), context.get())); } val capturePreviewAsBlob() { - return gpp_rethrow([=]() { - auto &file = get_file(); + auto &file = get_file(); - gpp_try(gp_camera_capture_preview(camera.get(), &file, context.get())); + gpp_try(gp_camera_capture_preview(camera.get(), &file, context.get())); - auto params = blob_chunks_and_opts(file); - return Blob.new_(std::move(params.first), std::move(params.second)); - }); + auto params = blob_chunks_and_opts(file); + return Blob.new_(std::move(params.first), std::move(params.second)); } val captureImageAsFile() { - return gpp_rethrow([=]() { - auto &file = get_file(); + auto &file = get_file(); - { - struct TempCameraFile { - Camera &camera; - GPContext &context; - CameraFilePath path; + { + struct TempCameraFile { + Camera &camera; + GPContext &context; + CameraFilePath path; - ~TempCameraFile() { - gp_camera_file_delete(&camera, path.folder, path.name, &context); - } - }; + ~TempCameraFile() { + gp_camera_file_delete(&camera, path.folder, path.name, &context); + } + }; - TempCameraFile camera_file{ - .camera = *camera, - .context = *context, - }; + TempCameraFile camera_file{ + .camera = *camera, + .context = *context, + }; - strcpy(camera_file.path.folder, "/"); - strcpy(camera_file.path.name, "web-gphoto2"); + strcpy(camera_file.path.folder, "/"); + strcpy(camera_file.path.name, "web-gphoto2"); - gpp_try(gp_camera_capture(camera.get(), GP_CAPTURE_IMAGE, - &camera_file.path, context.get())); + gpp_try(gp_camera_capture(camera.get(), GP_CAPTURE_IMAGE, + &camera_file.path, context.get())); - gpp_try(gp_camera_file_get(camera.get(), camera_file.path.folder, - camera_file.path.name, GP_FILE_TYPE_NORMAL, - &file, context.get())); - } + gpp_try(gp_camera_file_get(camera.get(), camera_file.path.folder, + camera_file.path.name, GP_FILE_TYPE_NORMAL, + &file, context.get())); + } - gpp_try(gp_file_set_name(&file, "image.")); - gpp_try(gp_file_adjust_name_for_mime_type(&file)); - auto name = val(GPP_CALL(const char *, gp_file_get_name(&file, _))); + gpp_try(gp_file_set_name(&file, "image.")); + gpp_try(gp_file_adjust_name_for_mime_type(&file)); + auto name = val(GPP_CALL(const char *, gp_file_get_name(&file, _))); - auto params = blob_chunks_and_opts(file); - return File.new_(std::move(params.first), std::move(name), - std::move(params.second)); - }); + auto params = blob_chunks_and_opts(file); + return File.new_(std::move(params.first), std::move(name), + std::move(params.second)); } private: