@@ -1816,10 +1816,10 @@ void Database::CreateTagStore(const FunctionCallbackInfo<Value>& args) {
18161816// undefined. Returns false if a JavaScript exception is pending, either from
18171817// the property getter or because the value is not a boolean.
18181818template <typename T>
1819- static bool ReadOptionalBool (Environment* env,
1820- Local<Object> options,
1821- const char * key,
1822- T* out) {
1819+ [[nodiscard]] static bool ReadOptionalBool (Environment* env,
1820+ Local<Object> options,
1821+ const char * key,
1822+ T* out) {
18231823 Local<String> key_string =
18241824 OneByteString (env->isolate (), key, -1 , NewStringType::kInternalized );
18251825 Local<Value> value;
@@ -1838,6 +1838,31 @@ static bool ReadOptionalBool(Environment* env,
18381838 return true ;
18391839}
18401840
1841+ // Reads options[key] into *out as a string, leaving *out unchanged if the value
1842+ // is undefined. Returns false if a JavaScript exception is pending, either from
1843+ // the property getter or because the value is not a string.
1844+ [[nodiscard]] static bool ReadOptionalString (Environment* env,
1845+ Local<Object> options,
1846+ const char * key,
1847+ std::string* out) {
1848+ Local<String> key_string =
1849+ OneByteString (env->isolate (), key, -1 , NewStringType::kInternalized );
1850+ Local<Value> value;
1851+ if (!options->Get (env->context (), key_string).ToLocal (&value)) {
1852+ return false ;
1853+ }
1854+ if (value->IsUndefined ()) {
1855+ return true ;
1856+ }
1857+ if (!value->IsString ()) {
1858+ THROW_ERR_INVALID_ARG_TYPE (
1859+ env->isolate (), " The \" options.%s\" argument must be a string." , key);
1860+ return false ;
1861+ }
1862+ *out = Utf8Value (env->isolate (), value.As <String>()).ToString ();
1863+ return true ;
1864+ }
1865+
18411866std::optional<std::string> ValidateDatabasePath (Environment* env,
18421867 Local<Value> path,
18431868 const std::string& field_name) {
@@ -2409,22 +2434,7 @@ void Database::Deserialize(const FunctionCallbackInfo<Value>& args) {
24092434 }
24102435
24112436 Local<Object> options = args[1 ].As <Object>();
2412- Local<String> db_name_key = FIXED_ONE_BYTE_STRING (env->isolate (), " dbName" );
2413- Local<Value> db_name_value;
2414- if (!options->Get (env->context (), db_name_key).ToLocal (&db_name_value)) {
2415- return ;
2416- }
2417-
2418- if (!db_name_value->IsUndefined ()) {
2419- if (!db_name_value->IsString ()) {
2420- THROW_ERR_INVALID_ARG_TYPE (
2421- env->isolate (),
2422- " The \" options.dbName\" argument must be a string." );
2423- return ;
2424- }
2425- db_name =
2426- Utf8Value (env->isolate (), db_name_value.As <String>()).ToString ();
2427- }
2437+ if (!ReadOptionalString (env, options, " dbName" , &db_name)) return ;
24282438 }
24292439
24302440 // Reading the options bag above can run user JavaScript through a property
@@ -2825,46 +2835,8 @@ void Database::CreateSession(const FunctionCallbackInfo<Value>& args) {
28252835 }
28262836
28272837 Local<Object> options = args[0 ].As <Object>();
2828-
2829- Local<String> table_key = env->table_string ();
2830- bool hasIt;
2831- if (!options->HasOwnProperty (env->context (), table_key).To (&hasIt)) {
2832- return ;
2833- }
2834- if (hasIt) {
2835- Local<Value> table_value;
2836- if (!options->Get (env->context (), table_key).ToLocal (&table_value)) {
2837- return ;
2838- }
2839-
2840- if (table_value->IsString ()) {
2841- table = Utf8Value (env->isolate (), table_value).ToString ();
2842- } else {
2843- THROW_ERR_INVALID_ARG_TYPE (
2844- env->isolate (), " The \" options.table\" argument must be a string." );
2845- return ;
2846- }
2847- }
2848-
2849- Local<String> db_key = FIXED_ONE_BYTE_STRING (env->isolate (), " db" );
2850-
2851- if (!options->HasOwnProperty (env->context (), db_key).To (&hasIt)) {
2852- return ;
2853- }
2854- if (hasIt) {
2855- Local<Value> db_value;
2856- if (!options->Get (env->context (), db_key).ToLocal (&db_value)) {
2857- // An error will have been scheduled.
2858- return ;
2859- }
2860- if (db_value->IsString ()) {
2861- db_name = Utf8Value (env->isolate (), db_value).ToString ();
2862- } else {
2863- THROW_ERR_INVALID_ARG_TYPE (
2864- env->isolate (), " The \" options.db\" argument must be a string." );
2865- return ;
2866- }
2867- }
2838+ if (!ReadOptionalString (env, options, " table" , &table)) return ;
2839+ if (!ReadOptionalString (env, options, " db" , &db_name)) return ;
28682840 }
28692841
28702842 // Reading the options bag above can run user JavaScript through a property
@@ -2942,39 +2914,8 @@ void Backup(const FunctionCallbackInfo<Value>& args) {
29422914 }
29432915 }
29442916
2945- Local<Value> source_v;
2946- if (!options->Get (env->context (), env->source_string ())
2947- .ToLocal (&source_v)) {
2948- return ;
2949- }
2950-
2951- if (!source_v->IsUndefined ()) {
2952- if (!source_v->IsString ()) {
2953- THROW_ERR_INVALID_ARG_TYPE (
2954- env->isolate (),
2955- " The \" options.source\" argument must be a string." );
2956- return ;
2957- }
2958-
2959- source_db = Utf8Value (env->isolate (), source_v.As <String>()).ToString ();
2960- }
2961-
2962- Local<Value> target_v;
2963- if (!options->Get (env->context (), env->target_string ())
2964- .ToLocal (&target_v)) {
2965- return ;
2966- }
2967-
2968- if (!target_v->IsUndefined ()) {
2969- if (!target_v->IsString ()) {
2970- THROW_ERR_INVALID_ARG_TYPE (
2971- env->isolate (),
2972- " The \" options.target\" argument must be a string." );
2973- return ;
2974- }
2975-
2976- dest_db = Utf8Value (env->isolate (), target_v.As <String>()).ToString ();
2977- }
2917+ if (!ReadOptionalString (env, options, " source" , &source_db)) return ;
2918+ if (!ReadOptionalString (env, options, " target" , &dest_db)) return ;
29782919
29792920 Local<Value> progress_v;
29802921 if (!options->Get (env->context (), env->progress_string ())
0 commit comments