File: cjs-deprecation-Use-a-larger-deprecation-stack-for-JS-inv.patch

package info (click to toggle)
cjs 128.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,264 kB
  • sloc: cpp: 34,377; javascript: 27,762; ansic: 13,033; sh: 1,611; python: 780; xml: 116; makefile: 38
file content (161 lines) | stat: -rw-r--r-- 7,143 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
From: =?utf-8?b?Ik1hcmNvIFRyZXZpc2FuIChUcmV2acOxbyki?= <mail@3v1n0.net>
Date: Fri, 12 Sep 2025 00:28:09 +0200
Subject: cjs/deprecation: Use a larger deprecation stack for JS invoked
 requests

When using warnDeprecatedOncePerCallsite() from JS we need to use a
larger stack to track the call site, otherwise we may end up considering
the same call site for different actual callers.

In fact when using this in Gio.js override the call site is always the
same, but we care about where that function is being invoked from.
---
 cjs/deprecation.cpp           | 19 +++++++++++--------
 cjs/deprecation.h             |  5 +++--
 installed-tests/js/testGio.js | 23 +++++++++++++++++------
 modules/print.cpp             |  4 ++--
 4 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/cjs/deprecation.cpp b/cjs/deprecation.cpp
index 9c4e44d..fca66ff 100644
--- a/cjs/deprecation.cpp
+++ b/cjs/deprecation.cpp
@@ -81,10 +81,10 @@ struct hash<DeprecationEntry> {
 static std::unordered_set<DeprecationEntry> logged_messages;
 
 GJS_JSAPI_RETURN_CONVENTION
-static JS::UniqueChars get_callsite(JSContext* cx) {
+static JS::UniqueChars get_callsite(JSContext* cx, unsigned max_frames) {
     JS::RootedObject stack_frame(cx);
     if (!JS::CaptureCurrentStack(cx, &stack_frame,
-                                 JS::StackCapture(JS::MaxFrames(1))) ||
+                                 JS::StackCapture(JS::MaxFrames(max_frames))) ||
         !stack_frame)
         return nullptr;
 
@@ -98,8 +98,9 @@ static JS::UniqueChars get_callsite(JSContext* cx) {
 
 static void warn_deprecated_unsafe_internal(JSContext* cx,
                                             const GjsDeprecationMessageId id,
-                                            const char* msg) {
-    JS::UniqueChars callsite(get_callsite(cx));
+                                            const char* msg,
+                                            unsigned max_frames) {
+    JS::UniqueChars callsite(get_callsite(cx, max_frames));
     DeprecationEntry entry(id, callsite.get());
     if (!logged_messages.count(entry)) {
         JS::UniqueChars stack_dump =
@@ -113,13 +114,15 @@ static void warn_deprecated_unsafe_internal(JSContext* cx,
  * 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) {
-    warn_deprecated_unsafe_internal(cx, id, messages[id]);
+                                            const GjsDeprecationMessageId id,
+                                            unsigned max_frames) {
+    warn_deprecated_unsafe_internal(cx, id, messages[id], max_frames);
 }
 
 void _gjs_warn_deprecated_once_per_callsite(
     JSContext* cx, GjsDeprecationMessageId id,
-    const std::vector<const char*>& args) {
+    const std::vector<const char*>& args,
+    unsigned max_frames) {
     // In C++20, use std::format() for this
     std::string_view format_string{messages[id]};
     std::stringstream message;
@@ -149,5 +152,5 @@ void _gjs_warn_deprecated_once_per_callsite(
     message << format_string.substr(copied, std::string::npos);
 
     std::string message_formatted = message.str();
-    warn_deprecated_unsafe_internal(cx, id, message_formatted.c_str());
+    warn_deprecated_unsafe_internal(cx, id, message_formatted.c_str(), max_frames);
 }
diff --git a/cjs/deprecation.h b/cjs/deprecation.h
index a59613d..7a76780 100644
--- a/cjs/deprecation.h
+++ b/cjs/deprecation.h
@@ -21,10 +21,11 @@ enum GjsDeprecationMessageId : unsigned {
 };
 
 void _gjs_warn_deprecated_once_per_callsite(JSContext* cx,
-                                            GjsDeprecationMessageId message);
+                                            GjsDeprecationMessageId message,
+                                            unsigned max_frames = 1);
 
 void _gjs_warn_deprecated_once_per_callsite(
     JSContext* cx, GjsDeprecationMessageId id,
-    const std::vector<const char*>& args);
+    const std::vector<const char*>& args, unsigned max_frames = 1);
 
 #endif  // GJS_DEPRECATION_H_
diff --git a/installed-tests/js/testGio.js b/installed-tests/js/testGio.js
index f67aec4..b92d374 100644
--- a/installed-tests/js/testGio.js
+++ b/installed-tests/js/testGio.js
@@ -440,7 +440,8 @@ Exec=${GLib.find_program_in_path('sh')}
     it('can be created using Gio wrapper', function () {
         expectDeprecationWarning(() =>
             expect(Gio.DesktopAppInfo.new_from_keyfile(keyFile)).not.toBeNull());
-        expect(Gio.DesktopAppInfo.new_from_keyfile(keyFile)).not.toBeNull();
+        expectDeprecationWarning(() =>
+            expect(Gio.DesktopAppInfo.new_from_keyfile(keyFile)).not.toBeNull());
     });
 
     describe('provides platform-independent functions', function () {
@@ -448,8 +449,13 @@ Exec=${GLib.find_program_in_path('sh')}
             if (!requiredVersion)
                 pending('Installed Gio is not new enough for this test');
 
-            const appInfo = ns.DesktopAppInfo.new_from_keyfile(keyFile);
-            expect(appInfo.get_name()).toBe('Some Application');
+            const maybeExpectDeprecationWarning = ns === Gio
+                ? expectDeprecationWarning : tf => tf();
+
+            maybeExpectDeprecationWarning(() => {
+                const appInfo = ns.DesktopAppInfo.new_from_keyfile(keyFile);
+                expect(appInfo.get_name()).toBe('Some Application');
+            });
         }));
     });
 
@@ -458,9 +464,14 @@ Exec=${GLib.find_program_in_path('sh')}
             if (!requiredVersion)
                 pending('Installed Gio is not new enough for this test');
 
-            const appInfo = ns.DesktopAppInfo.new_from_keyfile(keyFile);
-            expect(appInfo.has_key('Name')).toBeTrue();
-            expect(appInfo.get_string('Name')).toBe('Some Application');
+            const maybeExpectDeprecationWarning = ns === Gio
+                ? expectDeprecationWarning : tf => tf();
+
+            maybeExpectDeprecationWarning(() => {
+                const appInfo = ns.DesktopAppInfo.new_from_keyfile(keyFile);
+                expect(appInfo.has_key('Name')).toBeTrue();
+                expect(appInfo.get_string('Name')).toBe('Some Application');
+            });
         }));
     });
 });
diff --git a/modules/print.cpp b/modules/print.cpp
index c6aaa26..9f029ef 100644
--- a/modules/print.cpp
+++ b/modules/print.cpp
@@ -206,7 +206,7 @@ static bool warn_deprecated_once_per_callsite(JSContext* cx, unsigned argc,
 
     if (args.length() == 1) {
         _gjs_warn_deprecated_once_per_callsite(
-            cx, GjsDeprecationMessageId(message_id));
+            cx, GjsDeprecationMessageId(message_id), 2);
         return true;
     }
 
@@ -225,7 +225,7 @@ static bool warn_deprecated_once_per_callsite(JSContext* cx, unsigned argc,
     }
 
     _gjs_warn_deprecated_once_per_callsite(
-        cx, GjsDeprecationMessageId(message_id), format_args);
+        cx, GjsDeprecationMessageId(message_id), format_args, 2);
     return true;
 }