MCPcopy Create free account
hub / github.com/GNOME/gjs / callback_closure

Method callback_closure

gi/function.cpp:302–413  ·  view source on GitHub ↗

This is our main entry point for ffi_closure callbacks. ffi_prep_closure() is * doing pure magic and replaces the original function call with this one which * gives us the ffi arguments, a place to store the return value and our use * data. In other words, everything we need to call the JS function and get the * return value back. */

Source from the content-addressed store, hash-verified

300 * return value back.
301 */
302void GjsCallbackTrampoline::callback_closure(GIArgument** args, void* result) {
303 GI::StackTypeInfo ret_type;
304
305 // Fill in the result with some hopefully neutral value
306 m_info.load_return_type(&ret_type);
307 if (ret_type.tag() != GI_TYPE_TAG_VOID) {
308 GIArgument argument = {};
309 gjs_arg_unset(&argument);
310 set_return_ffi_arg_from_gi_argument(ret_type, result, &argument);
311 }
312
313 if (G_UNLIKELY(!is_valid())) {
314 warn_about_illegal_js_callback(
315 "during shutdown",
316 "destroying a Clutter actor or GTK widget with ::destroy signal "
317 "connected, or using the destroy(), dispose(), or remove() vfuncs",
318 true);
319 return;
320 }
321
322 JSContext* cx = this->cx();
323 GjsContextPrivate* gjs = GjsContextPrivate::from_cx(cx);
324 if (JS::RuntimeHeapIsCollecting()) {
325 warn_about_illegal_js_callback(
326 "during garbage collection",
327 "destroying a Clutter actor or GTK widget with ::destroy signal "
328 "connected, or using the destroy(), dispose(), or remove() vfuncs",
329 true);
330 return;
331 }
332
333 if (G_UNLIKELY(!gjs->is_owner_thread())) {
334 warn_about_illegal_js_callback("on a different thread",
335 "an API not intended to be used in JS",
336 false);
337 return;
338 }
339
340 JSAutoRealm ar{cx, callable()};
341
342 unsigned n_args = m_info.n_args();
343
344 auto cleanup = mozilla::MakeScopeExit([this, gjs]() {
345 if (this->m_scope == GI_SCOPE_TYPE_ASYNC) {
346 // We don't release the trampoline here as we've an extra ref that
347 // has been set in gjs_marshal_callback_in()
348 gjs_debug_closure("Saving async closure for gc cleanup %p", this);
349 gjs->async_closure_enqueue_for_gc(this);
350 }
351 gjs->schedule_gc_if_needed();
352 });
353
354 JS::RootedObject this_object{cx};
355 unsigned c_args_offset = 0;
356 GObject* gobj = nullptr;
357 if (m_is_vfunc) {
358 gobj = G_OBJECT(gjs_arg_get<GObject*>(args[0]));
359 if (gobj) {

Callers 1

Calls 15

gjs_arg_unsetFunction · 0.85
gjs_log_exceptionFunction · 0.85
gjs_debug_callableFunction · 0.85
load_return_typeMethod · 0.80
cxMethod · 0.80
is_owner_threadMethod · 0.80
n_argsMethod · 0.80
schedule_gc_if_neededMethod · 0.80

Tested by

no test coverage detected