Skip to content

Commit 2b86c09

Browse files
committed
src: backport FromV8Array
This backports nodejs#51758 which relies on an V8 API that's not available on v20.x. Original commit message: src: implement v8 array iteration using the new callback-based API Using this to iterate over an array can be faster than calling Array::Get repeatedly. Local experiment shows that this is faster once the array size is bigger than 2. PR-URL: nodejs#51758 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]>
1 parent 0f98c34 commit 2b86c09

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

src/util-inl.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,35 @@ inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
402402
// headers than we really need to.
403403
void ThrowErrStringTooLong(v8::Isolate* isolate);
404404

405+
struct ArrayIterationData {
406+
std::vector<v8::Global<v8::Value>>* out;
407+
v8::Isolate* isolate = nullptr;
408+
};
409+
410+
inline void PushItemToVector(uint32_t index,
411+
v8::Local<v8::Value> element,
412+
void* data) {
413+
auto vec = static_cast<ArrayIterationData*>(data)->out;
414+
auto isolate = static_cast<ArrayIterationData*>(data)->isolate;
415+
vec->push_back(v8::Global<v8::Value>(isolate, element));
416+
}
417+
418+
v8::Maybe<void> FromV8Array(v8::Local<v8::Context> context,
419+
v8::Local<v8::Array> js_array,
420+
std::vector<v8::Global<v8::Value>>* out) {
421+
uint32_t count = js_array->Length();
422+
out->reserve(count);
423+
ArrayIterationData data{out, context->GetIsolate()};
424+
for (uint32_t i = 0; i < js_array->Length(); i++) {
425+
v8::Local<v8::Value> element;
426+
if (!js_array->Get(context, i).ToLocal(&element)) {
427+
return v8::Nothing<void>();
428+
}
429+
PushItemToVector(i, element, &data);
430+
}
431+
return v8::JustVoid();
432+
}
433+
405434
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
406435
std::string_view str,
407436
v8::Isolate* isolate) {

src/util.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,16 @@ struct FunctionDeleter {
698698
template <typename T, void (*function)(T*)>
699699
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
700700

701+
// Convert a v8::Array into an std::vector using the callback-based API.
702+
// This can be faster than calling Array::Get() repeatedly when the array
703+
// has more than 2 entries.
704+
// Note that iterating over an array in C++ and performing operations on each
705+
// element in a C++ loop is still slower than iterating over the array in JS
706+
// and calling into native in the JS loop repeatedly on each element,
707+
// as of V8 11.9.
708+
inline v8::Maybe<void> FromV8Array(v8::Local<v8::Context> context,
709+
v8::Local<v8::Array> js_array,
710+
std::vector<v8::Global<v8::Value>>* out);
701711
std::vector<std::string_view> SplitString(const std::string_view in,
702712
const std::string_view delim);
703713

0 commit comments

Comments
 (0)