Skip to content
60 changes: 12 additions & 48 deletions src/env_properties.h

Large diffs are not rendered by default.

140 changes: 68 additions & 72 deletions src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ using v8::BigInt;
using v8::Boolean;
using v8::ConstructorBehavior;
using v8::Context;
using v8::DictionaryTemplate;
using v8::DontDelete;
using v8::Exception;
using v8::Function;
Expand Down Expand Up @@ -119,6 +120,18 @@ using v8::Value;
} \
} while (0)

namespace {
Local<DictionaryTemplate> getLazyIterTemplate(Environment* env) {
auto iter_template = env->iter_template();
if (iter_template.IsEmpty()) {
static constexpr std::string_view iter_keys[] = {"done", "value"};
iter_template = DictionaryTemplate::New(env->isolate(), iter_keys);
env->set_iter_template(iter_template);
}
return iter_template;
}
} // namespace

inline MaybeLocal<Object> CreateSQLiteError(Isolate* isolate,
const char* message) {
Local<String> js_msg;
Expand Down Expand Up @@ -2239,58 +2252,35 @@ void StatementSync::Columns(const FunctionCallbackInfo<Value>& args) {
int num_cols = sqlite3_column_count(stmt->statement_);
Isolate* isolate = env->isolate();
LocalVector<Value> cols(isolate);
LocalVector<Name> col_keys(isolate,
{env->column_string(),
env->database_string(),
env->name_string(),
env->table_string(),
env->type_string()});
Local<Value> value;
auto sqlite_column_template = env->sqlite_column_template();
if (sqlite_column_template.IsEmpty()) {
static constexpr std::string_view col_keys[] = {
"column", "database", "name", "table", "type"};
sqlite_column_template = DictionaryTemplate::New(isolate, col_keys);
env->set_sqlite_column_template(sqlite_column_template);
}

cols.reserve(num_cols);
for (int i = 0; i < num_cols; ++i) {
LocalVector<Value> col_values(isolate);
col_values.reserve(col_keys.size());

if (!NullableSQLiteStringToValue(
isolate, sqlite3_column_origin_name(stmt->statement_, i))
.ToLocal(&value)) {
return;
}
col_values.emplace_back(value);

if (!NullableSQLiteStringToValue(
isolate, sqlite3_column_database_name(stmt->statement_, i))
.ToLocal(&value)) {
return;
}
col_values.emplace_back(value);

if (!stmt->ColumnNameToName(i).ToLocal(&value)) {
return;
}
col_values.emplace_back(value);

if (!NullableSQLiteStringToValue(
isolate, sqlite3_column_table_name(stmt->statement_, i))
.ToLocal(&value)) {
return;
}
col_values.emplace_back(value);

if (!NullableSQLiteStringToValue(
isolate, sqlite3_column_decltype(stmt->statement_, i))
.ToLocal(&value)) {
MaybeLocal<Value> values[] = {
NullableSQLiteStringToValue(
isolate, sqlite3_column_origin_name(stmt->statement_, i)),
NullableSQLiteStringToValue(
isolate, sqlite3_column_database_name(stmt->statement_, i)),
stmt->ColumnNameToName(i),
NullableSQLiteStringToValue(
isolate, sqlite3_column_table_name(stmt->statement_, i)),
NullableSQLiteStringToValue(
isolate, sqlite3_column_decltype(stmt->statement_, i)),
};

Local<Object> col;
if (!NewDictionaryInstanceNullProto(
env->context(), sqlite_column_template, values)
.ToLocal(&col)) {
return;
}
col_values.emplace_back(value);

Local<Object> column = Object::New(isolate,
Null(isolate),
col_keys.data(),
col_values.data(),
col_keys.size());
cols.emplace_back(column);
cols.emplace_back(col);
}

args.GetReturnValue().Set(Array::New(isolate, cols.data(), cols.size()));
Expand Down Expand Up @@ -2522,15 +2512,19 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
THROW_AND_RETURN_ON_BAD_STATE(
env, iter->stmt_->IsFinalized(), "statement has been finalized");
Isolate* isolate = env->isolate();
LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()});

auto iter_template = getLazyIterTemplate(env);

if (iter->done_) {
LocalVector<Value> values(isolate,
{Boolean::New(isolate, true), Null(isolate)});
DCHECK_EQ(values.size(), keys.size());
Local<Object> result = Object::New(
isolate, Null(isolate), keys.data(), values.data(), keys.size());
args.GetReturnValue().Set(result);
MaybeLocal<Value> values[]{
Boolean::New(isolate, true),
Null(isolate),
};
Local<Object> result;
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
.ToLocal(&result)) {
args.GetReturnValue().Set(result);
}
return;
}

Expand All @@ -2539,12 +2533,12 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
CHECK_ERROR_OR_THROW(
env->isolate(), iter->stmt_->db_.get(), r, SQLITE_DONE, void());
sqlite3_reset(iter->stmt_->statement_);
LocalVector<Value> values(isolate,
{Boolean::New(isolate, true), Null(isolate)});
DCHECK_EQ(values.size(), keys.size());
Local<Object> result = Object::New(
isolate, Null(isolate), keys.data(), values.data(), keys.size());
args.GetReturnValue().Set(result);
MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};
Local<Object> result;
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
.ToLocal(&result)) {
args.GetReturnValue().Set(result);
}
return;
}

Expand Down Expand Up @@ -2572,11 +2566,12 @@ void StatementSyncIterator::Next(const FunctionCallbackInfo<Value>& args) {
isolate, Null(isolate), row_keys.data(), row_values.data(), num_cols);
}

LocalVector<Value> values(isolate, {Boolean::New(isolate, false), row_value});
DCHECK_EQ(keys.size(), values.size());
Local<Object> result = Object::New(
isolate, Null(isolate), keys.data(), values.data(), keys.size());
args.GetReturnValue().Set(result);
MaybeLocal<Value> values[] = {Boolean::New(isolate, false), row_value};
Local<Object> result;
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
.ToLocal(&result)) {
args.GetReturnValue().Set(result);
}
}

void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {
Expand All @@ -2589,14 +2584,15 @@ void StatementSyncIterator::Return(const FunctionCallbackInfo<Value>& args) {

sqlite3_reset(iter->stmt_->statement_);
iter->done_ = true;
LocalVector<Name> keys(isolate, {env->done_string(), env->value_string()});
LocalVector<Value> values(isolate,
{Boolean::New(isolate, true), Null(isolate)});

DCHECK_EQ(keys.size(), values.size());
Local<Object> result = Object::New(
isolate, Null(isolate), keys.data(), values.data(), keys.size());
args.GetReturnValue().Set(result);
auto iter_template = getLazyIterTemplate(env);
MaybeLocal<Value> values[] = {Boolean::New(isolate, true), Null(isolate)};

Local<Object> result;
if (NewDictionaryInstanceNullProto(env->context(), iter_template, values)
.ToLocal(&result)) {
args.GetReturnValue().Set(result);
}
}

Session::Session(Environment* env,
Expand Down
93 changes: 43 additions & 50 deletions src/node_url_pattern.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ namespace node::url_pattern {

using v8::Array;
using v8::Context;
using v8::DictionaryTemplate;
using v8::DontDelete;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Global;
using v8::Isolate;
using v8::Local;
using v8::LocalVector;
using v8::MaybeLocal;
using v8::Name;
using v8::NewStringType;
Expand Down Expand Up @@ -396,56 +396,49 @@ MaybeLocal<Object> URLPattern::URLPatternComponentResult::ToJSObject(
MaybeLocal<Value> URLPattern::URLPatternResult::ToJSValue(
Environment* env, const ada::url_pattern_result& result) {
auto isolate = env->isolate();
Local<Name> names[] = {
env->inputs_string(),
env->protocol_string(),
env->username_string(),
env->password_string(),
env->hostname_string(),
env->port_string(),
env->pathname_string(),
env->search_string(),
env->hash_string(),
};
LocalVector<Value> inputs(isolate, result.inputs.size());
size_t index = 0;
for (auto& input : result.inputs) {
if (std::holds_alternative<std::string_view>(input)) {
auto input_str = std::get<std::string_view>(input);
if (!ToV8Value(env->context(), input_str).ToLocal(&inputs[index])) {
return {};
}
} else {
DCHECK(std::holds_alternative<ada::url_pattern_init>(input));
auto init = std::get<ada::url_pattern_init>(input);
if (!URLPatternInit::ToJsObject(env, init).ToLocal(&inputs[index])) {
return {};
}
}
index++;
}
LocalVector<Value> values(isolate, arraysize(names));
values[0] = Array::New(isolate, inputs.data(), inputs.size());
if (!URLPatternComponentResult::ToJSObject(env, result.protocol)
.ToLocal(&values[1]) ||
!URLPatternComponentResult::ToJSObject(env, result.username)
.ToLocal(&values[2]) ||
!URLPatternComponentResult::ToJSObject(env, result.password)
.ToLocal(&values[3]) ||
!URLPatternComponentResult::ToJSObject(env, result.hostname)
.ToLocal(&values[4]) ||
!URLPatternComponentResult::ToJSObject(env, result.port)
.ToLocal(&values[5]) ||
!URLPatternComponentResult::ToJSObject(env, result.pathname)
.ToLocal(&values[6]) ||
!URLPatternComponentResult::ToJSObject(env, result.search)
.ToLocal(&values[7]) ||
!URLPatternComponentResult::ToJSObject(env, result.hash)
.ToLocal(&values[8])) {
return {};

auto tmpl = env->urlpatternresult_template();
if (tmpl.IsEmpty()) {
static constexpr std::string_view namesVec[] = {
"inputs",
"protocol",
"username",
"password",
"hostname",
"port",
"pathname",
"search",
"hash",
};
tmpl = DictionaryTemplate::New(isolate, namesVec);
env->set_urlpatternresult_template(tmpl);
}
return Object::New(
isolate, Object::New(isolate), names, values.data(), values.size());

size_t index = 0;
MaybeLocal<Value> vals[] = {
Array::New(env->context(),
result.inputs.size(),
[&index, &inputs = result.inputs, env]() {
auto& input = inputs[index++];
if (std::holds_alternative<std::string_view>(input)) {
auto input_str = std::get<std::string_view>(input);
return ToV8Value(env->context(), input_str);
} else {
DCHECK(
std::holds_alternative<ada::url_pattern_init>(input));
auto init = std::get<ada::url_pattern_init>(input);
return URLPatternInit::ToJsObject(env, init);
}
}),
URLPatternComponentResult::ToJSObject(env, result.protocol),
URLPatternComponentResult::ToJSObject(env, result.username),
URLPatternComponentResult::ToJSObject(env, result.password),
URLPatternComponentResult::ToJSObject(env, result.hostname),
URLPatternComponentResult::ToJSObject(env, result.port),
URLPatternComponentResult::ToJSObject(env, result.pathname),
URLPatternComponentResult::ToJSObject(env, result.search),
URLPatternComponentResult::ToJSObject(env, result.hash)};
return NewDictionaryInstanceNullProto(env->context(), tmpl, vals);
}

std::optional<ada::url_pattern_options>
Expand Down
37 changes: 24 additions & 13 deletions src/node_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ using v8::BigInt;
using v8::Boolean;
using v8::CFunction;
using v8::Context;
using v8::DictionaryTemplate;
using v8::External;
using v8::FunctionCallbackInfo;
using v8::IndexFilter;
Expand All @@ -23,6 +24,7 @@ using v8::Isolate;
using v8::KeyCollectionMode;
using v8::Local;
using v8::LocalVector;
using v8::MaybeLocal;
using v8::Name;
using v8::Object;
using v8::ObjectTemplate;
Expand Down Expand Up @@ -263,6 +265,20 @@ static void GetCallSites(const FunctionCallbackInfo<Value>& args) {
const int frame_count = stack->GetFrameCount();
LocalVector<Value> callsite_objects(isolate);

auto callsite_template = env->callsite_template();
if (callsite_template.IsEmpty()) {
static constexpr std::string_view names[] = {
"functionName",
"scriptId",
"scriptName",
"lineNumber",
"columnNumber",
// TODO(legendecas): deprecate CallSite.column.
"column"};
callsite_template = DictionaryTemplate::New(isolate, names);
env->set_callsite_template(callsite_template);
}

// Frame 0 is node:util. It should be skipped.
for (int i = 1; i < frame_count; ++i) {
Local<StackFrame> stack_frame = stack->GetFrame(isolate, i);
Expand All @@ -279,16 +295,7 @@ static void GetCallSites(const FunctionCallbackInfo<Value>& args) {

std::string script_id = std::to_string(stack_frame->GetScriptId());

Local<Name> names[] = {
env->function_name_string(),
env->script_id_string(),
env->script_name_string(),
env->line_number_string(),
env->column_number_string(),
// TODO(legendecas): deprecate CallSite.column.
env->column_string(),
};
Local<Value> values[] = {
MaybeLocal<Value> values[] = {
function_name,
OneByteString(isolate, script_id),
script_name,
Expand All @@ -297,10 +304,14 @@ static void GetCallSites(const FunctionCallbackInfo<Value>& args) {
// TODO(legendecas): deprecate CallSite.column.
Integer::NewFromUnsigned(isolate, stack_frame->GetColumn()),
};
Local<Object> obj = Object::New(
isolate, v8::Null(isolate), names, values, arraysize(names));

callsite_objects.push_back(obj);
Local<Object> callsite;
if (!NewDictionaryInstanceNullProto(
env->context(), callsite_template, values)
.ToLocal(&callsite)) {
return;
}
callsite_objects.push_back(callsite);
}

Local<Array> callsites =
Expand Down
Loading
Loading