18#define JS_KV_PERMISSION_ERROR_HELPER(C_FUNC_NAME, JS_METHOD_NAME) \
19 static JSValue C_FUNC_NAME( \
20 JSContext* ctx, JSValueConst this_val, int, JSValueConst*) \
22 js::core::Context& jsctx = \
23 *static_cast<js::core::Context*>(JS_GetContextOpaque(ctx)); \
24 const auto table_name = \
25 jsctx.to_str(JS_GetPropertyStr(jsctx, this_val, "_map_name")) \
27 if (table_name.empty()) \
29 return JS_ThrowTypeError(ctx, "Internal: No map name stored on handle"); \
31 auto func = jsctx.get_property(this_val, JS_METHOD_NAME); \
32 std::string explanation; \
33 auto error_msg = func["_error_msg"]; \
34 if (!error_msg.is_undefined()) \
36 explanation = jsctx.to_str(error_msg).value_or(""); \
38 return JS_ThrowTypeError( \
40 "Cannot call " #JS_METHOD_NAME " on table named %s. %s", \
42 explanation.c_str()); \
53 js_kv_get_version_of_previous_write_denied, "getVersionOfPreviousWrite")
54#undef JS_KV_PERMISSION_ERROR_HELPER
56#define JS_CHECK_HANDLE(h) \
61 return JS_ThrowInternalError( \
62 ctx, "Internal: Unable to access MapHandle"); \
66 template <ROHandleGetter GetReadOnlyHandle>
67 static JSValue js_kv_map_has(
75 return JS_ThrowTypeError(
76 ctx,
"Passed %d arguments, but expected 1",
argc);
84 return JS_ThrowTypeError(ctx,
"Argument must be an ArrayBuffer");
95 template <ROHandleGetter GetReadOnlyHandle>
96 static JSValue js_kv_map_get(
104 return JS_ThrowTypeError(
105 ctx,
"Passed %d arguments, but expected 1",
argc);
113 return JS_ThrowTypeError(ctx,
"Argument must be an ArrayBuffer");
121 if (!val.has_value())
123 return ccf::js::core::constants::Undefined;
133 template <ROHandleGetter GetReadOnlyHandle>
134 static JSValue js_kv_get_version_of_previous_write(
137 js::core::Context& jsctx =
138 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
142 return JS_ThrowTypeError(
143 ctx,
"Passed %d arguments, but expected 1",
argc);
151 return JS_ThrowTypeError(ctx,
"Argument must be an ArrayBuffer");
159 if (!val.has_value())
161 return ccf::js::core::constants::Undefined;
164 return JS_NewInt64(ctx, val.value());
167 template <ROHandleGetter GetReadOnlyHandle>
168 static JSValue js_kv_map_size_getter(
169 JSContext* ctx, JSValueConst
this_val,
int , JSValueConst*)
171 js::core::Context& jsctx =
172 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
177 const uint64_t size =
handle->size();
178 if (size > INT64_MAX)
180 return JS_ThrowInternalError(
181 ctx,
"Map size (%lu) is too large to represent in int64", size);
184 return JS_NewInt64(ctx, (int64_t)size);
187 template <RWHandleGetter GetWriteHandle>
188 static JSValue js_kv_map_delete(
191 js::core::Context& jsctx =
192 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
196 return JS_ThrowTypeError(
197 ctx,
"Passed %d arguments, but expected 1",
argc);
205 return JS_ThrowTypeError(ctx,
"Argument must be an ArrayBuffer");
213 return ccf::js::core::constants::Undefined;
216 template <RWHandleGetter GetWriteHandle>
217 static JSValue js_kv_map_set(
220 js::core::Context& jsctx =
221 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
225 return JS_ThrowTypeError(
226 ctx,
"Passed %d arguments, but expected 2",
argc);
233 uint8_t* val = JS_GetArrayBuffer(ctx, &val_size,
argv[1]);
237 return JS_ThrowTypeError(ctx,
"Arguments must be ArrayBuffers");
248 template <RWHandleGetter GetWriteHandle>
249 static JSValue js_kv_map_clear(
250 JSContext* ctx, JSValueConst
this_val,
int argc, JSValueConst* )
252 js::core::Context& jsctx =
253 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
257 return JS_ThrowTypeError(
258 ctx,
"Passed %d arguments, but expected 0",
argc);
266 return ccf::js::core::constants::Undefined;
269 template <ROHandleGetter GetReadOnlyHandle>
270 static JSValue js_kv_map_foreach(
273 js::core::Context& jsctx =
274 *
static_cast<js::core::Context*
>(JS_GetContextOpaque(ctx));
278 return JS_ThrowTypeError(
279 ctx,
"Passed %d arguments, but expected 1",
argc);
282 js::core::JSWrappedValue func(ctx,
argv[0]);
283 js::core::JSWrappedValue obj(ctx,
this_val);
285 if (!JS_IsFunction(ctx, func.val))
287 return JS_ThrowTypeError(ctx,
"Argument must be a function");
295 [&jsctx, &obj, &func, &failed](
const auto& k,
const auto& v) {
296 auto value = jsctx.new_array_buffer_copy(v.data(), v.size());
297 if (value.is_exception())
302 auto key = jsctx.new_array_buffer_copy(k.data(), k.size());
303 if (
key.is_exception())
309 std::vector<js::core::JSWrappedValue> args = {value,
key, obj};
311 auto val = jsctx.inner_call(func, args);
313 if (val.is_exception())
324 return ccf::js::core::constants::Exception;
327 return ccf::js::core::constants::Undefined;
329#undef JS_CHECK_HANDLE
331 template <ROHandleGetter GetReadOnlyHandle, RWHandleGetter GetWriteHandle>
332 static JSValue create_kv_map_handle(
333 js::core::Context& ctx,
334 const std::string& map_name,
336 const std::string& permission_explanation)
346 auto map_name_val = ctx.new_string(map_name);
348 JS_CHECK_SET(view_val.set(
"_map_name", std::move(map_name_val)));
355#define MAKE_FUNCTION( \
359 FUNC_FACTORY_METHOD, \
366 const auto permitted = \
367 ccf::js::intersect_access_permissions( \
368 access_permission, PERMISSION_FLAGS) != KVAccessPermissions::ILLEGAL; \
369 auto fn_val = ctx.FUNC_FACTORY_METHOD( \
370 !permitted ? C_FUNC_NAME##_denied : C_FUNC_NAME<HANDLE_GETTER>, \
373 JS_CHECK_EXC(fn_val); \
377 fn_val.set("_error_msg", ctx.new_string(permission_explanation))); \
379 JS_CHECK_SET(view_val.SETTER_METHOD(JS_METHOD_NAME, std::move(fn_val))); \
382#define MAKE_READ_FUNCTION(C_FUNC_NAME, JS_METHOD_NAME, ARG_COUNT) \
389 KVAccessPermissions::READ_ONLY, \
392#define MAKE_WRITE_FUNCTION(C_FUNC_NAME, JS_METHOD_NAME, ARG_COUNT) \
399 KVAccessPermissions::WRITE_ONLY, \
407 js_kv_get_version_of_previous_write,
"getVersionOfPreviousWrite", 1);
415 js_kv_map_size_getter,
418 new_getter_c_function,
423#undef MAKE_RW_FUNCTION
424#undef MAKE_RO_FUNCTION
427 return view_val.take();
JSWrappedValue new_array_buffer_copy(const uint8_t *buf, size_t buf_len) const
Definition context.cpp:335