Skip to content

Commit

Permalink
improve JS DOM connector API
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelsadok committed Aug 6, 2021
1 parent 120270f commit 392c20d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
41 changes: 22 additions & 19 deletions cpp/platform_support/dom_connector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@
#include <memory>

struct JsStub;
struct JsFuncStub;
class JsObjectTempRef;
using JsObjectRef = std::shared_ptr<JsObjectTempRef>;

extern "C" {
/**
* @brief Increments the refcount of an opaque JavaScript object ID.
*/
extern void _js_ref(unsigned int obj);
extern void _js_ref(unsigned int obj_id);

/**
* @brief Decrements the refcount of an opaque JavaScript object ID.
*
* When the refcount reaches zero the object ID must not be used anymore.
*/
extern void _js_unref(unsigned int obj);
extern void _js_unref(unsigned int obj_id);

extern void _js_call_sync(unsigned int obj, const char* func, JsStub* args, size_t n_args);
extern void _js_call_async(unsigned int obj, const char* func, JsStub* args, size_t n_args, void(*callback)(void*, const JsStub&), void* ctx, unsigned int dict_depth);
extern void _js_get_property(unsigned int obj, const char* property, void(*callback)(void*, const JsStub&), void* ctx, unsigned int dict_depth);
extern void _js_set_property(unsigned int obj, const char* property, JsStub* arg);
extern void* _js_get_property(unsigned int obj_id, const char* property, unsigned int dict_depth, JsStub* p_out);
extern void _js_set_property(unsigned int obj_id, const char* property, JsStub* arg);
extern void* _js_call_sync(unsigned int obj_id, const char* func, JsStub* args, size_t n_args, unsigned int dict_depth, JsStub* p_out);
extern void _js_call_async(unsigned int obj_id, const char* func, JsStub* args, size_t n_args, void(*callback)(void*, const JsStub&, const JsStub&), void* ctx, unsigned int dict_depth);

extern void _js_release(void*);
}


Expand All @@ -53,10 +56,11 @@ struct JsStub {
struct JsFuncStub {
uintptr_t callback;
uintptr_t ctx;
unsigned int dict_depth;
};

struct JsArrayStub {
uintptr_t start;
uintptr_t begin;
uintptr_t end;
};

Expand All @@ -75,7 +79,10 @@ class JsTransferStorage {
delete [] ptr;
}
for (auto ptr: funcs) {
delete [] ptr;
delete ptr;
}
for (auto ptr: arrays) {
delete ptr;
}
}

Expand Down Expand Up @@ -115,7 +122,7 @@ class JsTransferStorage {
}

JsStub to_js(fibre::Callback<void, const JsStub*, size_t> val) {
JsFuncStub* func = new JsFuncStub{(uintptr_t)val.get_ptr(), (uintptr_t)val.get_ctx()};
JsFuncStub* func = new JsFuncStub{(uintptr_t)val.get_ptr(), (uintptr_t)val.get_ctx(), 0};
funcs.push_back(func);
return {JsType::kFunc, (uintptr_t)func};
}
Expand Down Expand Up @@ -146,14 +153,10 @@ class JsObjectTempRef {
}

template<typename TVal> fibre::RichStatus get_property(std::string property, TVal* result, unsigned int dict_depth = 0) {
fibre::RichStatus status;
fibre::Callback<void, const JsStub&> callback{
[&](const JsStub& stub) {
status = from_js(stub, result);
}
};
_js_get_property(id_, property.data(), callback.get_ptr(),
callback.get_ctx(), dict_depth);
JsStub out;
void* storage = _js_get_property(id_, property.data(), dict_depth, &out);
fibre::RichStatus status = from_js(out, result);
_js_release(storage);
return status;
}

Expand All @@ -172,7 +175,7 @@ class JsObjectTempRef {

template<typename... TArgs>
void call_async(std::string func,
fibre::Callback<void, const JsStub&> callback,
fibre::Callback<void, const JsStub&, const JsStub&> callback,
unsigned int dict_depth,
TArgs... args) {
JsTransferStorage storage;
Expand Down Expand Up @@ -266,7 +269,7 @@ static inline fibre::RichStatus from_js(const JsStub& stub, fibre::cbufptr_t* ou
// time allocated buffer. Maybe we can optimize this?
F_RET_IF(stub.type != JsType::kArray, "expected array type but got " << (int)stub.type);
JsArrayStub* array_stub = (JsArrayStub*)stub.val;
*output = {(const unsigned char*)array_stub->start, (const unsigned char*)array_stub->end};
*output = {(const unsigned char*)array_stub->begin, (const unsigned char*)array_stub->end};
return fibre::RichStatus::success();
}

Expand Down
11 changes: 7 additions & 4 deletions cpp/platform_support/dom_connector.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ mergeInto(LibraryManager.library, {
const cb = Module.asm.__indirect_function_table.get(callback);
const storage = makeStorage();
try {
const ptr = Module._malloc(8 + args.length);
const ptr = Module._malloc(8 * args.length);
try {
for (let i = 0; i < args.length; ++i) {
toWasm(storage, args[i], ptr + 8 * i);
Expand Down Expand Up @@ -215,19 +215,22 @@ mergeInto(LibraryManager.library, {

__js_ref = _js_ref;
__js_unref = _js_unref;
__js_call_async = _js_call_async;
__js_get_property = _js_get_property;
__js_set_property = _js_set_property;
__js_call_async = _js_call_async;
__js_release = _js_release;
},

_js_ref: function() {},
_js_ref__deps: ['$method_support'],
_js_unref: function() {},
_js_unref__deps: ['$method_support'],
_js_call_async: function() {},
_js_call_async__deps: ['$method_support'],
_js_get_property: function() {},
_js_get_property__deps: ['$method_support'],
_js_set_property: function() {},
_js_set_property__deps: ['$method_support'],
_js_call_async: function() {},
_js_call_async__deps: ['$method_support'],
_js_release: function() {},
_js_release__deps: ['$method_support'],
});
35 changes: 20 additions & 15 deletions cpp/platform_support/webusb_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class WebUsb final : public UsbHostController {
on_lost_device_t on_lost) final;
RichStatus stop() final;

void on_get_devices_finished(const JsStub& stub);
void on_get_devices_finished(const JsStub& result_stub, const JsStub& error_stub);
void on_connect(const JsStub* args, size_t n_args);
void on_disconnect(const JsStub* args, size_t n_args);

Expand All @@ -51,10 +51,10 @@ struct WebUsbDevice final : UsbDevice {
RichStatus bulk_in_transfer(uint8_t ep_num, bufptr_t buffer, Callback<void, RichStatus, unsigned char*> callback) final;
RichStatus bulk_out_transfer(uint8_t ep_num, cbufptr_t buffer, Callback<void, RichStatus, const unsigned char*> callback) final;

void on_open_finished(const JsStub& stub);
void on_claim_interface_finished(const JsStub& stub);
void on_bulk_in_transfer_finished(const JsStub& stub);
void on_bulk_out_transfer_finished(const JsStub& stub);
void on_open_finished(const JsStub& result_stub, const JsStub& error_stub);
void on_claim_interface_finished(const JsStub& result_stub, const JsStub& error_stub);
void on_bulk_in_transfer_finished(const JsStub& result_stub, const JsStub& error_stub);
void on_bulk_out_transfer_finished(const JsStub& result_stub, const JsStub& error_stub);

WebUsb* webusb_;
JsObjectRef ref_;
Expand Down Expand Up @@ -101,11 +101,11 @@ RichStatus WebUsb::stop() {
return RichStatus::success();
}

void WebUsb::on_get_devices_finished(const JsStub& stub) {
void WebUsb::on_get_devices_finished(const JsStub& result_stub, const JsStub& error_stub) {
F_LOG_D(logger_, "got devices");

std::vector<JsObjectRef> devices;
if (F_LOG_IF_ERR(logger_, from_js(stub, &devices), "in device list")) {
if (F_LOG_IF_ERR(logger_, from_js(result_stub, &devices), "in device list")) {
return;
}

Expand Down Expand Up @@ -243,21 +243,26 @@ RichStatus WebUsbDevice::bulk_out_transfer(uint8_t ep_num, cbufptr_t buffer, Cal
return RichStatus::success();
}

void WebUsbDevice::on_open_finished(const JsStub& stub) {
F_LOG_D(webusb_->logger_, "open finished");
open_cb_.invoke_and_clear(this);
void WebUsbDevice::on_open_finished(const JsStub& result_stub, const JsStub& error_stub) {
if (error_stub.type != JsType::kUndefined) {
F_LOG_D(webusb_->logger_, "open failed with type " << (int)error_stub.type);
// TODO: error handling
} else {
F_LOG_D(webusb_->logger_, "open finished");
open_cb_.invoke_and_clear(this);
}
}

void WebUsbDevice::on_claim_interface_finished(const JsStub& stub) {
void WebUsbDevice::on_claim_interface_finished(const JsStub& result_stub, const JsStub& error_stub) {
F_LOG_D(webusb_->logger_, "claim_interface finished");
claim_interface_cb_.invoke_and_clear(this);
}

void WebUsbDevice::on_bulk_in_transfer_finished(const JsStub& stub) {
void WebUsbDevice::on_bulk_in_transfer_finished(const JsStub& result_stub, const JsStub& error_stub) {
F_LOG_T(webusb_->logger_, "bulk_in_transfer finished");

std::unordered_map<std::string, JsStub> result;
if (F_LOG_IF_ERR(webusb_->logger_, from_js(stub, &result), "can't parse transfer result")) {
if (F_LOG_IF_ERR(webusb_->logger_, from_js(result_stub, &result), "can't parse transfer result")) {
return; // TODO: propagate error to callback
}

Expand Down Expand Up @@ -296,11 +301,11 @@ void WebUsbDevice::on_bulk_in_transfer_finished(const JsStub& stub) {
bulk_in_transfer_cb_.invoke_and_clear(RichStatus::success(), end);
}

void WebUsbDevice::on_bulk_out_transfer_finished(const JsStub& stub) {
void WebUsbDevice::on_bulk_out_transfer_finished(const JsStub& result_stub, const JsStub& error_stub) {
F_LOG_T(webusb_->logger_, "bulk_out_transfer finished");

std::unordered_map<std::string, JsStub> result;
if (F_LOG_IF_ERR(webusb_->logger_, from_js(stub, &result), "can't parse transfer result")) {
if (F_LOG_IF_ERR(webusb_->logger_, from_js(result_stub, &result), "can't parse transfer result")) {
return; // TODO: propagate error to callback
}

Expand Down

0 comments on commit 392c20d

Please sign in to comment.