Skip to content

Commit 5cd2ec8

Browse files
committed
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: #51758 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]>
1 parent d51a74a commit 5cd2ec8

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

src/util-inl.h

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

404+
struct ArrayIterationData {
405+
std::vector<v8::Global<v8::Value>>* out;
406+
v8::Isolate* isolate = nullptr;
407+
};
408+
409+
inline v8::Array::CallbackResult PushItemToVector(uint32_t index,
410+
v8::Local<v8::Value> element,
411+
void* data) {
412+
auto vec = static_cast<ArrayIterationData*>(data)->out;
413+
auto isolate = static_cast<ArrayIterationData*>(data)->isolate;
414+
vec->push_back(v8::Global<v8::Value>(isolate, element));
415+
return v8::Array::CallbackResult::kContinue;
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+
return js_array->Iterate(context, PushItemToVector, &data);
425+
}
426+
404427
v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
405428
std::string_view str,
406429
v8::Isolate* isolate) {

src/util.h

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

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

0 commit comments

Comments
 (0)