1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 17:27:35 +00:00

Browser: Synchronize database statements used for cookies

Since SQLServer is inherently asynchronous, database statements can run
in parallel. Our `CookieJar` did not require synchronous actions on the
database for its cookies, resulting in cookies not being set
immediately. This resulted in a bug that could be exposed by setting
`document.cookie` and immediately querying its value, revealing that the
cookie was not yet persisted.

Solve this by requiring all database statements to be executed
synchronously. Ideally SQLServer has a mechanism to determine interquery
dependencies and blocks until dependent queries are fully executed, but
until we have that, this works around that limitation.
This commit is contained in:
Jelle Raaijmakers 2023-08-07 23:33:01 +02:00 committed by Tim Flynn
parent 568c486610
commit 14091f32c6
2 changed files with 26 additions and 14 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2023, Jelle Raaijmakers <jelle@gmta.nl>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -14,6 +15,7 @@
#include <AK/RefCounted.h>
#include <AK/StringView.h>
#include <AK/Vector.h>
#include <LibCore/Promise.h>
#include <LibSQL/SQLClient.h>
#include <LibSQL/Type.h>
#include <LibSQL/Value.h>
@ -34,14 +36,24 @@ public:
template<typename... PlaceholderValues>
void execute_statement(SQL::StatementID statement_id, OnResult on_result, OnComplete on_complete, OnError on_error, PlaceholderValues&&... placeholder_values)
{
auto sync_promise = Core::Promise<Empty>::construct();
PendingExecution pending_execution {
.on_result = move(on_result),
.on_complete = move(on_complete),
.on_error = move(on_error),
.on_complete = [sync_promise, on_complete = move(on_complete)] {
if (on_complete)
on_complete();
sync_promise->resolve({}); },
.on_error = [sync_promise, on_error = move(on_error)](auto message) {
if (on_error)
on_error(message);
sync_promise->resolve({}); },
};
Vector<SQL::Value> values { SQL::Value(forward<PlaceholderValues>(placeholder_values))... };
execute_statement(statement_id, move(values), move(pending_execution));
MUST(sync_promise->await());
}
private: