@@ -233,6 +233,27 @@ inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, DatabaseSync* db) {
233233 }
234234}
235235
236+ bool DatabaseSync::HasPendingAuthorizerError () const {
237+ return has_pending_authorizer_error_;
238+ }
239+
240+ void DatabaseSync::StoreAuthorizerError (Local<Value> error) {
241+ if (!has_pending_authorizer_error_) {
242+ pending_authorizer_error_.Reset (env ()->isolate (), error);
243+ has_pending_authorizer_error_ = true ;
244+ }
245+ }
246+
247+ void DatabaseSync::RethrowPendingAuthorizerError () {
248+ if (has_pending_authorizer_error_) {
249+ Isolate* isolate = env ()->isolate ();
250+ Local<Value> err = pending_authorizer_error_.Get (isolate);
251+ pending_authorizer_error_.Reset ();
252+ has_pending_authorizer_error_ = false ;
253+ isolate->ThrowException (err);
254+ }
255+ }
256+
236257inline void THROW_ERR_SQLITE_ERROR (Isolate* isolate, const char * message) {
237258 Local<Object> e;
238259 if (CreateSQLiteError (isolate, message).ToLocal (&e)) {
@@ -1126,6 +1147,15 @@ void DatabaseSync::Prepare(const FunctionCallbackInfo<Value>& args) {
11261147 Utf8Value sql (env->isolate (), args[0 ].As <String>());
11271148 sqlite3_stmt* s = nullptr ;
11281149 int r = sqlite3_prepare_v2 (db->connection_ , *sql, -1 , &s, 0 );
1150+
1151+ if (db->HasPendingAuthorizerError ()) {
1152+ db->RethrowPendingAuthorizerError ();
1153+ if (s != nullptr ) {
1154+ sqlite3_finalize (s);
1155+ }
1156+ return ;
1157+ }
1158+
11291159 CHECK_ERROR_OR_THROW (env->isolate (), db, r, SQLITE_OK, void ());
11301160 BaseObjectPtr<StatementSync> stmt =
11311161 StatementSync::Create (env, BaseObjectPtr<DatabaseSync>(db), s);
@@ -1147,6 +1177,10 @@ void DatabaseSync::Exec(const FunctionCallbackInfo<Value>& args) {
11471177
11481178 Utf8Value sql (env->isolate (), args[0 ].As <String>());
11491179 int r = sqlite3_exec (db->connection_ , *sql, nullptr , nullptr , nullptr );
1180+ if (db->HasPendingAuthorizerError ()) {
1181+ db->RethrowPendingAuthorizerError ();
1182+ return ;
1183+ }
11501184 CHECK_ERROR_OR_THROW (env->isolate (), db, r, SQLITE_OK, void ());
11511185}
11521186
@@ -1906,9 +1940,7 @@ int DatabaseSync::AuthorizerCallback(void* user_data,
19061940 Local<Value> cb =
19071941 db->object ()->GetInternalField (kAuthorizerCallback ).template As <Value>();
19081942
1909- if (!cb->IsFunction ()) {
1910- return SQLITE_DENY;
1911- }
1943+ CHECK (cb->IsFunction ());
19121944
19131945 Local<Function> callback = cb.As <Function>();
19141946 LocalVector<Value> js_argv (isolate);
@@ -1929,29 +1961,43 @@ int DatabaseSync::AuthorizerCallback(void* user_data,
19291961 context, Undefined (isolate), js_argv.size (), js_argv.data ());
19301962
19311963 if (try_catch.HasCaught ()) {
1932- // If there's an exception in the callback, deny the operation
1933- // TODO: Rethrow exception
1964+ db->StoreAuthorizerError (try_catch.Exception ());
19341965 return SQLITE_DENY;
19351966 }
19361967
19371968 Local<Value> result;
1938- if (!retval.ToLocal (&result)) {
1969+ if (!retval.ToLocal (&result) || result->IsUndefined () || result->IsNull ()) {
1970+ // Missing return value
1971+ Local<Value> err = Exception::TypeError (
1972+ String::NewFromUtf8 (
1973+ isolate,
1974+ " Authorizer callback must return an integer authorization code" )
1975+ .ToLocalChecked ());
1976+ db->StoreAuthorizerError (err);
19391977 return SQLITE_DENY;
19401978 }
19411979
1942- if (!result->IsNumber ()) {
1980+ if (!result->IsInt32 ()) {
1981+ Local<Value> err = Exception::TypeError (
1982+ String::NewFromUtf8 (
1983+ isolate, " Authorizer callback return value must be an integer" )
1984+ .ToLocalChecked ());
1985+ db->StoreAuthorizerError (err);
19431986 return SQLITE_DENY;
19441987 }
19451988
1946- double num_result = result.As <Number>()->Value ();
1947- int int_result = static_cast <int >(num_result);
1948-
1949- if (int_result == SQLITE_OK || int_result == SQLITE_DENY ||
1950- int_result == SQLITE_IGNORE) {
1951- return int_result;
1989+ int32_t int_result = result.As <Int32>()->Value ();
1990+ if (int_result != SQLITE_OK && int_result != SQLITE_DENY &&
1991+ int_result != SQLITE_IGNORE) {
1992+ Local<Value> err = Exception::RangeError (
1993+ String::NewFromUtf8 (
1994+ isolate, " Authorizer callback returned invalid authorization code" )
1995+ .ToLocalChecked ());
1996+ db->StoreAuthorizerError (err);
1997+ return SQLITE_DENY;
19521998 }
19531999
1954- return SQLITE_DENY ;
2000+ return int_result ;
19552001}
19562002
19572003StatementSync::StatementSync (Environment* env,
0 commit comments