141
123
context = gjs_runtime_get_current_context(trampoline->runtime);
143
JS_RemoveValueRoot(context, &trampoline->js_function);
125
if (!trampoline->is_vfunc)
126
JS_RemoveValueRoot(context, &trampoline->js_function);
144
127
g_callable_info_free_closure(trampoline->info, trampoline->closure);
145
128
g_base_info_unref( (GIBaseInfo*) trampoline->info);
129
g_free (trampoline->param_types);
146
130
g_slice_free(GjsCallbackTrampoline, trampoline);
236
223
g_assert(n_args >= 0);
238
226
jsargs = (jsval*)g_newa(jsval, n_args);
239
227
for (i = 0, n_jsargs = 0; i < n_args; i++) {
240
228
GIArgInfo arg_info;
241
229
GITypeInfo type_info;
230
GjsParamType param_type;
243
232
g_callable_info_load_arg(trampoline->info, i, &arg_info);
244
233
g_arg_info_load_type(&arg_info, &type_info);
247
236
if (g_type_info_get_tag(&type_info) == GI_TYPE_TAG_VOID)
250
if (!gjs_value_from_g_argument(context,
239
if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_OUT) {
244
if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_INOUT)
247
param_type = trampoline->param_types[i];
249
switch (param_type) {
253
gint array_length_pos = g_type_info_get_array_length(&type_info);
254
GIArgInfo array_length_arg;
255
GITypeInfo arg_type_info;
258
g_callable_info_load_arg(trampoline->info, array_length_pos, &array_length_arg);
259
g_arg_info_load_type(&array_length_arg, &arg_type_info);
260
if (!gjs_value_from_g_argument(context, &length,
262
args[array_length_pos], TRUE))
265
if (!gjs_value_from_explicit_array(context, &jsargs[n_jsargs++],
266
&type_info, args[i], JSVAL_TO_INT(length)))
271
if (!gjs_value_from_g_argument(context,
278
g_assert_not_reached();
282
if (trampoline->is_vfunc)
283
this_object = JSVAL_TO_OBJECT(jsargs[0]);
257
287
if (!JS_CallFunctionValue(context,
259
289
trampoline->js_function,
266
296
g_callable_info_load_return_type(trampoline->info, &ret_type);
268
if (!gjs_value_to_g_argument(context,
272
GJS_ARGUMENT_RETURN_VALUE,
297
ret_type_is_void = g_type_info_get_tag (&ret_type) == GI_TYPE_TAG_VOID;
299
if (n_outargs == 0 && !ret_type_is_void) {
302
/* non-void return value, no out args. Should
303
* be a single return value. */
304
if (!gjs_value_to_g_argument(context,
308
GJS_ARGUMENT_RETURN_VALUE,
314
set_return_ffi_arg_from_giargument(&ret_type,
317
} else if (n_outargs == 1 && ret_type_is_void) {
318
/* void return value, one out args. Should
319
* be a single return value. */
320
for (i = 0; i < n_args; i++) {
322
GITypeInfo type_info;
323
g_callable_info_load_arg(trampoline->info, i, &arg_info);
324
if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_IN)
327
g_arg_info_load_type(&arg_info, &type_info);
328
if (!gjs_value_to_g_argument(context,
332
GJS_ARGUMENT_ARGUMENT,
335
*(gpointer *)args[i]))
343
/* more than one of a return value or an out argument.
344
* Should be an array of output values. */
346
if (!ret_type_is_void) {
349
if (!JS_GetElement(context, JSVAL_TO_OBJECT(rval), elem_idx, &elem))
352
if (!gjs_value_to_g_argument(context,
356
GJS_ARGUMENT_ARGUMENT,
362
set_return_ffi_arg_from_giargument(&ret_type,
369
for (i = 0; i < n_args; i++) {
371
GITypeInfo type_info;
372
g_callable_info_load_arg(trampoline->info, i, &arg_info);
373
if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_IN)
376
g_arg_info_load_type(&arg_info, &type_info);
377
if (!JS_GetElement(context, JSVAL_TO_OBJECT(rval), elem_idx, &elem))
380
if (!gjs_value_to_g_argument(context,
384
GJS_ARGUMENT_ARGUMENT,
387
*(gpointer *)args[i]))
280
set_return_ffi_arg_from_giargument(&ret_type, result, &return_value);
309
421
gjs_callback_trampoline_unref(trampoline);
312
static GjsCallbackTrampoline*
424
GjsCallbackTrampoline*
313
425
gjs_callback_trampoline_new(JSContext *context,
315
427
GICallableInfo *callable_info,
318
431
GjsCallbackTrampoline *trampoline;
320
if (function == JSVAL_NULL) {
434
if (JSVAL_IS_NULL(function)) {
329
443
trampoline->info = callable_info;
330
444
g_base_info_ref((GIBaseInfo*)trampoline->info);
331
445
trampoline->js_function = function;
332
JS_AddValueRoot(context, &trampoline->js_function);
447
JS_AddValueRoot(context, &trampoline->js_function);
449
/* Analyze param types and directions, similarly to init_cached_function_data */
450
n_args = g_callable_info_get_n_args(trampoline->info);
451
trampoline->param_types = g_new0(GjsParamType, n_args);
453
for (i = 0; i < n_args; i++) {
454
GIDirection direction;
456
GITypeInfo type_info;
459
if (trampoline->param_types[i] == PARAM_SKIPPED)
462
g_callable_info_load_arg(trampoline->info, i, &arg_info);
463
g_arg_info_load_type(&arg_info, &type_info);
465
direction = g_arg_info_get_direction(&arg_info);
466
type_tag = g_type_info_get_tag(&type_info);
468
if (direction != GI_DIRECTION_IN) {
469
/* INOUT and OUT arguments are handled differently. */
473
if (type_tag == GI_TYPE_TAG_INTERFACE) {
474
GIBaseInfo* interface_info;
475
GIInfoType interface_type;
477
interface_info = g_type_info_get_interface(&type_info);
478
interface_type = g_base_info_get_type(interface_info);
479
if (interface_type == GI_INFO_TYPE_CALLBACK) {
480
gjs_throw(context, "Callback accepts another callback as a parameter. This is not supported");
481
g_base_info_unref(interface_info);
484
g_base_info_unref(interface_info);
485
} else if (type_tag == GI_TYPE_TAG_ARRAY) {
486
if (g_type_info_get_array_type(&type_info) == GI_ARRAY_TYPE_C) {
487
int array_length_pos = g_type_info_get_array_length(&type_info);
489
if (array_length_pos >= 0 && array_length_pos < n_args) {
490
GIArgInfo length_arg_info;
492
g_callable_info_load_arg(trampoline->info, array_length_pos, &length_arg_info);
493
if (g_arg_info_get_direction(&length_arg_info) != direction) {
494
gjs_throw(context, "Callback has an array with different-direction length arg, not supported");
498
trampoline->param_types[array_length_pos] = PARAM_SKIPPED;
499
trampoline->param_types[i] = PARAM_ARRAY;
333
505
trampoline->closure = g_callable_info_prepare_closure(callable_info, &trampoline->cif,
334
506
gjs_callback_closure, trampoline);
336
508
trampoline->scope = scope;
509
trampoline->is_vfunc = is_vfunc;
338
511
return trampoline;
502
677
completed_trampolines = NULL;
505
flags = g_function_info_get_flags(function->info);
506
is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
507
can_throw_gerror = (flags & GI_FUNCTION_THROWS) != 0;
680
info_type = g_base_info_get_type((GIBaseInfo *)function->info);
683
case GI_INFO_TYPE_FUNCTION:
685
GIFunctionInfoFlags flags;
686
flags = g_function_info_get_flags((GIFunctionInfo *)function->info);
687
is_method = (flags & GI_FUNCTION_IS_METHOD) != 0;
688
can_throw_gerror = (flags & GI_FUNCTION_THROWS) != 0;
691
case GI_INFO_TYPE_VFUNC:
693
GIVFuncInfoFlags flags;
694
flags = g_vfunc_info_get_flags ((GIVFuncInfo *)function->info);
695
can_throw_gerror = (flags & GI_VFUNC_THROWS) != 0;
699
case GI_INFO_TYPE_CALLBACK:
701
can_throw_gerror = FALSE;
704
g_assert_not_reached();
508
707
c_argc = function->invoker.cif.nargs;
509
708
gi_argc = g_callable_info_get_n_args( (GICallableInfo*) function->info);
560
759
in_arg_cvalues[0].v_pointer = gjs_g_object_from_object(context, obj);
760
if (in_arg_cvalues[0].v_pointer == NULL) {
761
/* priv == NULL (user probably forgot to chain _init).
762
* Anyway, in this case we've thrown an exception, so just
763
* make sure we fail. */
562
768
gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo *)container);
563
769
if (!g_type_is_a (G_TYPE_FROM_INSTANCE (in_arg_cvalues[0].v_pointer),
837
1044
array_length_pos += is_method ? 1 : 0;
838
1045
arg_failed = !gjs_value_from_g_argument(context, &length,
840
&out_arg_cvalues[array_length_pos]);
1047
&out_arg_cvalues[array_length_pos],
841
1049
if (!arg_failed) {
842
1050
arg_failed = !gjs_value_from_explicit_array(context,
843
1051
&return_values[next_rval],
856
1064
arg_failed = !gjs_value_from_g_argument(context, &return_values[next_rval],
857
&return_info, &return_gargument);
1065
&return_info, &return_gargument,
858
1067
/* Free GArgument, the jsval should have ref'd or copied it */
859
1068
if (!arg_failed &&
860
1069
!gjs_g_argument_release(context,
974
1183
array_length_pos += is_method ? 1 : 0;
975
1184
arg_failed = !gjs_value_from_g_argument(context, &array_length,
976
1185
&array_length_type_info,
977
&out_arg_cvalues[array_length_pos]);
1186
&out_arg_cvalues[array_length_pos],
978
1188
if (!arg_failed) {
979
1189
arg_failed = !gjs_value_from_explicit_array(context,
980
1190
&return_values[next_rval],
1095
1305
jsval *js_argv = JS_ARGV(context, vp);
1096
1306
JSObject *object = JS_THIS_OBJECT(context, vp);
1097
1307
JSObject *callee = JSVAL_TO_OBJECT(JS_CALLEE(context, vp));
1100
function_call(JSContext *context,
1101
JSObject *object, /* "this" object, not the function object */
1106
JSObject *callee = JSVAL_TO_OBJECT(JS_ARGV_CALLEE(js_argv));
1108
1308
JSBool success;
1109
1309
Function *priv;
1111
1312
priv = priv_from_js(context, callee);
1112
1313
gjs_debug_marshal(GJS_DEBUG_GFUNCTION, "Call callee %p priv %p this obj %p %s", callee, priv,
1117
1318
return JS_TRUE; /* we are the prototype, or have the wrong class */
1120
#ifdef JSFUN_CONSTRUCTOR
1123
success = gjs_invoke_c_function(context, priv, object, js_argc, js_argv, &retval);
1125
JS_SET_RVAL(context, vp, retval);
1128
success = gjs_invoke_c_function(context, priv, object, js_argc, js_argv, retval);
1321
success = gjs_invoke_c_function(context, priv, object, js_argc, js_argv, &retval);
1323
JS_SET_RVAL(context, vp, retval);
1130
1325
return success;
1133
/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
1134
* the prototype in addition to on each instance. When called on the
1135
* prototype, "obj" is the prototype, and "retval" is the prototype
1136
* also, but can be replaced with another object to use instead as the
1137
* prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
1138
* identify the prototype as an object of our class with NULL private
1141
#ifdef JSFUN_CONSTRUCTOR
1143
function_constructor(JSContext *context,
1148
if (!JS_IsConstructing_PossiblyWithGivenThisObject(context, vp, &object)) {
1149
gjs_throw_constructor_error(context);
1153
object = JS_NewObjectForConstructor(context, vp);
1156
function_constructor(JSContext *context,
1328
GJS_NATIVE_CONSTRUCTOR_DECLARE(function)
1330
GJS_NATIVE_CONSTRUCTOR_VARIABLES(function)
1163
1331
Function *priv;
1333
GJS_NATIVE_CONSTRUCTOR_PRELUDE(name);
1165
1335
priv = g_slice_new0(Function);
1167
1337
GJS_INC_COUNTER(function);
1172
1342
gjs_debug_lifecycle(GJS_DEBUG_GFUNCTION,
1173
1343
"function constructor, obj %p priv %p", object, priv);
1174
#ifdef JSFUN_CONSTRUCTOR
1175
JS_SET_RVAL(context, vp, OBJECT_TO_JSVAL(object));
1345
GJS_NATIVE_CONSTRUCTOR_FINISH(name);
1178
1347
return JS_TRUE;
1233
1402
if (priv == NULL) {
1234
1403
string = "function () {\n}";
1405
} else if (g_base_info_get_type(priv->info) == GI_INFO_TYPE_FUNCTION) {
1237
1406
string = g_strdup_printf("function %s(){\n\t/* proxy for native symbol %s(); */\n}",
1238
1407
g_base_info_get_name ((GIBaseInfo *) priv->info),
1239
g_function_info_get_symbol (priv->info));
1408
g_function_info_get_symbol ((GIFunctionInfo *) priv->info));
1411
string = g_strdup_printf("function %s(){\n\t/* proxy for native symbol */\n}",
1412
g_base_info_get_name ((GIBaseInfo *) priv->info));
1292
1465
static gboolean
1293
1466
init_cached_function_data (JSContext *context,
1294
1467
Function *function,
1295
GIFunctionInfo *info)
1469
GICallableInfo *info)
1297
1471
guint8 i, n_args, array_length_pos;
1298
1472
GError *error = NULL;
1299
1473
GITypeInfo return_type;
1301
if (!g_function_info_prep_invoker(info, &(function->invoker), &error)) {
1302
gjs_throw_g_error(context, error);
1474
GIInfoType info_type;
1476
info_type = g_base_info_get_type((GIBaseInfo *)info);
1478
if (info_type == GI_INFO_TYPE_FUNCTION) {
1479
if (!g_function_info_prep_invoker((GIFunctionInfo *)info,
1480
&(function->invoker),
1482
gjs_throw_g_error(context, error);
1485
} else if (info_type == GI_INFO_TYPE_VFUNC) {
1488
addr = g_vfunc_info_get_address((GIVFuncInfo *)info, gtype, &error);
1489
if (error != NULL) {
1490
if (error->code != G_INVOKE_ERROR_SYMBOL_NOT_FOUND)
1491
gjs_throw_g_error(context, error);
1496
if (!g_function_invoker_new_for_address(addr, info,
1497
&(function->invoker),
1499
gjs_throw_g_error(context, error);
1306
1504
g_callable_info_load_return_type((GICallableInfo*)info, &return_type);
1308
1506
function->js_out_argc += 1;
1310
1508
n_args = g_callable_info_get_n_args((GICallableInfo*) info);
1311
function->param_types = g_new0(ParamType, n_args);
1509
function->param_types = g_new0(GjsParamType, n_args);
1313
1511
array_length_pos = g_type_info_get_array_length(&return_type);
1314
1512
if (array_length_pos >= 0 && array_length_pos < n_args)
1476
1676
gjs_define_function(JSContext *context,
1477
1677
JSObject *in_object,
1478
GIFunctionInfo *info)
1679
GICallableInfo *info)
1681
JSObject *function = NULL;
1682
GIInfoType info_type;
1686
info_type = g_base_info_get_type((GIBaseInfo *)info);
1482
1688
JS_BeginRequest(context);
1484
function = function_new(context, info);
1690
function = function_new(context, gtype, info);
1485
1691
if (function == NULL) {
1486
1692
gjs_move_exception(context, context);
1492
if (!JS_DefineProperty(context, in_object,
1493
g_base_info_get_name( (GIBaseInfo*) info),
1698
if (info_type == GI_INFO_TYPE_FUNCTION) {
1699
name = (gchar *) g_base_info_get_name((GIBaseInfo*) info);
1701
} else if (info_type == GI_INFO_TYPE_VFUNC) {
1702
name = g_strdup_printf("vfunc_%s", g_base_info_get_name((GIBaseInfo*) info));
1705
g_assert_not_reached ();
1708
if (!JS_DefineProperty(context, in_object, name,
1494
1709
OBJECT_TO_JSVAL(function),
1496
1711
GJS_MODULE_PROP_FLAGS)) {
1519
1737
memset (&function, 0, sizeof (Function));
1520
if (!init_cached_function_data (context, &function, info))
1738
if (!init_cached_function_data (context, &function, 0, info))
1521
1739
return JS_FALSE;
1523
1741
result = gjs_invoke_c_function (context, &function, obj, argc, argv, rval);