@@ -82,6 +82,23 @@ inline MaybeLocal<String> Utf8StringMaybeOneByte(Isolate* isolate,
8282 isolate, input.data (), NewStringType::kNormal , len);
8383}
8484
85+ static inline void SetSideEffectFreeGetter (
86+ Isolate* isolate,
87+ Local<FunctionTemplate> class_template,
88+ Local<String> name,
89+ FunctionCallback fn) {
90+ Local<FunctionTemplate> getter =
91+ FunctionTemplate::New (isolate,
92+ fn,
93+ Local<Value>(),
94+ v8::Signature::New (isolate, class_template),
95+ /* length */ 0 ,
96+ ConstructorBehavior::kThrow ,
97+ SideEffectType::kHasNoSideEffect );
98+ class_template->InstanceTemplate ()->SetAccessorProperty (
99+ name, getter, Local<FunctionTemplate>(), DontDelete);
100+ }
101+
85102BindingData::BindingData (Realm* realm, Local<Object> wrap)
86103 : BaseObject(realm, wrap) {
87104 MakeWeak ();
@@ -1279,11 +1296,17 @@ std::optional<std::string> ValidateDatabasePath(Environment* env,
12791296 } else if (path->IsObject ()) { // When is URL
12801297 auto url = path.As <Object>();
12811298 Local<Value> href;
1282- if (url->Get (env->context (), env->href_string ()).ToLocal (&href) &&
1283- href->IsString ()) {
1299+ // Let an exception thrown by the href getter propagate instead of
1300+ // replacing it with ERR_INVALID_ARG_TYPE.
1301+ if (!url->Get (env->context (), env->href_string ()).ToLocal (&href)) {
1302+ return std::nullopt ;
1303+ }
1304+ if (href->IsString ()) {
12841305 Utf8Value location_value (env->isolate (), href.As <String>());
12851306 auto location = location_value.ToStringView ();
12861307 if (!has_null_bytes (location)) {
1308+ // A real URL always has a parseable href, but any object with a string
1309+ // href reaches this branch, so the value cannot be assumed to be one.
12871310 if (!ada::can_parse (location)) {
12881311 THROW_ERR_INVALID_URL (env->isolate (), " Invalid URL" );
12891312 return std::nullopt ;
@@ -1306,6 +1329,62 @@ std::optional<std::string> ValidateDatabasePath(Environment* env,
13061329 return std::nullopt ;
13071330}
13081331
1332+ Local<FunctionTemplate> DatabaseSync::GetConstructorTemplate (Environment* env) {
1333+ Local<FunctionTemplate> tmpl =
1334+ env->sqlite_database_sync_constructor_template ();
1335+ if (tmpl.IsEmpty ()) {
1336+ Isolate* isolate = env->isolate ();
1337+ tmpl = NewFunctionTemplate (isolate, DatabaseSync::New);
1338+ tmpl->InstanceTemplate ()->SetInternalFieldCount (
1339+ DatabaseSync::kInternalFieldCount );
1340+ SetProtoMethod (isolate, tmpl, " open" , DatabaseSync::Open);
1341+ SetProtoMethod (isolate, tmpl, " close" , DatabaseSync::Close);
1342+ SetProtoDispose (isolate, tmpl, DatabaseSync::Dispose);
1343+ SetProtoMethod (isolate, tmpl, " prepare" , DatabaseSync::Prepare);
1344+ SetProtoMethod (isolate, tmpl, " exec" , DatabaseSync::Exec);
1345+ SetProtoMethod (isolate, tmpl, " function" , DatabaseSync::CustomFunction);
1346+ SetProtoMethod (
1347+ isolate, tmpl, " createTagStore" , DatabaseSync::CreateTagStore);
1348+ SetProtoMethodNoSideEffect (
1349+ isolate, tmpl, " location" , DatabaseSync::Location);
1350+ SetProtoMethod (isolate, tmpl, " aggregate" , DatabaseSync::AggregateFunction);
1351+ SetProtoMethod (isolate, tmpl, " createSession" , DatabaseSync::CreateSession);
1352+ SetProtoMethod (
1353+ isolate, tmpl, " applyChangeset" , DatabaseSync::ApplyChangeset);
1354+ SetProtoMethod (isolate,
1355+ tmpl,
1356+ " enableLoadExtension" ,
1357+ DatabaseSync::EnableLoadExtension);
1358+ SetProtoMethod (
1359+ isolate, tmpl, " enableDefensive" , DatabaseSync::EnableDefensive);
1360+ SetProtoMethod (isolate, tmpl, " loadExtension" , DatabaseSync::LoadExtension);
1361+ SetProtoMethod (isolate, tmpl, " serialize" , DatabaseSync::Serialize);
1362+ SetProtoMethod (isolate, tmpl, " deserialize" , DatabaseSync::Deserialize);
1363+ SetProtoMethod (isolate, tmpl, " setAuthorizer" , DatabaseSync::SetAuthorizer);
1364+ SetSideEffectFreeGetter (isolate,
1365+ tmpl,
1366+ FIXED_ONE_BYTE_STRING (isolate, " isOpen" ),
1367+ DatabaseSync::IsOpenGetter);
1368+ SetSideEffectFreeGetter (isolate,
1369+ tmpl,
1370+ FIXED_ONE_BYTE_STRING (isolate, " isTransaction" ),
1371+ DatabaseSync::IsTransactionGetter);
1372+ SetSideEffectFreeGetter (isolate,
1373+ tmpl,
1374+ FIXED_ONE_BYTE_STRING (isolate, " limits" ),
1375+ DatabaseSync::LimitsGetter);
1376+ Local<String> sqlite_type_key =
1377+ FIXED_ONE_BYTE_STRING (isolate, " sqlite-type" );
1378+ Local<v8::Symbol> sqlite_type_symbol =
1379+ v8::Symbol::For (isolate, sqlite_type_key);
1380+ Local<String> database_sync_string =
1381+ FIXED_ONE_BYTE_STRING (isolate, " node:sqlite" );
1382+ tmpl->InstanceTemplate ()->Set (sqlite_type_symbol, database_sync_string);
1383+ env->set_sqlite_database_sync_constructor_template (tmpl);
1384+ }
1385+ return tmpl;
1386+ }
1387+
13091388void DatabaseSync::New (const FunctionCallbackInfo<Value>& args) {
13101389 Environment* env = Environment::GetCurrent (args);
13111390 if (!args.IsConstructCall ()) {
@@ -2422,16 +2501,13 @@ void DatabaseSync::CreateSession(const FunctionCallbackInfo<Value>& args) {
24222501
24232502void Backup (const FunctionCallbackInfo<Value>& args) {
24242503 Environment* env = Environment::GetCurrent (args);
2425- if (args.Length () < 1 || !args[0 ]->IsObject ()) {
2426- THROW_ERR_INVALID_ARG_TYPE (env->isolate (),
2427- " The \" sourceDb\" argument must be an object." );
2428- return ;
2429- }
2430-
2431- if (!env->sqlite_database_sync_constructor_template ()->HasInstance (args[0 ])) {
2504+ // Unlike the other unwrap sites in this file, which rely on V8's signature
2505+ // check for args.This(), this one takes a value out of args[] and so has to
2506+ // check the type itself before unwrapping it.
2507+ if (!DatabaseSync::GetConstructorTemplate (env)->HasInstance (args[0 ])) {
24322508 THROW_ERR_INVALID_ARG_TYPE (
24332509 env->isolate (),
2434- " The \" sourceDb\" argument must be a DatabaseSync instance." );
2510+ " The \" sourceDb\" argument must be an instance of DatabaseSync ." );
24352511 return ;
24362512 }
24372513
@@ -3821,23 +3897,6 @@ SQLTagStore::SQLTagStore(Environment* env,
38213897 MakeWeak ();
38223898}
38233899
3824- static inline void SetSideEffectFreeGetter (
3825- Isolate* isolate,
3826- Local<FunctionTemplate> class_template,
3827- Local<String> name,
3828- FunctionCallback fn) {
3829- Local<FunctionTemplate> getter =
3830- FunctionTemplate::New (isolate,
3831- fn,
3832- Local<Value>(),
3833- v8::Signature::New (isolate, class_template),
3834- /* length */ 0 ,
3835- ConstructorBehavior::kThrow ,
3836- SideEffectType::kHasNoSideEffect );
3837- class_template->InstanceTemplate ()->SetAccessorProperty (
3838- name, getter, Local<FunctionTemplate>(), DontDelete);
3839- }
3840-
38413900SQLTagStore::~SQLTagStore () {}
38423901
38433902Local<FunctionTemplate> SQLTagStore::GetConstructorTemplate (Environment* env) {
@@ -4579,63 +4638,14 @@ static void Initialize(Local<Object> target,
45794638 }
45804639 });
45814640 }
4582- Local<FunctionTemplate> db_tmpl =
4583- NewFunctionTemplate (isolate, DatabaseSync::New);
4584- db_tmpl->InstanceTemplate ()->SetInternalFieldCount (
4585- DatabaseSync::kInternalFieldCount );
4586- env->set_sqlite_database_sync_constructor_template (db_tmpl);
45874641 Local<Object> constants = Object::New (isolate);
45884642
45894643 DefineConstants (constants);
45904644
4591- SetProtoMethod (isolate, db_tmpl, " open" , DatabaseSync::Open);
4592- SetProtoMethod (isolate, db_tmpl, " close" , DatabaseSync::Close);
4593- SetProtoDispose (isolate, db_tmpl, DatabaseSync::Dispose);
4594- SetProtoMethod (isolate, db_tmpl, " prepare" , DatabaseSync::Prepare);
4595- SetProtoMethod (isolate, db_tmpl, " exec" , DatabaseSync::Exec);
4596- SetProtoMethod (isolate, db_tmpl, " function" , DatabaseSync::CustomFunction);
4597- SetProtoMethod (
4598- isolate, db_tmpl, " createTagStore" , DatabaseSync::CreateTagStore);
4599- SetProtoMethodNoSideEffect (
4600- isolate, db_tmpl, " location" , DatabaseSync::Location);
4601- SetProtoMethod (
4602- isolate, db_tmpl, " aggregate" , DatabaseSync::AggregateFunction);
4603- SetProtoMethod (
4604- isolate, db_tmpl, " createSession" , DatabaseSync::CreateSession);
4605- SetProtoMethod (
4606- isolate, db_tmpl, " applyChangeset" , DatabaseSync::ApplyChangeset);
4607- SetProtoMethod (isolate,
4608- db_tmpl,
4609- " enableLoadExtension" ,
4610- DatabaseSync::EnableLoadExtension);
4611- SetProtoMethod (
4612- isolate, db_tmpl, " enableDefensive" , DatabaseSync::EnableDefensive);
4613- SetProtoMethod (
4614- isolate, db_tmpl, " loadExtension" , DatabaseSync::LoadExtension);
4615- SetProtoMethod (isolate, db_tmpl, " serialize" , DatabaseSync::Serialize);
4616- SetProtoMethod (isolate, db_tmpl, " deserialize" , DatabaseSync::Deserialize);
4617- SetProtoMethod (
4618- isolate, db_tmpl, " setAuthorizer" , DatabaseSync::SetAuthorizer);
4619- SetSideEffectFreeGetter (isolate,
4620- db_tmpl,
4621- FIXED_ONE_BYTE_STRING (isolate, " isOpen" ),
4622- DatabaseSync::IsOpenGetter);
4623- SetSideEffectFreeGetter (isolate,
4624- db_tmpl,
4625- FIXED_ONE_BYTE_STRING (isolate, " isTransaction" ),
4626- DatabaseSync::IsTransactionGetter);
4627- SetSideEffectFreeGetter (isolate,
4628- db_tmpl,
4629- FIXED_ONE_BYTE_STRING (isolate, " limits" ),
4630- DatabaseSync::LimitsGetter);
4631- Local<String> sqlite_type_key = FIXED_ONE_BYTE_STRING (isolate, " sqlite-type" );
4632- Local<v8::Symbol> sqlite_type_symbol =
4633- v8::Symbol::For (isolate, sqlite_type_key);
4634- Local<String> database_sync_string =
4635- FIXED_ONE_BYTE_STRING (isolate, " node:sqlite" );
4636- db_tmpl->InstanceTemplate ()->Set (sqlite_type_symbol, database_sync_string);
4637-
4638- SetConstructorFunction (context, target, " DatabaseSync" , db_tmpl);
4645+ SetConstructorFunction (context,
4646+ target,
4647+ " DatabaseSync" ,
4648+ DatabaseSync::GetConstructorTemplate (env));
46394649 SetConstructorFunction (context,
46404650 target,
46414651 " StatementSync" ,
0 commit comments