Skip to content

Commit

Permalink
Add emscripten_idb_clear API (#20182)
Browse files Browse the repository at this point in the history
This patch adds missing `clear` IndexedDB API (both sync and async
versions).
  • Loading branch information
polarnis authored Sep 11, 2023
1 parent 5da546c commit 104e3de
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 3 deletions.
22 changes: 22 additions & 0 deletions site/source/docs/api_reference/emscripten.h.rst
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,21 @@ Asynchronous IndexedDB API
- *(void*)* : Equal to ``arg`` (user defined data).
.. c:function:: void emscripten_idb_async_clear(const char *db_name, void* arg, em_arg_callback_func onclear, em_arg_callback_func onerror)
Clears all data from local IndexedDB storage asynchronously.
When the storage has been cleared then the ``onclear`` callback will be called. If any error occurred ``onerror`` will be called.
:param db_name: The IndexedDB database.
:param void* arg: User-defined data that is passed to the callbacks, untouched by the API itself. This may be used by a callback to identify the associated call.
:param em_arg_callback_func onclear: Callback on successful clear. The callback function parameter is:
- *(void*)* : Equal to ``arg`` (user defined data).
:param em_arg_callback_func onerror: Callback in the event of failure. The callback function parameter is:
- *(void*)* : Equal to ``arg`` (user defined data).
.. c:function:: int emscripten_run_preload_plugins(const char* file, em_str_callback_func onload, em_str_callback_func onerror)
Expand Down Expand Up @@ -1362,6 +1377,13 @@ IndexedDB
:param pexists: An out parameter that will be filled with a non-zero value if the file exists in that database.
:param perror: An out parameter that will be filled with a non-zero value if an error occurred.
.. c:function:: void emscripten_idb_clear(const char *db_name, int *perror);
Synchronously clears all data from IndexedDB.
:param db_name: The name of the database to clear
:param perror: An out parameter that will be filled with a non-zero value if an error occurred.
Upstream Asyncify functions
===========================
Expand Down
8 changes: 8 additions & 0 deletions src/IDBStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,12 @@ var IDBStore = {
req.onerror = (error) => callback(error);
});
},
clearStore(dbName, callback) {
IDBStore.getStore(dbName, 'readwrite', (err, store) => {
if (err) return callback(err);
var req = store.clear();
req.onsuccess = (event) => callback();
req.onerror = (error) => callback(error);
});
},
};
26 changes: 26 additions & 0 deletions src/library_idbstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ var LibraryIDBStore = {
});
});
},
emscripten_idb_async_clear__deps: ['$UTF8ToString', '$callUserCallback'],
emscripten_idb_async_clear: (db, arg, onclear, onerror) => {
{{{ runtimeKeepalivePush() }}};
IDBStore.clearStore(UTF8ToString(db), (error) => {
{{{ runtimeKeepalivePop() }}}
callUserCallback(() => {
if (error) {
if (onerror) {{{ makeDynCall('vp', 'onerror') }}}(arg);
return;
}
if (onclear) {{{ makeDynCall('vp', 'onclear') }}}(arg);
});
});
},

#if ASYNCIFY
emscripten_idb_load__async: true,
Expand Down Expand Up @@ -125,6 +139,15 @@ var LibraryIDBStore = {
});
});
},
emscripten_idb_clear__async: true,
emscripten_idb_clear: (db, perror) => {
return Asyncify.handleSleep((wakeUp) => {
IDBStore.clearStore(UTF8ToString(db), (error) => {
{{{ makeSetValue('perror', 0, '!!error', 'i32') }}};
wakeUp();
});
});
},
// extra worker methods - proxied
emscripten_idb_load_blob__async: true,
emscripten_idb_load_blob: (db, id, pblob, perror) => {
Expand Down Expand Up @@ -195,6 +218,9 @@ var LibraryIDBStore = {
emscripten_idb_exists: (db, id, pexists, perror) => {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_exists, etc.';
},
emscripten_idb_clear: (db, perror) => {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_clear, etc.';
},
#endif // ASYNCIFY
};

Expand Down
2 changes: 2 additions & 0 deletions src/library_sigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -650,10 +650,12 @@ sigs = {
emscripten_has_threading_support__sig: 'i',
emscripten_hide_mouse__sig: 'v',
emscripten_html5_remove_all_event_listeners__sig: 'v',
emscripten_idb_async_clear__sig: 'vpppp',
emscripten_idb_async_delete__sig: 'vppppp',
emscripten_idb_async_exists__sig: 'vppppp',
emscripten_idb_async_load__sig: 'vppppp',
emscripten_idb_async_store__sig: 'vpppippp',
emscripten_idb_clear__sig: 'vpp',
emscripten_idb_delete__sig: 'vppp',
emscripten_idb_exists__sig: 'vpppp',
emscripten_idb_load__sig: 'vppppp',
Expand Down
2 changes: 2 additions & 0 deletions system/include/emscripten/emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,15 @@ void emscripten_idb_async_store(const char *db_name __attribute__((nonnull)), co
void emscripten_idb_async_delete(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* arg, em_arg_callback_func ondelete, em_arg_callback_func onerror);
typedef void (*em_idb_exists_func)(void*, int);
void emscripten_idb_async_exists(const char *db_name __attribute__((nonnull)), const char *file_id __attribute__((nonnull)), void* arg, em_idb_exists_func oncheck, em_arg_callback_func onerror);
void emscripten_idb_async_clear(const char *db_name __attribute__((nonnull)), void* arg, em_arg_callback_func onclear, em_arg_callback_func onerror);

// IDB "sync"

void emscripten_idb_load(const char *db_name, const char *file_id, void** pbuffer, int* pnum, int *perror);
void emscripten_idb_store(const char *db_name, const char *file_id, void* buffer, int num, int *perror);
void emscripten_idb_delete(const char *db_name, const char *file_id, int *perror);
void emscripten_idb_exists(const char *db_name, const char *file_id, int* pexists, int *perror);
void emscripten_idb_clear(const char *db_name, int *perror);

void emscripten_idb_load_blob(const char *db_name, const char *file_id, int* pblob, int *perror);
void emscripten_idb_store_blob(const char *db_name, const char *file_id, void* buffer, int num, int *perror);
Expand Down
4 changes: 4 additions & 0 deletions test/browser/test_idbstore.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ int main() {
#elif STAGE == 5
expected = 77;
emscripten_idb_async_exists(DB, "the_secret", (void*)expected, onchecknope, onerror);
#elif STAGE == 6
expected = 88;
printf("clearing\n");
emscripten_idb_async_clear(DB, (void*)expected, ok, onerror);
#else
assert(0);
#endif
Expand Down
10 changes: 10 additions & 0 deletions test/browser/test_idbstore_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ void test() {
assert(error); // expected error!
sum++;

printf("storing %s again\n", SECRET);
emscripten_idb_store(DB, "the_secret", SECRET, strlen(SECRET)+1, &error);
assert(!error);
sum++;

printf("clearing the store\n");
emscripten_idb_clear(DB, &error);
assert(!error);
sum++;

printf("last checking\n");
emscripten_idb_exists(DB, "the_secret", &exists, &error);
assert(!error);
Expand Down
12 changes: 11 additions & 1 deletion test/browser/test_idbstore_sync_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ int main() {
assert(error); // expected error!
sum++;

printf("storing %s again\n", SECRET);
emscripten_idb_store(DB, "the_secret", SECRET, strlen(SECRET)+1, &error);
assert(!error);
sum++;

printf("clearing the store\n");
emscripten_idb_clear(DB, &error);
assert(!error);
sum++;

printf("last checking\n");
emscripten_idb_exists(DB, "the_secret", &exists, &error);
assert(!error);
Expand Down Expand Up @@ -93,7 +103,7 @@ int main() {

// finish up

assert(sum == 6);
assert(sum == 8);
REPORT_RESULT(0);
return 0;
}
4 changes: 2 additions & 2 deletions test/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ def test_separate_metadata_later(self):
@also_with_wasm64
def test_idbstore(self):
secret = str(time.time())
for stage in [0, 1, 2, 3, 0, 1, 2, 0, 0, 1, 4, 2, 5]:
for stage in [0, 1, 2, 3, 0, 1, 2, 0, 0, 1, 4, 2, 5, 0, 4, 6, 5]:
print(stage)
self.btest_exit('test_idbstore.c',
args=['-lidbstore.js', f'-DSTAGE={stage}', f'-DSECRET="{secret}"'],
Expand All @@ -1524,7 +1524,7 @@ def test_idbstore_sync(self, asyncify, wasm64):
if asyncify == 2:
self.require_jspi()
secret = str(time.time())
self.btest('test_idbstore_sync.c', '6', args=['-lidbstore.js', f'-DSECRET="{secret}"', '-O3', '-g2', '-sASYNCIFY=' + str(asyncify)])
self.btest('test_idbstore_sync.c', '8', args=['-lidbstore.js', f'-DSECRET="{secret}"', '-O3', '-g2', '-sASYNCIFY=' + str(asyncify)])

def test_idbstore_sync_worker(self):
secret = str(time.time())
Expand Down

0 comments on commit 104e3de

Please sign in to comment.