|
7 | 7 |
|
8 | 8 | #include <jsinspector-modern/RuntimeTarget.h> |
9 | 9 |
|
| 10 | +#include <concepts> |
10 | 11 | #include <deque> |
11 | 12 | #include <string> |
12 | 13 |
|
@@ -99,6 +100,25 @@ double getTimestampMs() { |
99 | 100 | .count(); |
100 | 101 | } |
101 | 102 |
|
| 103 | +template <typename T> |
| 104 | +concept ConsoleMethodBody = std::invocable< |
| 105 | + T, |
| 106 | + jsi::Runtime& /*runtime*/, |
| 107 | + const jsi::Value* /*args*/, |
| 108 | + size_t /*count*/, |
| 109 | + RuntimeTargetDelegate& /*runtimeTargetDelegate*/, |
| 110 | + ConsoleState& /*state*/, |
| 111 | + double /*timestampMs*/, |
| 112 | + std::unique_ptr<StackTrace> /*stackTrace*/>; |
| 113 | + |
| 114 | +template <typename T> |
| 115 | +concept CallableAsHostFunction = std::invocable< |
| 116 | + T, |
| 117 | + jsi::Runtime& /*runtime*/, |
| 118 | + const jsi::Value& /*thisVal*/, |
| 119 | + const jsi::Value* /*args*/, |
| 120 | + size_t /*count*/>; |
| 121 | + |
102 | 122 | } // namespace |
103 | 123 |
|
104 | 124 | void RuntimeTarget::installConsoleHandler() { |
@@ -127,31 +147,30 @@ void RuntimeTarget::installConsoleHandler() { |
127 | 147 | * \warning The callback will not run if the RuntimeTarget has been |
128 | 148 | * destroyed. |
129 | 149 | */ |
130 | | - auto delegateExecutorSync = [selfWeak, selfExecutor](auto&& func) { |
131 | | - if (auto self = selfWeak.lock()) { |
132 | | - // Q: Why is it safe to use self->delegate_ here? |
133 | | - // A: Because the caller of InspectorTarget::registerRuntime |
134 | | - // is explicitly required to guarantee that the delegate not |
135 | | - // only outlives the target, but also outlives all JS code |
136 | | - // execution that occurs on the JS thread. |
137 | | - func(self->delegate_); |
138 | | - // To ensure we never destroy `self` on the JS thread, send |
139 | | - // our shared_ptr back to the inspector thread. |
140 | | - selfExecutor([self = std::move(self)](auto&) { (void)self; }); |
141 | | - } |
142 | | - }; |
| 150 | + auto delegateExecutorSync = |
| 151 | + [selfWeak, |
| 152 | + selfExecutor](std::invocable<RuntimeTargetDelegate&> auto func) { |
| 153 | + if (auto self = selfWeak.lock()) { |
| 154 | + // Q: Why is it safe to use self->delegate_ here? |
| 155 | + // A: Because the caller of InspectorTarget::registerRuntime |
| 156 | + // is explicitly required to guarantee that the delegate not |
| 157 | + // only outlives the target, but also outlives all JS code |
| 158 | + // execution that occurs on the JS thread. |
| 159 | + func(self->delegate_); |
| 160 | + // To ensure we never destroy `self` on the JS thread, send |
| 161 | + // our shared_ptr back to the inspector thread. |
| 162 | + selfExecutor([self = std::move(self)](auto&) { (void)self; }); |
| 163 | + } |
| 164 | + }; |
143 | 165 |
|
144 | 166 | /** |
145 | 167 | * Call \param innerFn and forward any arguments to the original console |
146 | 168 | * method named \param methodName, if possible. |
147 | 169 | */ |
148 | | - auto forwardToOriginalConsole = [originalConsole, delegateExecutorSync]( |
| 170 | + auto forwardToOriginalConsole = [originalConsole]( |
149 | 171 | const char* methodName, |
150 | | - auto&& innerFn) { |
151 | | - return [originalConsole, |
152 | | - delegateExecutorSync, |
153 | | - innerFn = std::forward<decltype(innerFn)>(innerFn), |
154 | | - methodName]( |
| 172 | + CallableAsHostFunction auto innerFn) { |
| 173 | + return [originalConsole, innerFn = std::move(innerFn), methodName]( |
155 | 174 | jsi::Runtime& runtime, |
156 | 175 | const jsi::Value& thisVal, |
157 | 176 | const jsi::Value* args, |
@@ -179,47 +198,38 @@ void RuntimeTarget::installConsoleHandler() { |
179 | 198 | * due to RuntimeTarget having been destroyed), the method of the same name |
180 | 199 | * is also called on originalConsole (if it exists). |
181 | 200 | */ |
182 | | - auto installConsoleMethod = |
183 | | - [&](const char* methodName, |
184 | | - std::function<void( |
185 | | - jsi::Runtime & runtime, |
186 | | - const jsi::Value* args, |
187 | | - size_t count, |
188 | | - RuntimeTargetDelegate& runtimeTargetDelegate, |
189 | | - ConsoleState& state, |
190 | | - double timestampMs, |
191 | | - std::unique_ptr<StackTrace> stackTrace)>&& body) { |
192 | | - console.setProperty( |
| 201 | + auto installConsoleMethod = [&](const char* methodName, |
| 202 | + ConsoleMethodBody auto body) { |
| 203 | + console.setProperty( |
| 204 | + runtime, |
| 205 | + methodName, |
| 206 | + jsi::Function::createFromHostFunction( |
193 | 207 | runtime, |
194 | | - methodName, |
195 | | - jsi::Function::createFromHostFunction( |
196 | | - runtime, |
197 | | - jsi::PropNameID::forAscii(runtime, methodName), |
198 | | - 0, |
199 | | - forwardToOriginalConsole( |
200 | | - methodName, |
201 | | - [body = std::move(body), state, delegateExecutorSync]( |
202 | | - jsi::Runtime& runtime, |
203 | | - const jsi::Value& /*thisVal*/, |
204 | | - const jsi::Value* args, |
205 | | - size_t count) { |
206 | | - auto timestampMs = getTimestampMs(); |
207 | | - delegateExecutorSync([&](auto& runtimeTargetDelegate) { |
208 | | - auto stackTrace = |
209 | | - runtimeTargetDelegate.captureStackTrace( |
210 | | - runtime, /* framesToSkip */ 1); |
211 | | - body( |
212 | | - runtime, |
213 | | - args, |
214 | | - count, |
215 | | - runtimeTargetDelegate, |
216 | | - *state, |
217 | | - timestampMs, |
218 | | - std::move(stackTrace)); |
219 | | - }); |
220 | | - return jsi::Value::undefined(); |
221 | | - }))); |
222 | | - }; |
| 208 | + jsi::PropNameID::forAscii(runtime, methodName), |
| 209 | + 0, |
| 210 | + forwardToOriginalConsole( |
| 211 | + methodName, |
| 212 | + [body = std::move(body), state, delegateExecutorSync]( |
| 213 | + jsi::Runtime& runtime, |
| 214 | + const jsi::Value& /*thisVal*/, |
| 215 | + const jsi::Value* args, |
| 216 | + size_t count) { |
| 217 | + auto timestampMs = getTimestampMs(); |
| 218 | + delegateExecutorSync([&](auto& runtimeTargetDelegate) { |
| 219 | + auto stackTrace = runtimeTargetDelegate.captureStackTrace( |
| 220 | + runtime, /* framesToSkip */ 1); |
| 221 | + body( |
| 222 | + runtime, |
| 223 | + args, |
| 224 | + count, |
| 225 | + runtimeTargetDelegate, |
| 226 | + *state, |
| 227 | + timestampMs, |
| 228 | + std::move(stackTrace)); |
| 229 | + }); |
| 230 | + return jsi::Value::undefined(); |
| 231 | + }))); |
| 232 | + }; |
223 | 233 |
|
224 | 234 | /** |
225 | 235 | * console.count |
|
0 commit comments