[gjs: 1/3] deprecation: Add deprecation warning framework



commit f55c0123ad9be959d133c9c94292525e70b768f9
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Aug 19 22:17:28 2018 -0400

    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.

 gjs-srcs.mk         |  2 ++
 gjs/deprecation.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gjs/deprecation.h   | 36 +++++++++++++++++++++
 3 files changed, 129 insertions(+)
---
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_ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]