@@ -249,16 +249,19 @@ Local<Array> Storage::Enumerate() { |
249 | 249 | CHECK_ERROR_OR_THROW(env(), r, SQLITE_OK, Local<Array>()); |
250 | 250 | auto stmt = stmt_unique_ptr(s); |
251 | 251 | std::vector<Local<Value>> values; |
| 252 | + Local<Value> value; |
252 | 253 | while ((r = sqlite3_step(stmt.get())) == SQLITE_ROW) { |
253 | 254 | CHECK(sqlite3_column_type(stmt.get(), 0) == SQLITE_BLOB); |
254 | 255 | auto size = sqlite3_column_bytes(stmt.get(), 0) / sizeof(uint16_t); |
255 | | - values.emplace_back( |
256 | | - String::NewFromTwoByte(env()->isolate(), |
257 | | - reinterpret_cast<const uint16_t*>( |
258 | | - sqlite3_column_blob(stmt.get(), 0)), |
259 | | - v8::NewStringType::kNormal, |
260 | | - size) |
261 | | - .ToLocalChecked()); |
| 256 | + if (!String::NewFromTwoByte(env()->isolate(), |
| 257 | + reinterpret_cast<const uint16_t*>( |
| 258 | + sqlite3_column_blob(stmt.get(), 0)), |
| 259 | + v8::NewStringType::kNormal, |
| 260 | + size) |
| 261 | + .ToLocal(&value)) { |
| 262 | + return Local<Array>(); |
| 263 | + } |
| 264 | + values.emplace_back(value); |
262 | 265 | } |
263 | 266 | CHECK_ERROR_OR_THROW(env(), r, SQLITE_DONE, Local<Array>()); |
264 | 267 | return Array::New(env()->isolate(), values.data(), values.size()); |
@@ -308,12 +311,14 @@ Local<Value> Storage::Load(Local<Name> key) { |
308 | 311 | if (r == SQLITE_ROW) { |
309 | 312 | CHECK(sqlite3_column_type(stmt.get(), 0) == SQLITE_BLOB); |
310 | 313 | auto size = sqlite3_column_bytes(stmt.get(), 0) / sizeof(uint16_t); |
311 | | - value = String::NewFromTwoByte(env()->isolate(), |
312 | | - reinterpret_cast<const uint16_t*>( |
313 | | - sqlite3_column_blob(stmt.get(), 0)), |
314 | | - v8::NewStringType::kNormal, |
315 | | - size) |
316 | | - .ToLocalChecked(); |
| 314 | + if (!String::NewFromTwoByte(env()->isolate(), |
| 315 | + reinterpret_cast<const uint16_t*>( |
| 316 | + sqlite3_column_blob(stmt.get(), 0)), |
| 317 | + v8::NewStringType::kNormal, |
| 318 | + size) |
| 319 | + .ToLocal(&value)) { |
| 320 | + return {}; |
| 321 | + } |
317 | 322 | } else if (r != SQLITE_DONE) { |
318 | 323 | THROW_SQLITE_ERROR(env(), r); |
319 | 324 | } |
@@ -323,7 +328,7 @@ Local<Value> Storage::Load(Local<Name> key) { |
323 | 328 |
|
324 | 329 | Local<Value> Storage::LoadKey(const int index) { |
325 | 330 | if (!Open()) { |
326 | | - return Local<Value>(); |
| 331 | + return {}; |
327 | 332 | } |
328 | 333 |
|
329 | 334 | static constexpr std::string_view sql = |
@@ -340,12 +345,14 @@ Local<Value> Storage::LoadKey(const int index) { |
340 | 345 | if (r == SQLITE_ROW) { |
341 | 346 | CHECK(sqlite3_column_type(stmt.get(), 0) == SQLITE_BLOB); |
342 | 347 | auto size = sqlite3_column_bytes(stmt.get(), 0) / sizeof(uint16_t); |
343 | | - value = String::NewFromTwoByte(env()->isolate(), |
344 | | - reinterpret_cast<const uint16_t*>( |
345 | | - sqlite3_column_blob(stmt.get(), 0)), |
346 | | - v8::NewStringType::kNormal, |
347 | | - size) |
348 | | - .ToLocalChecked(); |
| 348 | + if (!String::NewFromTwoByte(env()->isolate(), |
| 349 | + reinterpret_cast<const uint16_t*>( |
| 350 | + sqlite3_column_blob(stmt.get(), 0)), |
| 351 | + v8::NewStringType::kNormal, |
| 352 | + size) |
| 353 | + .ToLocal(&value)) { |
| 354 | + return {}; |
| 355 | + } |
349 | 356 | } else if (r != SQLITE_DONE) { |
350 | 357 | THROW_SQLITE_ERROR(env(), r); |
351 | 358 | } |
@@ -421,10 +428,8 @@ bool Storage::Store(Local<Name> key, Local<Value> value) { |
421 | 428 | return true; |
422 | 429 | } |
423 | 430 |
|
424 | | -static Local<Name> Uint32ToName(Local<Context> context, uint32_t index) { |
425 | | - return Uint32::New(context->GetIsolate(), index) |
426 | | - ->ToString(context) |
427 | | - .ToLocalChecked(); |
| 431 | +static MaybeLocal<String> Uint32ToName(Local<Context> context, uint32_t index) { |
| 432 | + return Uint32::New(context->GetIsolate(), index)->ToString(context); |
428 | 433 | } |
429 | 434 |
|
430 | 435 | static void Clear(const FunctionCallbackInfo<Value>& info) { |
@@ -625,33 +630,68 @@ static Intercepted StorageDefiner(Local<Name> property, |
625 | 630 | static Intercepted IndexedGetter(uint32_t index, |
626 | 631 | const PropertyCallbackInfo<Value>& info) { |
627 | 632 | Environment* env = Environment::GetCurrent(info); |
628 | | - return StorageGetter(Uint32ToName(env->context(), index), info); |
| 633 | + Local<Name> name; |
| 634 | + if (!Uint32ToName(env->context(), index).ToLocal(&name)) { |
| 635 | + // There was an error converting the index to a name. |
| 636 | + // We aren't going to return a result but let's indicate |
| 637 | + // that we intercepted the operation. |
| 638 | + return Intercepted::kYes; |
| 639 | + } |
| 640 | + return StorageGetter(name, info); |
629 | 641 | } |
630 | 642 |
|
631 | 643 | static Intercepted IndexedSetter(uint32_t index, |
632 | 644 | Local<Value> value, |
633 | 645 | const PropertyCallbackInfo<void>& info) { |
634 | 646 | Environment* env = Environment::GetCurrent(info); |
635 | | - return StorageSetter(Uint32ToName(env->context(), index), value, info); |
| 647 | + Local<Name> name; |
| 648 | + if (!Uint32ToName(env->context(), index).ToLocal(&name)) { |
| 649 | + // There was an error converting the index to a name. |
| 650 | + // We aren't going to return a result but let's indicate |
| 651 | + // that we intercepted the operation. |
| 652 | + return Intercepted::kYes; |
| 653 | + } |
| 654 | + return StorageSetter(name, value, info); |
636 | 655 | } |
637 | 656 |
|
638 | 657 | static Intercepted IndexedQuery(uint32_t index, |
639 | 658 | const PropertyCallbackInfo<Integer>& info) { |
640 | 659 | Environment* env = Environment::GetCurrent(info); |
641 | | - return StorageQuery(Uint32ToName(env->context(), index), info); |
| 660 | + Local<Name> name; |
| 661 | + if (!Uint32ToName(env->context(), index).ToLocal(&name)) { |
| 662 | + // There was an error converting the index to a name. |
| 663 | + // We aren't going to return a result but let's indicate |
| 664 | + // that we intercepted the operation. |
| 665 | + return Intercepted::kYes; |
| 666 | + } |
| 667 | + return StorageQuery(name, info); |
642 | 668 | } |
643 | 669 |
|
644 | 670 | static Intercepted IndexedDeleter(uint32_t index, |
645 | 671 | const PropertyCallbackInfo<Boolean>& info) { |
646 | 672 | Environment* env = Environment::GetCurrent(info); |
647 | | - return StorageDeleter(Uint32ToName(env->context(), index), info); |
| 673 | + Local<Name> name; |
| 674 | + if (!Uint32ToName(env->context(), index).ToLocal(&name)) { |
| 675 | + // There was an error converting the index to a name. |
| 676 | + // We aren't going to return a result but let's indicate |
| 677 | + // that we intercepted the operation. |
| 678 | + return Intercepted::kYes; |
| 679 | + } |
| 680 | + return StorageDeleter(name, info); |
648 | 681 | } |
649 | 682 |
|
650 | 683 | static Intercepted IndexedDefiner(uint32_t index, |
651 | 684 | const PropertyDescriptor& desc, |
652 | 685 | const PropertyCallbackInfo<void>& info) { |
653 | 686 | Environment* env = Environment::GetCurrent(info); |
654 | | - return StorageDefiner(Uint32ToName(env->context(), index), desc, info); |
| 687 | + Local<Name> name; |
| 688 | + if (!Uint32ToName(env->context(), index).ToLocal(&name)) { |
| 689 | + // There was an error converting the index to a name. |
| 690 | + // We aren't going to return a result but let's indicate |
| 691 | + // that we intercepted the operation. |
| 692 | + return Intercepted::kYes; |
| 693 | + } |
| 694 | + return StorageDefiner(name, desc, info); |
655 | 695 | } |
656 | 696 |
|
657 | 697 | static void StorageLengthGetter(const FunctionCallbackInfo<Value>& info) { |
|