Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: use string_view for report and related code #46723

Merged
merged 2 commits into from
Feb 20, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/json_utils.cc
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@

namespace node {

std::string EscapeJsonChars(const std::string& str) {
const std::string control_symbols[0x20] = {
std::string EscapeJsonChars(std::string_view str) {
static const std::string_view control_symbols[0x20] = {
"\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005",
"\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b",
"\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011",
25 changes: 18 additions & 7 deletions src/json_utils.h
Original file line number Diff line number Diff line change
@@ -4,13 +4,21 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <iomanip>
#include <ostream>
#include <limits>
#include <ostream>
#include <string>
#include <string_view>

namespace node {

std::string EscapeJsonChars(const std::string& str);
constexpr bool NeedsJsonEscape(std::string_view str) {
for (const char c : str) {
if (c == '\\' || c == '"' || c < 0x20) return true;
}
return false;
}

std::string EscapeJsonChars(std::string_view str);
std::string Reindent(const std::string& str, int indentation);

// JSON compiler definitions.
@@ -135,17 +143,20 @@ class JSONWriter {
}

inline void write_value(Null null) { out_ << "null"; }
inline void write_value(const char* str) { write_string(str); }
inline void write_value(const std::string& str) { write_string(str); }
inline void write_value(std::string_view str) { write_string(str); }

inline void write_value(const ForeignJSON& json) {
out_ << Reindent(json.as_string, indent_);
}

inline void write_string(const std::string& str) {
out_ << '"' << EscapeJsonChars(str) << '"';
inline void write_string(std::string_view str) {
out_ << '"';
if (NeedsJsonEscape(str)) // only create temporary std::string if necessary
out_ << EscapeJsonChars(str);
else
out_ << str;
out_ << '"';
}
inline void write_string(const char* str) { write_string(std::string(str)); }

enum JSONState { kObjectStart, kAfterValue };
std::ostream& out_;
2 changes: 1 addition & 1 deletion src/node_api.cc
Original file line number Diff line number Diff line change
@@ -657,7 +657,7 @@ void napi_module_register_by_symbol(v8::Local<v8::Object> exports,
// a file system path.
// TODO(gabrielschulhof): Pass the `filename` through unchanged if/when we
// receive it as a URL already.
module_filename = node::url::FromFilePath(filename.ToString());
module_filename = node::url::FromFilePath(filename.ToStringView());
}

// Create a new napi_env for this specific module.
6 changes: 4 additions & 2 deletions src/node_errors.cc
Original file line number Diff line number Diff line change
@@ -420,8 +420,10 @@ static void ReportFatalException(Environment* env,
// Not an error object. Just print as-is.
node::Utf8Value message(env->isolate(), error);

FPrintF(stderr, "%s\n",
*message ? message.ToString() : "<toString() threw exception>");
FPrintF(
stderr,
"%s\n",
*message ? message.ToStringView() : "<toString() threw exception>");
} else {
node::Utf8Value name_string(env->isolate(), name.ToLocalChecked());
node::Utf8Value message_string(env->isolate(), message.ToLocalChecked());
28 changes: 14 additions & 14 deletions src/node_report.cc
Original file line number Diff line number Diff line change
@@ -400,11 +400,10 @@ static void PrintJavaScriptErrorProperties(JSONWriter* writer,
!value->ToString(context).ToLocal(&value_string)) {
continue;
}
String::Utf8Value k(isolate, key);
node::Utf8Value k(isolate, key);
if (!strcmp(*k, "stack") || !strcmp(*k, "message")) continue;
String::Utf8Value v(isolate, value_string);
writer->json_keyvalue(std::string(*k, k.length()),
std::string(*v, v.length()));
node::Utf8Value v(isolate, value_string);
writer->json_keyvalue(k.ToStringView(), v.ToStringView());
}
}
writer->json_objectend(); // the end of 'errorProperties'
@@ -631,27 +630,26 @@ static void PrintResourceUsage(JSONWriter* writer) {
uint64_t free_memory = uv_get_free_memory();
uint64_t total_memory = uv_get_total_memory();

writer->json_keyvalue("free_memory", std::to_string(free_memory));
writer->json_keyvalue("total_memory", std::to_string(total_memory));
writer->json_keyvalue("free_memory", free_memory);
writer->json_keyvalue("total_memory", total_memory);

size_t rss;
int err = uv_resident_set_memory(&rss);
if (!err) {
writer->json_keyvalue("rss", std::to_string(rss));
writer->json_keyvalue("rss", rss);
}

uint64_t constrained_memory = uv_get_constrained_memory();
if (constrained_memory) {
writer->json_keyvalue("constrained_memory",
std::to_string(constrained_memory));
writer->json_keyvalue("constrained_memory", constrained_memory);
}

// See GuessMemoryAvailableToTheProcess
if (!err && constrained_memory && constrained_memory >= rss) {
uint64_t available_memory = constrained_memory - rss;
writer->json_keyvalue("available_memory", std::to_string(available_memory));
writer->json_keyvalue("available_memory", available_memory);
} else {
writer->json_keyvalue("available_memory", std::to_string(free_memory));
writer->json_keyvalue("available_memory", free_memory);
}

if (uv_getrusage(&rusage) == 0) {
@@ -668,7 +666,7 @@ static void PrintResourceUsage(JSONWriter* writer) {
writer->json_keyvalue("cpuConsumptionPercent", cpu_percentage);
writer->json_keyvalue("userCpuConsumptionPercent", user_cpu_percentage);
writer->json_keyvalue("kernelCpuConsumptionPercent", kernel_cpu_percentage);
writer->json_keyvalue("maxRss", std::to_string(rusage.ru_maxrss * 1024));
writer->json_keyvalue("maxRss", rusage.ru_maxrss * 1024);
writer->json_objectstart("pageFaults");
writer->json_keyvalue("IORequired", rusage.ru_majflt);
writer->json_keyvalue("IONotRequired", rusage.ru_minflt);
@@ -795,13 +793,15 @@ static void PrintComponentVersions(JSONWriter* writer) {
writer->json_objectstart("componentVersions");

#define V(key) +1
std::pair<std::string, std::string> versions_array[NODE_VERSIONS_KEYS(V)];
std::pair<std::string_view, std::string_view>
versions_array[NODE_VERSIONS_KEYS(V)];
#undef V
auto* slot = &versions_array[0];

#define V(key) \
do { \
*slot++ = std::make_pair(#key, per_process::metadata.versions.key); \
*slot++ = std::pair<std::string_view, std::string_view>( \
#key, per_process::metadata.versions.key); \
} while (0);
NODE_VERSIONS_KEYS(V)
#undef V
62 changes: 29 additions & 33 deletions src/node_report_utils.cc
Original file line number Diff line number Diff line change
@@ -83,79 +83,75 @@ static void ReportEndpoints(uv_handle_t* h, JSONWriter* writer) {
// Utility function to format libuv pipe information.
static void ReportPipeEndpoints(uv_handle_t* h, JSONWriter* writer) {
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
MallocedBuffer<char> buffer(0);
size_t buffer_size = 0;
MaybeStackBuffer<char> buffer;
size_t buffer_size = buffer.capacity();
int rc = -1;

// First call to get required buffer size.
rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size);
rc = uv_pipe_getsockname(&handle->pipe, buffer.out(), &buffer_size);
if (rc == UV_ENOBUFS) {
buffer = MallocedBuffer<char>(buffer_size);
if (buffer.data != nullptr) {
rc = uv_pipe_getsockname(&handle->pipe, buffer.data, &buffer_size);
} else {
buffer_size = 0;
}
buffer.AllocateSufficientStorage(buffer_size);
rc = uv_pipe_getsockname(&handle->pipe, buffer.out(), &buffer_size);
}
if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) {
writer->json_keyvalue("localEndpoint", buffer.data);
if (rc == 0 && buffer_size != 0) {
buffer.SetLength(buffer_size);
writer->json_keyvalue("localEndpoint", buffer.ToStringView());
} else {
writer->json_keyvalue("localEndpoint", null);
}

// First call to get required buffer size.
rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size);
buffer_size = buffer.capacity();
rc = uv_pipe_getpeername(&handle->pipe, buffer.out(), &buffer_size);
if (rc == UV_ENOBUFS) {
buffer = MallocedBuffer<char>(buffer_size);
if (buffer.data != nullptr) {
rc = uv_pipe_getpeername(&handle->pipe, buffer.data, &buffer_size);
}
buffer.AllocateSufficientStorage(buffer_size);
rc = uv_pipe_getpeername(&handle->pipe, buffer.out(), &buffer_size);
}
if (rc == 0 && buffer_size != 0 && buffer.data != nullptr) {
writer->json_keyvalue("remoteEndpoint", buffer.data);
if (rc == 0 && buffer_size != 0) {
buffer.SetLength(buffer_size);
writer->json_keyvalue("remoteEndpoint", buffer.ToStringView());
} else {
writer->json_keyvalue("remoteEndpoint", null);
}
}

// Utility function to format libuv path information.
static void ReportPath(uv_handle_t* h, JSONWriter* writer) {
MallocedBuffer<char> buffer(0);
MaybeStackBuffer<char> buffer;
int rc = -1;
size_t size = 0;
size_t size = buffer.capacity();
uv_any_handle* handle = reinterpret_cast<uv_any_handle*>(h);
bool wrote_filename = false;
// First call to get required buffer size.
switch (h->type) {
case UV_FS_EVENT:
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.out(), &size);
break;
case UV_FS_POLL:
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.out(), &size);
break;
default:
break;
}
if (rc == UV_ENOBUFS) {
buffer = MallocedBuffer<char>(size + 1);
buffer.AllocateSufficientStorage(size);
switch (h->type) {
case UV_FS_EVENT:
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.data, &size);
rc = uv_fs_event_getpath(&(handle->fs_event), buffer.out(), &size);
break;
case UV_FS_POLL:
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.data, &size);
rc = uv_fs_poll_getpath(&(handle->fs_poll), buffer.out(), &size);
break;
default:
break;
}
if (rc == 0) {
// buffer is not null terminated.
buffer.data[size] = '\0';
writer->json_keyvalue("filename", buffer.data);
wrote_filename = true;
}
}
if (!wrote_filename) writer->json_keyvalue("filename", null);

if (rc == 0 && size > 0) {
buffer.SetLength(size);
writer->json_keyvalue("filename", buffer.ToStringView());
} else {
writer->json_keyvalue("filename", null);
}
}

// Utility function to walk libuv handles.
13 changes: 8 additions & 5 deletions src/util.h
Original file line number Diff line number Diff line change
@@ -38,10 +38,10 @@
#include <array>
#include <limits>
#include <memory>
#include <set>
#include <string>
#include <string_view>
#include <type_traits>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>
@@ -486,6 +486,11 @@ class MaybeStackBuffer {
free(buf_);
}

inline std::basic_string<T> ToString() const { return {out(), length()}; }
inline std::basic_string_view<T> ToStringView() const {
return {out(), length()};
}

private:
size_t length_;
// capacity of the malloc'ed buf_
@@ -533,8 +538,6 @@ class Utf8Value : public MaybeStackBuffer<char> {
public:
explicit Utf8Value(v8::Isolate* isolate, v8::Local<v8::Value> value);

inline std::string ToString() const { return std::string(out(), length()); }

inline bool operator==(const char* a) const {
return strcmp(out(), a) == 0;
}
@@ -609,7 +612,7 @@ struct MallocedBuffer {
}

void Truncate(size_t new_size) {
CHECK(new_size <= size);
CHECK_LE(new_size, size);
size = new_size;
}

@@ -618,7 +621,7 @@ struct MallocedBuffer {
data = UncheckedRealloc(data, new_size);
}

inline bool is_empty() const { return data == nullptr; }
bool is_empty() const { return data == nullptr; }

MallocedBuffer() : data(nullptr), size(0) {}
explicit MallocedBuffer(size_t size) : data(Malloc<T>(size)), size(size) {}