diff --git a/src/util-inl.h b/src/util-inl.h index acd370e2358264..6d612f1eb7c8b7 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -377,8 +377,9 @@ inline char* UncheckedCalloc(size_t n) { return UncheckedCalloc(n); } void ThrowErrStringTooLong(v8::Isolate* isolate); v8::MaybeLocal ToV8Value(v8::Local context, - const std::string& str) { - v8::Isolate* isolate = context->GetIsolate(); + const std::string& str, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); if (UNLIKELY(str.size() >= static_cast(v8::String::kMaxLength))) { // V8 only has a TODO comment about adding an exception when the maximum // string size is exceeded. @@ -393,33 +394,33 @@ v8::MaybeLocal ToV8Value(v8::Local context, template v8::MaybeLocal ToV8Value(v8::Local context, - const std::vector& vec) { - v8::Isolate* isolate = context->GetIsolate(); + const std::vector& vec, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); v8::EscapableHandleScope handle_scope(isolate); - v8::Local arr = v8::Array::New(isolate, vec.size()); + MaybeStackBuffer, 128> arr(vec.size()); + arr.SetLength(vec.size()); for (size_t i = 0; i < vec.size(); ++i) { - v8::Local val; - if (!ToV8Value(context, vec[i]).ToLocal(&val) || - arr->Set(context, i, val).IsNothing()) { + if (!ToV8Value(context, vec[i], isolate).ToLocal(&arr[i])) return v8::MaybeLocal(); - } } - return handle_scope.Escape(arr); + return handle_scope.Escape(v8::Array::New(isolate, arr.out(), arr.length())); } template v8::MaybeLocal ToV8Value(v8::Local context, - const std::unordered_map& map) { - v8::Isolate* isolate = context->GetIsolate(); + const std::unordered_map& map, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); v8::EscapableHandleScope handle_scope(isolate); v8::Local ret = v8::Map::New(isolate); for (const auto& item : map) { v8::Local first, second; - if (!ToV8Value(context, item.first).ToLocal(&first) || - !ToV8Value(context, item.second).ToLocal(&second) || + if (!ToV8Value(context, item.first, isolate).ToLocal(&first) || + !ToV8Value(context, item.second, isolate).ToLocal(&second) || ret->Set(context, first, second).IsEmpty()) { return v8::MaybeLocal(); } @@ -428,6 +429,32 @@ v8::MaybeLocal ToV8Value(v8::Local context, return handle_scope.Escape(ret); } +template +v8::MaybeLocal ToV8Value(v8::Local context, + const T& number, + v8::Isolate* isolate) { + if (isolate == nullptr) isolate = context->GetIsolate(); + + using Limits = std::numeric_limits; + // Choose Uint32, Int32, or Double depending on range checks. + // These checks should all collapse at compile time. + if (static_cast(Limits::max()) <= + std::numeric_limits::max() && + static_cast(Limits::min()) >= + std::numeric_limits::min() && Limits::is_exact) { + return v8::Integer::NewFromUnsigned(isolate, static_cast(number)); + } + + if (static_cast(Limits::max()) <= + std::numeric_limits::max() && + static_cast(Limits::min()) >= + std::numeric_limits::min() && Limits::is_exact) { + return v8::Integer::New(isolate, static_cast(number)); + } + + return v8::Number::New(isolate, static_cast(number)); +} + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS diff --git a/src/util.h b/src/util.h index d3835c7e692b7d..b1a135b46dc2a9 100644 --- a/src/util.h +++ b/src/util.h @@ -35,6 +35,7 @@ #include #include // std::function +#include #include #include #include @@ -519,13 +520,21 @@ using DeleteFnPtr = typename FunctionDeleter::Pointer; std::set ParseCommaSeparatedSet(const std::string& in); inline v8::MaybeLocal ToV8Value(v8::Local context, - const std::string& str); + const std::string& str, + v8::Isolate* isolate = nullptr); +template ::is_specialized, bool>::type> +inline v8::MaybeLocal ToV8Value(v8::Local context, + const T& number, + v8::Isolate* isolate = nullptr); template inline v8::MaybeLocal ToV8Value(v8::Local context, - const std::vector& vec); + const std::vector& vec, + v8::Isolate* isolate = nullptr); template inline v8::MaybeLocal ToV8Value(v8::Local context, - const std::unordered_map& map); + const std::unordered_map& map, + v8::Isolate* isolate = nullptr); // These macros expects a `Isolate* isolate` and a `Local context` // to be in the scope.