[gjs: 2/9] log: Add gjs_debug_id()
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 2/9] log: Add gjs_debug_id()
- Date: Sat, 12 May 2018 17:39:55 +0000 (UTC)
commit 05212069d8751c45050db4fbade25a4af273a462
Author: Philip Chimento <philip chimento gmail com>
Date: Sat Nov 18 01:36:07 2017 -0800
log: Add gjs_debug_id()
In order to prevent converting a jsid to a UTF-8 string, only for the
purpose of putting it in a debug message, we introduce gjs_debug_id() and
its friends gjs_debug_value(), gjs_debug_string(), and
gjs_debug_symbol(). If this seems like overkill just to avoid one UTF-8
conversion, it is; but these functions will be used later in the
structured logging code.
gjs/jsapi-util-string.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++
gjs/jsapi-util.cpp | 11 ++--
gjs/jsapi-util.h | 5 ++
gjs/module.cpp | 7 +--
4 files changed, 144 insertions(+), 12 deletions(-)
---
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index 9ce43587..dc9777f0 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -24,6 +24,9 @@
#include <config.h>
#include <algorithm>
+#include <iomanip>
+#include <sstream>
+#include <string>
#include <string.h>
#include "jsapi-util.h"
@@ -365,3 +368,133 @@ gjs_intern_string_to_id(JSContext *cx,
JS::RootedId id(cx, INTERNED_STRING_TO_JSID(cx, str));
return id;
}
+
+static std::string
+gjs_debug_flat_string(JSFlatString *fstr)
+{
+ JSLinearString *str = js::FlatStringToLinearString(fstr);
+ size_t len = js::GetLinearStringLength(str);
+
+ JS::AutoCheckCannotGC nogc;
+ if (js::LinearStringHasLatin1Chars(str)) {
+ const JS::Latin1Char *chars = js::GetLatin1LinearStringChars(nogc, str);
+ return std::string(reinterpret_cast<const char *>(chars), len);
+ }
+
+ std::ostringstream out;
+ const char16_t *chars = js::GetTwoByteLinearStringChars(nogc, str);
+ for (size_t ix = 0; ix < len; ix++) {
+ char16_t c = chars[ix];
+ if (c == '\n')
+ out << "\\n";
+ else if (c == '\t')
+ out << "\\t";
+ else if (c >= 32 && c < 127)
+ out << c;
+ else if (c <= 255)
+ out << "\\x" << std::setfill('0') << std::setw(2) << unsigned(c);
+ else
+ out << "\\x" << std::setfill('0') << std::setw(4) << unsigned(c);
+ }
+ return out.str();
+}
+
+std::string
+gjs_debug_string(JSString *str)
+{
+ if (!JS_StringIsFlat(str)) {
+ std::ostringstream out("<non-flat string of length ");
+ out << JS_GetStringLength(str) << '>';
+ return out.str();
+ }
+ return gjs_debug_flat_string(JS_ASSERT_STRING_IS_FLAT(str));
+}
+
+std::string
+gjs_debug_symbol(JS::Symbol * const sym)
+{
+ /* This is OK because JS::GetSymbolCode() and JS::GetSymbolDescription()
+ * can't cause a garbage collection */
+ JS::HandleSymbol handle = JS::HandleSymbol::fromMarkedLocation(&sym);
+ JS::SymbolCode code = JS::GetSymbolCode(handle);
+ JSString *descr = JS::GetSymbolDescription(handle);
+
+ if (size_t(code) < JS::WellKnownSymbolLimit)
+ return gjs_debug_string(descr);
+
+ std::ostringstream out;
+ if (code == JS::SymbolCode::InSymbolRegistry) {
+ out << "Symbol.for(";
+ if (descr)
+ out << gjs_debug_string(descr);
+ else
+ out << "undefined";
+ out << ")";
+ return out.str();
+ }
+ if (code == JS::SymbolCode::UniqueSymbol) {
+ if (descr)
+ out << "Symbol(" << gjs_debug_string(descr) << ")";
+ else
+ out << "<Symbol at " << sym << ">";
+ return out.str();
+ }
+
+ out << "<unexpected symbol code " << uint32_t(code) << ">";
+ return out.str();
+}
+
+std::string
+gjs_debug_value(JS::Value v)
+{
+ std::ostringstream out;
+ if (v.isNull())
+ return "null";
+ if (v.isUndefined())
+ return "undefined";
+ if (v.isInt32()) {
+ out << v.toInt32();
+ return out.str();
+ }
+ if (v.isDouble()) {
+ out << v.toDouble();
+ return out.str();
+ }
+ if (v.isString()) {
+ out << gjs_debug_string(v.toString());
+ return out.str();
+ }
+ if (v.isSymbol()) {
+ out << gjs_debug_symbol(v.toSymbol());
+ return out.str();
+ }
+ if (v.isObject() && js::IsFunctionObject(&v.toObject())) {
+ JSFunction* fun = JS_GetObjectFunction(&v.toObject());
+ JSString *display_name = JS_GetFunctionDisplayId(fun);
+ if (display_name)
+ out << "<function " << gjs_debug_string(display_name);
+ else
+ out << "<unnamed function";
+ out << " at " << fun << '>';
+ return out.str();
+ }
+ if (v.isObject()) {
+ JSObject *obj = &v.toObject();
+ const JSClass* clasp = JS_GetClass(obj);
+ out << "<object " << clasp->name << " at " << obj << '>';
+ return out.str();
+ }
+ if (v.isBoolean())
+ return (v.toBoolean() ? "true" : "false");
+ if (v.isMagic())
+ return "<magic>";
+ return "unexpected value";
+}
+
+std::string
+gjs_debug_id(jsid id)
+{
+ if (JSID_IS_STRING(id))
+ return gjs_debug_flat_string(JSID_TO_FLAT_STRING(id));
+ return gjs_debug_value(js::IdToValue(id));
+}
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 5c91dd2a..3f51aac5 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -138,15 +138,12 @@ throw_property_lookup_error(JSContext *cx,
/* remember gjs_throw() is a no-op if JS_GetProperty()
* already set an exception
*/
- GjsAutoJSChar name;
- gjs_get_string_id(cx, property_name, &name);
-
if (description)
- gjs_throw(cx, "No property '%s' in %s (or %s)", name.get(), description,
- reason);
+ gjs_throw(cx, "No property '%s' in %s (or %s)",
+ gjs_debug_id(property_name).c_str(), description, reason);
else
- gjs_throw(cx, "No property '%s' in object %p (or %s)", name.get(),
- obj.address(), reason);
+ gjs_throw(cx, "No property '%s' in object %p (or %s)",
+ gjs_debug_id(property_name).c_str(), obj.get(), reason);
}
/* Returns whether the object had the property; if the object did
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index 8c54ee0a..881a221d 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -385,4 +385,9 @@ bool gjs_object_require_converted_property(JSContext *cx,
value);
}
+std::string gjs_debug_string(JSString *str);
+std::string gjs_debug_symbol(JS::Symbol * const sym);
+std::string gjs_debug_value(JS::Value v);
+std::string gjs_debug_id(jsid id);
+
#endif /* __GJS_JSAPI_UTIL_H__ */
diff --git a/gjs/module.cpp b/gjs/module.cpp
index cc6657a7..474bba40 100644
--- a/gjs/module.cpp
+++ b/gjs/module.cpp
@@ -163,17 +163,14 @@ class GjsModule {
* be supported according to ES6. For compatibility with earlier GJS,
* we treat it as if it were a real property, but warn about it. */
- GjsAutoJSChar prop_name;
- if (!gjs_get_string_id(cx, id, &prop_name))
- return false;
-
g_warning("Some code accessed the property '%s' on the module '%s'. "
"That property was defined with 'let' or 'const' inside the "
"module. This was previously supported, but is not correct "
"according to the ES6 standard. Any symbols to be exported "
"from a module must be defined with 'var'. The property "
"access will work as previously for the time being, but "
- "please fix your code anyway.", prop_name.get(), m_name);
+ "please fix your code anyway.",
+ gjs_debug_id(id).c_str(), m_name);
JS::Rooted<JS::PropertyDescriptor> desc(cx);
return JS_GetPropertyDescriptorById(cx, lexical, id, &desc) &&
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]