@@ -377,8 +377,9 @@ inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc<char>(n); }
377377void ThrowErrStringTooLong (v8::Isolate* isolate);
378378
379379v8::MaybeLocal<v8::Value> ToV8Value (v8::Local<v8::Context> context,
380- const std::string& str) {
381- v8::Isolate* isolate = context->GetIsolate ();
380+ const std::string& str,
381+ v8::Isolate* isolate) {
382+ if (isolate == nullptr ) isolate = context->GetIsolate ();
382383 if (UNLIKELY (str.size () >= static_cast <size_t >(v8::String::kMaxLength ))) {
383384 // V8 only has a TODO comment about adding an exception when the maximum
384385 // string size is exceeded.
@@ -393,33 +394,33 @@ v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
393394
394395template <typename T>
395396v8::MaybeLocal<v8::Value> ToV8Value (v8::Local<v8::Context> context,
396- const std::vector<T>& vec) {
397- v8::Isolate* isolate = context->GetIsolate ();
397+ const std::vector<T>& vec,
398+ v8::Isolate* isolate) {
399+ if (isolate == nullptr ) isolate = context->GetIsolate ();
398400 v8::EscapableHandleScope handle_scope (isolate);
399401
400- v8::Local<v8::Array> arr = v8::Array::New (isolate, vec.size ());
402+ MaybeStackBuffer<v8::Local<v8::Value>, 128 > arr (vec.size ());
403+ arr.SetLength (vec.size ());
401404 for (size_t i = 0 ; i < vec.size (); ++i) {
402- v8::Local<v8::Value> val;
403- if (!ToV8Value (context, vec[i]).ToLocal (&val) ||
404- arr->Set (context, i, val).IsNothing ()) {
405+ if (!ToV8Value (context, vec[i], isolate).ToLocal (&arr[i]))
405406 return v8::MaybeLocal<v8::Value>();
406- }
407407 }
408408
409- return handle_scope.Escape (arr);
409+ return handle_scope.Escape (v8::Array::New (isolate, arr. out (), arr. length ()) );
410410}
411411
412412template <typename T, typename U>
413413v8::MaybeLocal<v8::Value> ToV8Value (v8::Local<v8::Context> context,
414- const std::unordered_map<T, U>& map) {
415- v8::Isolate* isolate = context->GetIsolate ();
414+ const std::unordered_map<T, U>& map,
415+ v8::Isolate* isolate) {
416+ if (isolate == nullptr ) isolate = context->GetIsolate ();
416417 v8::EscapableHandleScope handle_scope (isolate);
417418
418419 v8::Local<v8::Map> ret = v8::Map::New (isolate);
419420 for (const auto & item : map) {
420421 v8::Local<v8::Value> first, second;
421- if (!ToV8Value (context, item.first ).ToLocal (&first) ||
422- !ToV8Value (context, item.second ).ToLocal (&second) ||
422+ if (!ToV8Value (context, item.first , isolate ).ToLocal (&first) ||
423+ !ToV8Value (context, item.second , isolate ).ToLocal (&second) ||
423424 ret->Set (context, first, second).IsEmpty ()) {
424425 return v8::MaybeLocal<v8::Value>();
425426 }
@@ -428,6 +429,32 @@ v8::MaybeLocal<v8::Value> ToV8Value(v8::Local<v8::Context> context,
428429 return handle_scope.Escape (ret);
429430}
430431
432+ template <typename T, typename >
433+ v8::MaybeLocal<v8::Value> ToV8Value (v8::Local<v8::Context> context,
434+ const T& number,
435+ v8::Isolate* isolate) {
436+ if (isolate == nullptr ) isolate = context->GetIsolate ();
437+
438+ using Limits = std::numeric_limits<T>;
439+ // Choose Uint32, Int32, or Double depending on range checks.
440+ // These checks should all collapse at compile time.
441+ if (static_cast <uint32_t >(Limits::max ()) <=
442+ std::numeric_limits<uint32_t >::max () &&
443+ static_cast <uint32_t >(Limits::min ()) >=
444+ std::numeric_limits<uint32_t >::min () && Limits::is_exact) {
445+ return v8::Integer::NewFromUnsigned (isolate, static_cast <uint32_t >(number));
446+ }
447+
448+ if (static_cast <int32_t >(Limits::max ()) <=
449+ std::numeric_limits<int32_t >::max () &&
450+ static_cast <int32_t >(Limits::min ()) >=
451+ std::numeric_limits<int32_t >::min () && Limits::is_exact) {
452+ return v8::Integer::New (isolate, static_cast <int32_t >(number));
453+ }
454+
455+ return v8::Number::New (isolate, static_cast <double >(number));
456+ }
457+
431458} // namespace node
432459
433460#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
0 commit comments