diff --git a/src/node_errors.cc b/src/node_errors.cc index 9bae27550cec1b..4e13c24e15e1d0 100644 --- a/src/node_errors.cc +++ b/src/node_errors.cc @@ -375,8 +375,13 @@ static void ReportFatalException(Environment* env, } if (!env->options()->trace_uncaught) { - FPrintF(stderr, "(Use `node --trace-uncaught ...` to show " - "where the exception was thrown)\n"); + std::string argv0; + if (!env->argv().empty()) argv0 = env->argv()[0]; + if (argv0.empty()) argv0 = "node"; + FPrintF(stderr, + "(Use `%s --trace-uncaught ...` to show where the exception " + "was thrown)\n", + fs::Basename(argv0, ".exe")); } } diff --git a/src/node_file.cc b/src/node_file.cc index f4d26adf290781..203ec5c8ca57b1 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -82,6 +82,22 @@ constexpr char kPathSeparator = '/'; const char* const kPathSeparator = "\\/"; #endif +std::string Basename(const std::string& str, const std::string& extension) { + std::string ret = str; + + // Remove everything leading up to and including the final path separator. + std::string::size_type pos = ret.find_last_of(kPathSeparator); + if (pos != std::string::npos) ret = ret.substr(pos + 1); + + // Strip away the extension, if any. + if (ret.size() >= extension.size() && + ret.substr(ret.size() - extension.size()) == extension) { + ret = ret.substr(0, ret.size() - extension.size()); + } + + return ret; +} + inline int64_t GetOffset(Local value) { return IsSafeJsInt(value) ? value.As()->Value() : -1; } diff --git a/src/node_internals.h b/src/node_internals.h index dfb2c6e0c37c04..fa3ba022fe7e23 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -396,6 +396,10 @@ BaseObjectPtr CreateHeapSnapshotStream( Environment* env, HeapSnapshotPointer&& snapshot); } // namespace heap +namespace fs { +std::string Basename(const std::string& str, const std::string& extension); +} // namespace fs + } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS