@@ -24,6 +24,7 @@ using v8::BigInt;
2424using v8::Boolean;
2525using v8::ConstructorBehavior;
2626using v8::Context;
27+ using v8::DictionaryTemplate;
2728using v8::DontDelete;
2829using v8::Exception;
2930using v8::Function;
@@ -119,6 +120,18 @@ using v8::Value;
119120 } \
120121 } while (0 )
121122
123+ namespace {
124+ Local<DictionaryTemplate> getLazyIterTemplate (Environment* env) {
125+ auto iter_template = env->iter_template ();
126+ if (iter_template.IsEmpty ()) {
127+ static constexpr std::string_view iter_keys[] = {" done" , " value" };
128+ iter_template = DictionaryTemplate::New (env->isolate (), iter_keys);
129+ env->set_iter_template (iter_template);
130+ }
131+ return iter_template;
132+ }
133+ } // namespace
134+
122135inline MaybeLocal<Object> CreateSQLiteError (Isolate* isolate,
123136 const char * message) {
124137 Local<String> js_msg;
@@ -2231,58 +2244,35 @@ void StatementSync::Columns(const FunctionCallbackInfo<Value>& args) {
22312244 int num_cols = sqlite3_column_count (stmt->statement_ );
22322245 Isolate* isolate = env->isolate ();
22332246 LocalVector<Value> cols (isolate);
2234- LocalVector<Name> col_keys (isolate,
2235- {env-> column_string (),
2236- env-> database_string (),
2237- env-> name_string (),
2238- env-> table_string (),
2239- env->type_string ()} );
2240- Local<Value> value;
2247+ auto sqlite_column_template = env-> sqlite_column_template ();
2248+ if (sqlite_column_template. IsEmpty ()) {
2249+ static constexpr std::string_view col_keys[] = {
2250+ " column " , " database " , " name " , " table " , " type " };
2251+ sqlite_column_template = DictionaryTemplate::New (isolate, col_keys);
2252+ env->set_sqlite_column_template (sqlite_column_template );
2253+ }
22412254
22422255 cols.reserve (num_cols);
22432256 for (int i = 0 ; i < num_cols; ++i) {
2244- LocalVector<Value> col_values (isolate);
2245- col_values.reserve (col_keys.size ());
2246-
2247- if (!NullableSQLiteStringToValue (
2248- isolate, sqlite3_column_origin_name (stmt->statement_ , i))
2249- .ToLocal (&value)) {
2250- return ;
2251- }
2252- col_values.emplace_back (value);
2253-
2254- if (!NullableSQLiteStringToValue (
2255- isolate, sqlite3_column_database_name (stmt->statement_ , i))
2256- .ToLocal (&value)) {
2257- return ;
2258- }
2259- col_values.emplace_back (value);
2260-
2261- if (!stmt->ColumnNameToName (i).ToLocal (&value)) {
2262- return ;
2263- }
2264- col_values.emplace_back (value);
2265-
2266- if (!NullableSQLiteStringToValue (
2267- isolate, sqlite3_column_table_name (stmt->statement_ , i))
2268- .ToLocal (&value)) {
2269- return ;
2270- }
2271- col_values.emplace_back (value);
2272-
2273- if (!NullableSQLiteStringToValue (
2274- isolate, sqlite3_column_decltype (stmt->statement_ , i))
2275- .ToLocal (&value)) {
2257+ MaybeLocal<Value> values[] = {
2258+ NullableSQLiteStringToValue (
2259+ isolate, sqlite3_column_origin_name (stmt->statement_ , i)),
2260+ NullableSQLiteStringToValue (
2261+ isolate, sqlite3_column_database_name (stmt->statement_ , i)),
2262+ stmt->ColumnNameToName (i),
2263+ NullableSQLiteStringToValue (
2264+ isolate, sqlite3_column_table_name (stmt->statement_ , i)),
2265+ NullableSQLiteStringToValue (
2266+ isolate, sqlite3_column_decltype (stmt->statement_ , i)),
2267+ };
2268+
2269+ Local<Object> col;
2270+ if (!NewDictionaryInstanceNullProto (
2271+ env->context (), sqlite_column_template, values)
2272+ .ToLocal (&col)) {
22762273 return ;
22772274 }
2278- col_values.emplace_back (value);
2279-
2280- Local<Object> column = Object::New (isolate,
2281- Null (isolate),
2282- col_keys.data (),
2283- col_values.data (),
2284- col_keys.size ());
2285- cols.emplace_back (column);
2275+ cols.emplace_back (col);
22862276 }
22872277
22882278 args.GetReturnValue ().Set (Array::New (isolate, cols.data (), cols.size ()));
@@ -2514,15 +2504,19 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
25142504 THROW_AND_RETURN_ON_BAD_STATE (
25152505 env, iter->stmt_ ->IsFinalized (), " statement has been finalized" );
25162506 Isolate* isolate = env->isolate ();
2517- LocalVector<Name> keys (isolate, {env->done_string (), env->value_string ()});
2507+
2508+ auto iter_template = getLazyIterTemplate (env);
25182509
25192510 if (iter->done_ ) {
2520- LocalVector<Value> values (isolate,
2521- {Boolean::New (isolate, true ), Null (isolate)});
2522- DCHECK_EQ (values.size (), keys.size ());
2523- Local<Object> result = Object::New (
2524- isolate, Null (isolate), keys.data (), values.data (), keys.size ());
2525- args.GetReturnValue ().Set (result);
2511+ MaybeLocal<Value> values[]{
2512+ Boolean::New (isolate, true ),
2513+ Null (isolate),
2514+ };
2515+ Local<Object> result;
2516+ if (NewDictionaryInstanceNullProto (env->context (), iter_template, values)
2517+ .ToLocal (&result)) {
2518+ args.GetReturnValue ().Set (result);
2519+ }
25262520 return ;
25272521 }
25282522
@@ -2531,12 +2525,12 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
25312525 CHECK_ERROR_OR_THROW (
25322526 env->isolate (), iter->stmt_ ->db_ .get (), r, SQLITE_DONE, void ());
25332527 sqlite3_reset (iter->stmt_ ->statement_ );
2534- LocalVector <Value> values (isolate,
2535- { Boolean::New (isolate, true ), Null (isolate)}) ;
2536- DCHECK_EQ (values. size ( ), keys. size ());
2537- Local<Object> result = Object::New (
2538- isolate, Null (isolate), keys. data (), values. data (), keys. size () );
2539- args. GetReturnValue (). Set (result);
2528+ MaybeLocal <Value> values[] = { Boolean::New (isolate, true ), Null (isolate)};
2529+ Local<Object> result ;
2530+ if ( NewDictionaryInstanceNullProto (env-> context ( ), iter_template, values)
2531+ . ToLocal (&result)) {
2532+ args. GetReturnValue (). Set (result );
2533+ }
25402534 return ;
25412535 }
25422536
@@ -2564,11 +2558,12 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
25642558 isolate, Null (isolate), row_keys.data (), row_values.data (), num_cols);
25652559 }
25662560
2567- LocalVector<Value> values (isolate, {Boolean::New (isolate, false ), row_value});
2568- DCHECK_EQ (keys.size (), values.size ());
2569- Local<Object> result = Object::New (
2570- isolate, Null (isolate), keys.data (), values.data (), keys.size ());
2571- args.GetReturnValue ().Set (result);
2561+ MaybeLocal<Value> values[] = {Boolean::New (isolate, false ), row_value};
2562+ Local<Object> result;
2563+ if (NewDictionaryInstanceNullProto (env->context (), iter_template, values)
2564+ .ToLocal (&result)) {
2565+ args.GetReturnValue ().Set (result);
2566+ }
25722567}
25732568
25742569void StatementSyncIterator::Return (const FunctionCallbackInfo<Value>& args) {
@@ -2581,14 +2576,15 @@ void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
25812576
25822577 sqlite3_reset (iter->stmt_ ->statement_ );
25832578 iter->done_ = true ;
2584- LocalVector<Name> keys (isolate, {env->done_string (), env->value_string ()});
2585- LocalVector<Value> values (isolate,
2586- {Boolean::New (isolate, true ), Null (isolate)});
25872579
2588- DCHECK_EQ (keys.size (), values.size ());
2589- Local<Object> result = Object::New (
2590- isolate, Null (isolate), keys.data (), values.data (), keys.size ());
2591- args.GetReturnValue ().Set (result);
2580+ auto iter_template = getLazyIterTemplate (env);
2581+ MaybeLocal<Value> values[] = {Boolean::New (isolate, true ), Null (isolate)};
2582+
2583+ Local<Object> result;
2584+ if (NewDictionaryInstanceNullProto (env->context (), iter_template, values)
2585+ .ToLocal (&result)) {
2586+ args.GetReturnValue ().Set (result);
2587+ }
25922588}
25932589
25942590Session::Session (Environment* env,
0 commit comments