@@ -471,6 +471,52 @@ void IteratorFunc(const v8::FunctionCallbackInfo<v8::Value>& info) {
471471 info.GetReturnValue ().Set (info.Holder ());
472472}
473473
474+ struct IterateCaptureContext {
475+ int num_cols;
476+ StatementSync* stmt;
477+ };
478+
479+ void StatementSync::IterateNextCallback (const FunctionCallbackInfo<Value>& args) {
480+ Environment* env = Environment::GetCurrent (args);
481+ auto isolate = env->isolate ();
482+ auto context = env->context ();
483+
484+ Local<v8::External> data = Local<v8::External>::Cast (args.Data ());
485+ IterateCaptureContext* captureContext = static_cast <IterateCaptureContext*>(data->Value ());
486+ auto stmt = captureContext->stmt ;
487+ auto num_cols = captureContext->num_cols ;
488+
489+ int r = sqlite3_step (captureContext->stmt ->statement_ );
490+ if (r != SQLITE_ROW) {
491+ CHECK_ERROR_OR_THROW (isolate, captureContext->stmt ->db_ , r, SQLITE_DONE, void ());
492+ Local<Object> result = Object::New (isolate);
493+ result->Set (context, String::NewFromUtf8Literal (isolate, " done" ), v8::Boolean::New (isolate, true )).Check ();
494+ result->Set (context, String::NewFromUtf8Literal (isolate, " value" ), v8::Null (isolate)).Check ();
495+
496+ args.GetReturnValue ().Set (result);
497+ return ;
498+ }
499+
500+ Local<Object> row = Object::New (isolate);
501+
502+ for (int i = 0 ; i < num_cols; ++i) {
503+ Local<Value> key = stmt->ColumnNameToValue (i);
504+ if (key.IsEmpty ()) return ;
505+ Local<Value> val = stmt->ColumnToValue (i);
506+ if (val.IsEmpty ()) return ;
507+
508+ if (row->Set (env->context (), key, val).IsNothing ()) {
509+ return ;
510+ }
511+ }
512+
513+ Local<Object> result = Object::New (isolate);
514+ result->Set (context, String::NewFromUtf8Literal (isolate, " done" ), v8::Boolean::New (isolate, false )).Check ();
515+ result->Set (context, String::NewFromUtf8Literal (isolate, " value" ), row).Check ();
516+
517+ args.GetReturnValue ().Set (result);
518+ }
519+
474520void StatementSync::Iterate (const FunctionCallbackInfo<Value>& args) {
475521 StatementSync* stmt;
476522 ASSIGN_OR_RETURN_UNWRAP (&stmt, args.This ());
@@ -488,55 +534,16 @@ void StatementSync::Iterate(const FunctionCallbackInfo<Value>& args) {
488534
489535 v8::Local<v8::ObjectTemplate> iterableIteratorTemplate = v8::ObjectTemplate::New (isolate);
490536
491- v8::Local<v8::FunctionTemplate> nextFuncTemplate = v8::FunctionTemplate::NewWithCache (
537+ IterateCaptureContext* captureContext = new IterateCaptureContext ();
538+ captureContext->num_cols = sqlite3_column_count (stmt->statement_ );
539+ captureContext->stmt = stmt;
540+ v8::Local<v8::FunctionTemplate> nextFuncTemplate = v8::FunctionTemplate::New (
492541 isolate,
493- [](const v8::FunctionCallbackInfo<v8::Value>& info) {
494- auto cache = info.Data ().As <std::pair<StatementSync*, std::pair<Environment*, int >*>>();
495- auto stmt = cache->first ;
496- auto env = cache->second ->first ;
497- auto num_cols = cache->second ->second ;
498-
499- auto isolate = env->isolate ();
500- auto context = env->context ();
501-
502- int r = sqlite3_step (stmt->statement_ );
503- if (r != SQLITE_ROW) {
504- CHECK_ERROR_OR_THROW (isolate, stmt->db_ , r, SQLITE_DONE, void ());
505- Local<Object> result = Object::New (isolate);
506- result->Set (context, String::NewFromUtf8Literal (isolate, " done" ), v8::Boolean::New (isolate, true )).Check ();
507- result->Set (context, String::NewFromUtf8Literal (isolate, " value" ), v8::Null (isolate)).Check ();
508-
509- info.GetReturnValue ().Set (result);
510- return ;
511- }
512-
513- Local<Object> row = Object::New (isolate);
514-
515- for (int i = 0 ; i < num_cols; ++i) {
516- Local<Value> key = stmt->ColumnNameToValue (i);
517- if (key.IsEmpty ()) return ;
518- Local<Value> val = stmt->ColumnToValue (i);
519- if (val.IsEmpty ()) return ;
520-
521- if (row->Set (env->context (), key, val).IsNothing ()) {
522- return ;
523- }
524- }
525-
526- Local<Object> result = Object::New (isolate);
527- result->Set (context, String::NewFromUtf8Literal (isolate, " done" ), v8::Boolean::New (isolate, false )).Check ();
528- result->Set (context, String::NewFromUtf8Literal (isolate, " value" ), row).Check ();
529-
530- info.GetReturnValue ().Set (result);
531- },
532- v8::External::New (isolate, new std::pair<StatementSync*, std::pair<Environment*, int >*>(
533- stmt,
534- new std::pair<Environment*, int >(env, sqlite3_column_count (stmt->statement_ ))
535- ))
542+ StatementSync::IterateNextCallback,
543+ v8::External::New (isolate, captureContext)
536544 );
537545
538546 v8::Local<v8::FunctionTemplate> iteratorFuncTemplate = v8::FunctionTemplate::New (isolate, IteratorFunc);
539-
540547 iterableIteratorTemplate->Set (String::NewFromUtf8Literal (isolate, " next" ), nextFuncTemplate);
541548 iterableIteratorTemplate->Set (v8::Symbol::GetIterator (isolate), iteratorFuncTemplate->GetFunction (context).ToLocalChecked ());
542549
0 commit comments