Skip to content

Commit

Permalink
feat: Add KVStore.prototype.delete method
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeChampion committed Apr 11, 2024
1 parent f5cefbb commit 578d858
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
84 changes: 84 additions & 0 deletions runtime/js-compute-runtime/builtins/kv-store.cpp
Expand Up @@ -183,6 +183,89 @@ bool parse_and_validate_key(JSContext *cx, const char *key, size_t len) {

} // namespace

bool KVStore::has_pending_delete_handle(JSObject *self) {
MOZ_ASSERT(KVStore::is_instance(self));

JS::Value handle_val =
JS::GetReservedSlot(self, static_cast<uint32_t>(Slots::PendingDeleteHandle));
return handle_val.isInt32() &&
handle_val.toInt32() != host_api::ObjectStorePendingDelete::invalid;
}

host_api::ObjectStorePendingDelete KVStore::pending_delete_handle(JSObject *self) {
MOZ_ASSERT(KVStore::is_instance(self));
host_api::ObjectStorePendingDelete res;

JS::Value handle_val =
JS::GetReservedSlot(self, static_cast<uint32_t>(Slots::PendingDeleteHandle));
if (handle_val.isInt32()) {
res = host_api::ObjectStorePendingDelete(handle_val.toInt32());
}

return res;
}

bool KVStore::process_pending_kv_store_delete(JSContext *cx, JS::HandleObject self) {
MOZ_ASSERT(KVStore::is_instance(self));

auto pending_promise_value =
JS::GetReservedSlot(self, static_cast<uint32_t>(Slots::PendingDeletePromise));
MOZ_ASSERT(pending_promise_value.isObject());
JS::RootedObject result_promise(cx, &pending_promise_value.toObject());

auto res = builtins::KVStore::pending_delete_handle(self).wait();

if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return RejectPromiseWithPendingError(cx, result_promise);
}

JS::ResolvePromise(cx, result_promise, JS::UndefinedHandleValue);

return true;
}

bool KVStore::delete_(JSContext *cx, unsigned argc, JS::Value *vp) {
METHOD_HEADER_WITH_NAME(1, "delete");

JS::RootedObject result_promise(cx, JS::NewPromiseObject(cx, nullptr));
if (!result_promise) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

JS::RootedValue key(cx, args.get(0));

// Convert the key argument into a String following https://tc39.es/ecma262/#sec-tostring
auto key_chars = core::encode(cx, key);
if (!key_chars) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

if (!parse_and_validate_key(cx, key_chars.begin(), key_chars.len)) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

auto res = kv_store_handle(self).delete_async(key_chars);

if (auto *err = res.to_err()) {
HANDLE_ERROR(cx, *err);
return ReturnPromiseRejectedWithPendingError(cx, args);
}
auto ret = res.unwrap();

JS::SetReservedSlot(self, static_cast<uint32_t>(Slots::PendingDeleteHandle),
JS::Int32Value(ret.handle));
JS::SetReservedSlot(self, static_cast<uint32_t>(Slots::PendingDeletePromise),
JS::ObjectValue(*result_promise));

if (!core::EventLoop::queue_async_task(self)) {
return ReturnPromiseRejectedWithPendingError(cx, args);
}

args.rval().setObject(*result_promise);
return true;
}

host_api::ObjectStorePendingLookup KVStore::pending_lookup_handle(JSObject *self) {
MOZ_ASSERT(KVStore::is_instance(self));
host_api::ObjectStorePendingLookup res;
Expand Down Expand Up @@ -399,6 +482,7 @@ const JSPropertySpec KVStore::static_properties[] = {
};

const JSFunctionSpec KVStore::methods[] = {
JS_FN("delete", delete_, 1, JSPROP_ENUMERATE),
JS_FN("get", get, 1, JSPROP_ENUMERATE),
JS_FN("put", put, 1, JSPROP_ENUMERATE),
JS_FS_END,
Expand Down
6 changes: 6 additions & 0 deletions runtime/js-compute-runtime/builtins/kv-store.h
Expand Up @@ -31,6 +31,7 @@ class KVStoreEntry final : public BuiltinImpl<KVStoreEntry> {
};

class KVStore final : public BuiltinImpl<KVStore> {
static bool delete_(JSContext *cx, unsigned argc, JS::Value *vp);
static bool get(JSContext *cx, unsigned argc, JS::Value *vp);
static bool put(JSContext *cx, unsigned argc, JS::Value *vp);

Expand All @@ -40,6 +41,8 @@ class KVStore final : public BuiltinImpl<KVStore> {
KVStore,
PendingLookupPromise,
PendingLookupHandle,
PendingDeletePromise,
PendingDeleteHandle,
Count,
};
static const JSFunctionSpec static_methods[];
Expand All @@ -53,6 +56,9 @@ class KVStore final : public BuiltinImpl<KVStore> {
static bool constructor(JSContext *cx, unsigned argc, JS::Value *vp);
static host_api::ObjectStorePendingLookup pending_lookup_handle(JSObject *self);
static bool process_pending_kv_store_lookup(JSContext *cx, JS::HandleObject self);
static host_api::ObjectStorePendingDelete pending_delete_handle(JSObject *self);
static bool process_pending_kv_store_delete(JSContext *cx, JS::HandleObject self);
static bool has_pending_delete_handle(JSObject *self);
};

} // namespace builtins
Expand Down
12 changes: 10 additions & 2 deletions runtime/js-compute-runtime/core/event_loop.cpp
Expand Up @@ -260,7 +260,11 @@ bool EventLoop::process_pending_async_tasks(JSContext *cx) {
if (builtins::Request::is_instance(pending_obj)) {
handles.push_back(builtins::Request::pending_handle(pending_obj).async_handle());
} else if (builtins::KVStore::is_instance(pending_obj)) {
handles.push_back(builtins::KVStore::pending_lookup_handle(pending_obj).async_handle());
if (builtins::KVStore::has_pending_delete_handle(pending_obj)) {
handles.push_back(builtins::KVStore::pending_delete_handle(pending_obj).async_handle());
} else {
handles.push_back(builtins::KVStore::pending_lookup_handle(pending_obj).async_handle());
}
} else {
MOZ_ASSERT(builtins::NativeStreamSource::is_instance(pending_obj));
JS::RootedObject owner(cx, builtins::NativeStreamSource::owner(pending_obj));
Expand Down Expand Up @@ -301,7 +305,11 @@ bool EventLoop::process_pending_async_tasks(JSContext *cx) {
if (builtins::Request::is_instance(ready_obj)) {
ok = process_pending_request(cx, ready_obj, host_api::HttpPendingReq{ready_handle});
} else if (builtins::KVStore::is_instance(ready_obj)) {
ok = builtins::KVStore::process_pending_kv_store_lookup(cx, ready_obj);
if (builtins::KVStore::has_pending_delete_handle(ready_obj)) {
ok = builtins::KVStore::process_pending_kv_store_delete(cx, ready_obj);
} else {
ok = builtins::KVStore::process_pending_kv_store_lookup(cx, ready_obj);
}
} else {
MOZ_ASSERT(builtins::NativeStreamSource::is_instance(ready_obj));
ok = process_body_read(cx, ready_obj, host_api::HttpBody{ready_handle});
Expand Down

0 comments on commit 578d858

Please sign in to comment.