Skip to content

Commit f63cba7

Browse files
committed
sqlite: store callback in internal field
1 parent 3662e71 commit f63cba7

File tree

2 files changed

+72
-83
lines changed

2 files changed

+72
-83
lines changed

src/node_sqlite.cc

Lines changed: 61 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -664,66 +664,6 @@ void UserDefinedFunction::xDestroy(void* self) {
664664
delete static_cast<UserDefinedFunction*>(self);
665665
}
666666

667-
AuthorizerFunction::AuthorizerFunction(Environment* env,
668-
Local<Function> fn,
669-
DatabaseSync* db)
670-
: env_(env), fn_(env->isolate(), fn), db_(db) {}
671-
672-
AuthorizerFunction::~AuthorizerFunction() {}
673-
674-
int AuthorizerFunction::xAuthorizer(void* user_data,
675-
int action_code,
676-
const char* param1,
677-
const char* param2,
678-
const char* param3,
679-
const char* param4) {
680-
AuthorizerFunction* self = static_cast<AuthorizerFunction*>(user_data);
681-
Environment* env = self->env_;
682-
Isolate* isolate = env->isolate();
683-
HandleScope handle_scope(isolate);
684-
Local<Context> context = env->context();
685-
686-
auto fn = self->fn_.Get(isolate);
687-
LocalVector<Value> js_argv(isolate);
688-
689-
// Convert SQLite authorizer parameters to JavaScript values
690-
js_argv.emplace_back(Integer::New(isolate, action_code));
691-
js_argv.emplace_back(
692-
NullableSQLiteStringToValue(isolate, param1).ToLocalChecked());
693-
js_argv.emplace_back(
694-
NullableSQLiteStringToValue(isolate, param2).ToLocalChecked());
695-
js_argv.emplace_back(
696-
NullableSQLiteStringToValue(isolate, param3).ToLocalChecked());
697-
js_argv.emplace_back(
698-
NullableSQLiteStringToValue(isolate, param4).ToLocalChecked());
699-
700-
TryCatch try_catch(isolate);
701-
MaybeLocal<Value> retval =
702-
fn->Call(context, Undefined(isolate), js_argv.size(), js_argv.data());
703-
704-
if (try_catch.HasCaught()) {
705-
// If there's an exception in the callback, deny the operation
706-
return SQLITE_DENY;
707-
}
708-
709-
Local<Value> result;
710-
if (!retval.ToLocal(&result)) {
711-
return SQLITE_DENY;
712-
}
713-
714-
if (result->IsNumber()) {
715-
double num_result = result.As<Number>()->Value();
716-
return static_cast<int>(num_result);
717-
}
718-
719-
// Default to OK if the result isn't a number
720-
return SQLITE_OK;
721-
}
722-
723-
void AuthorizerFunction::xDestroy(void* self) {
724-
delete static_cast<AuthorizerFunction*>(self);
725-
}
726-
727667
DatabaseSync::DatabaseSync(Environment* env,
728668
Local<Object> object,
729669
DatabaseOpenConfiguration&& open_config,
@@ -1929,6 +1869,7 @@ void DatabaseSync::SetAuthorizer(const FunctionCallbackInfo<Value>& args) {
19291869
if (args[0]->IsNull()) {
19301870
// Clear the authorizer
19311871
sqlite3_set_authorizer(db->connection_, nullptr, nullptr);
1872+
db->object()->SetInternalField(kAuthorizerCallback, Null(isolate));
19321873
return;
19331874
}
19341875

@@ -1939,17 +1880,74 @@ void DatabaseSync::SetAuthorizer(const FunctionCallbackInfo<Value>& args) {
19391880
}
19401881

19411882
Local<Function> fn = args[0].As<Function>();
1942-
AuthorizerFunction* user_data = new AuthorizerFunction(env, fn, db);
1883+
1884+
db->object()->SetInternalField(kAuthorizerCallback, fn);
19431885

19441886
int r = sqlite3_set_authorizer(
1945-
db->connection_, AuthorizerFunction::xAuthorizer, user_data);
1887+
db->connection_, DatabaseSync::AuthorizerCallback, db);
19461888

19471889
if (r != SQLITE_OK) {
1948-
delete user_data;
19491890
CHECK_ERROR_OR_THROW(isolate, db, r, SQLITE_OK, void());
19501891
}
19511892
}
19521893

1894+
int DatabaseSync::AuthorizerCallback(void* user_data,
1895+
int action_code,
1896+
const char* param1,
1897+
const char* param2,
1898+
const char* param3,
1899+
const char* param4) {
1900+
DatabaseSync* db = static_cast<DatabaseSync*>(user_data);
1901+
Environment* env = db->env();
1902+
Isolate* isolate = env->isolate();
1903+
HandleScope handle_scope(isolate);
1904+
Local<Context> context = env->context();
1905+
1906+
Local<Value> cb =
1907+
db->object()->GetInternalField(kAuthorizerCallback).template As<Value>();
1908+
1909+
if (!cb->IsFunction()) {
1910+
return SQLITE_DENY;
1911+
}
1912+
1913+
Local<Function> callback = cb.As<Function>();
1914+
LocalVector<Value> js_argv(isolate);
1915+
1916+
// Convert SQLite authorizer parameters to JavaScript values
1917+
js_argv.emplace_back(Integer::New(isolate, action_code));
1918+
js_argv.emplace_back(
1919+
NullableSQLiteStringToValue(isolate, param1).ToLocalChecked());
1920+
js_argv.emplace_back(
1921+
NullableSQLiteStringToValue(isolate, param2).ToLocalChecked());
1922+
js_argv.emplace_back(
1923+
NullableSQLiteStringToValue(isolate, param3).ToLocalChecked());
1924+
js_argv.emplace_back(
1925+
NullableSQLiteStringToValue(isolate, param4).ToLocalChecked());
1926+
1927+
TryCatch try_catch(isolate);
1928+
MaybeLocal<Value> retval = callback->Call(
1929+
context, Undefined(isolate), js_argv.size(), js_argv.data());
1930+
1931+
if (try_catch.HasCaught()) {
1932+
// If there's an exception in the callback, deny the operation
1933+
// TODO: Rethrow exepction
1934+
return SQLITE_DENY;
1935+
}
1936+
1937+
Local<Value> result;
1938+
if (!retval.ToLocal(&result)) {
1939+
return SQLITE_DENY;
1940+
}
1941+
1942+
if (result->IsNumber()) {
1943+
double num_result = result.As<Number>()->Value();
1944+
return static_cast<int>(num_result);
1945+
}
1946+
1947+
// Default to OK if the result isn't a number
1948+
return SQLITE_OK;
1949+
}
1950+
19531951
StatementSync::StatementSync(Environment* env,
19541952
Local<Object> object,
19551953
BaseObjectPtr<DatabaseSync> db,

src/node_sqlite.h

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ class StatementExecutionHelper {
111111

112112
class DatabaseSync : public BaseObject {
113113
public:
114+
enum InternalFields {
115+
kAuthorizerCallback = BaseObject::kInternalFieldCount,
116+
kInternalFieldCount
117+
};
118+
114119
DatabaseSync(Environment* env,
115120
v8::Local<v8::Object> object,
116121
DatabaseOpenConfiguration&& open_config,
@@ -137,6 +142,12 @@ class DatabaseSync : public BaseObject {
137142
const v8::FunctionCallbackInfo<v8::Value>& args);
138143
static void LoadExtension(const v8::FunctionCallbackInfo<v8::Value>& args);
139144
static void SetAuthorizer(const v8::FunctionCallbackInfo<v8::Value>& args);
145+
static int AuthorizerCallback(void* user_data,
146+
int action_code,
147+
const char* param1,
148+
const char* param2,
149+
const char* param3,
150+
const char* param4);
140151
void FinalizeStatements();
141152
void RemoveBackup(BackupJob* backup);
142153
void AddBackup(BackupJob* backup);
@@ -318,26 +329,6 @@ class SQLTagStore : public BaseObject {
318329
friend class StatementExecutionHelper;
319330
};
320331

321-
class AuthorizerFunction {
322-
public:
323-
AuthorizerFunction(Environment* env,
324-
v8::Local<v8::Function> fn,
325-
DatabaseSync* db);
326-
~AuthorizerFunction();
327-
static int xAuthorizer(void* user_data,
328-
int action_code,
329-
const char* param1,
330-
const char* param2,
331-
const char* param3,
332-
const char* param4);
333-
static void xDestroy(void* self);
334-
335-
private:
336-
Environment* env_;
337-
v8::Global<v8::Function> fn_;
338-
DatabaseSync* db_;
339-
};
340-
341332
class UserDefinedFunction {
342333
public:
343334
UserDefinedFunction(Environment* env,

0 commit comments

Comments
 (0)