summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2018-08-19 22:17:28 -0400
committerPhilip Chimento <philip.chimento@gmail.com>2018-08-19 22:54:21 -0400
commitf55c0123ad9be959d133c9c94292525e70b768f9 (patch)
tree81b0ddaed61a62fde905794f681c2269d31c6379
parent3276e0c1b4cfce44d3d69dc02dd4285e9a9bd733 (diff)
downloadgjs-f55c0123ad9be959d133c9c94292525e70b768f9.tar.gz
deprecation: Add deprecation warning framework
This adds a framework for deprecation warnings. It consists of an enum of deprecated features, and the API _gjs_warn_deprecated_once_per_callsite() which warns only once in each place the feature is used, even if that code is executed more than once. This is meant to be joined in the future by _gjs_warn_deprecated_once() and _gjs_warn_deprecated_once_per_file(), since we have unconditional deprecation warnings elsewhere in GJS that could very well use those APIs.
-rw-r--r--gjs-srcs.mk2
-rw-r--r--gjs/deprecation.cpp91
-rw-r--r--gjs/deprecation.h36
3 files changed, 129 insertions, 0 deletions
diff --git a/gjs-srcs.mk b/gjs-srcs.mk
index dadfa0ed..6e172b45 100644
--- a/gjs-srcs.mk
+++ b/gjs-srcs.mk
@@ -59,6 +59,8 @@ gjs_srcs = \
gjs/context-private.h \
gjs/coverage.cpp \
gjs/debugger.cpp \
+ gjs/deprecation.cpp \
+ gjs/deprecation.h \
gjs/engine.cpp \
gjs/engine.h \
gjs/global.cpp \
diff --git a/gjs/deprecation.cpp b/gjs/deprecation.cpp
new file mode 100644
index 00000000..9faf0c02
--- /dev/null
+++ b/gjs/deprecation.cpp
@@ -0,0 +1,91 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2018 Philip Chimento <philip.chimento@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <string>
+#include <unordered_set>
+
+#include "gjs/context-private.h"
+#include "gjs/deprecation.h"
+#include "gjs/jsapi-util.h"
+#include "gjs/jsapi-wrapper.h"
+
+const char* messages[] = {
+ // None:
+ "(invalid message)",
+};
+
+struct DeprecationEntry {
+ GjsDeprecationMessageId id;
+ std::string loc;
+
+ DeprecationEntry(GjsDeprecationMessageId an_id, const char* a_loc)
+ : id(an_id), loc(a_loc) {}
+
+ bool operator==(const DeprecationEntry& other) const {
+ return id == other.id && loc == other.loc;
+ }
+};
+
+namespace std {
+template <>
+struct hash<DeprecationEntry> {
+ size_t operator()(const DeprecationEntry& key) const {
+ return hash<int>()(key.id) ^ hash<std::string>()(key.loc);
+ }
+};
+}; // namespace std
+
+static std::unordered_set<DeprecationEntry> logged_messages;
+
+static char* get_callsite(JSContext* cx) {
+ JS::RootedObject stack_frame(cx);
+ if (!JS::CaptureCurrentStack(cx, &stack_frame,
+ JS::StackCapture(JS::MaxFrames(1))) ||
+ !stack_frame)
+ return nullptr;
+
+ JS::RootedValue v_frame(cx, JS::ObjectValue(*stack_frame));
+ JS::RootedString frame_string(cx, JS::ToString(cx, v_frame));
+ if (!frame_string)
+ return nullptr;
+
+ GjsAutoJSChar frame_utf8;
+ if (!gjs_string_to_utf8(cx, JS::StringValue(frame_string), &frame_utf8))
+ return nullptr;
+ return frame_utf8.release();
+}
+
+/* Note, this can only be called from the JS thread because it uses the full
+ * stack dump API and not the "safe" gjs_dumpstack() which can only print to
+ * stdout or stderr. Do not use this function during GC, for example. */
+void _gjs_warn_deprecated_once_per_callsite(JSContext* cx,
+ const GjsDeprecationMessageId id) {
+ GjsAutoJSChar callsite = get_callsite(cx);
+ DeprecationEntry entry(id, callsite);
+ if (!logged_messages.count(entry)) {
+ JS::UniqueChars stack_dump = JS::FormatStackDump(cx, nullptr, false,
+ false, false);
+ g_warning("%s\n%s", messages[id], stack_dump.get());
+ logged_messages.insert(std::move(entry));
+ }
+}
diff --git a/gjs/deprecation.h b/gjs/deprecation.h
new file mode 100644
index 00000000..7353388f
--- /dev/null
+++ b/gjs/deprecation.h
@@ -0,0 +1,36 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2018 Philip Chimento <philip.chimento@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef GJS_DEPRECATION_H_
+#define GJS_DEPRECATION_H_
+
+#include "gjs/jsapi-wrapper.h"
+
+enum GjsDeprecationMessageId {
+ None,
+};
+
+void _gjs_warn_deprecated_once_per_callsite(JSContext* cx,
+ GjsDeprecationMessageId message);
+
+#endif /* GJS_DEPRECATION_H_ */