node-gtk 0.8.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/binding.gyp +36 -17
- package/lib/binding/node-v93-linux-x64/node_gtk.node +0 -0
- package/lib/bootstrap.js +0 -21
- package/package.json +9 -9
- package/scripts/ci.sh +0 -0
- package/src/boxed.cc +3 -3
- package/src/callback.cc +8 -9
- package/src/closure.cc +5 -5
- package/src/closure.h +2 -2
- package/src/debug.cc +2 -2
- package/src/function.cc +225 -333
- package/src/function.h +1 -2
- package/src/gi.cc +17 -35
- package/src/gobject.cc +9 -5
- package/src/loop.cc +9 -0
- package/src/modules/cairo/context.cc +102 -106
- package/src/modules/cairo/generator.js +1 -5
- package/src/type.cc +5 -5
- package/src/value.cc +114 -35
- package/src/value.h +1 -1
- package/CHANGELOG.md +0 -25
package/src/function.cc
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
#include <string.h>
|
|
3
2
|
#include <girffi.h>
|
|
4
3
|
|
|
@@ -44,8 +43,8 @@ static int GetV8ArrayLength (Local<Value> value) {
|
|
|
44
43
|
else if (value->IsNull() || value->IsUndefined())
|
|
45
44
|
return 0;
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
ERROR("Could not determine array length for value %s",
|
|
47
|
+
*Nan::Utf8String(TO_STRING (value)));
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
static void* AllocateArgument (GIBaseInfo *arg_info) {
|
|
@@ -56,7 +55,7 @@ static void* AllocateArgument (GIBaseInfo *arg_info) {
|
|
|
56
55
|
|
|
57
56
|
GIBaseInfo* base_info = g_type_info_get_interface (&arg_type);
|
|
58
57
|
size_t size = Boxed::GetSize (base_info);
|
|
59
|
-
void* pointer =
|
|
58
|
+
void* pointer = g_malloc0(size);
|
|
60
59
|
|
|
61
60
|
g_base_info_unref(base_info);
|
|
62
61
|
return pointer;
|
|
@@ -106,7 +105,196 @@ bool IsDestroyNotify (GIBaseInfo *info) {
|
|
|
106
105
|
|
|
107
106
|
|
|
108
107
|
/**
|
|
109
|
-
*
|
|
108
|
+
* The constructor just stores the GIBaseInfo ref. The rest of the
|
|
109
|
+
* initialization is done in FunctionInfo::Init, lazily.
|
|
110
|
+
*/
|
|
111
|
+
FunctionInfo::FunctionInfo (GIBaseInfo* gi_info) {
|
|
112
|
+
info = g_base_info_ref (gi_info);
|
|
113
|
+
call_parameters = nullptr;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
FunctionInfo::~FunctionInfo () {
|
|
117
|
+
g_base_info_unref (info);
|
|
118
|
+
|
|
119
|
+
if (call_parameters != nullptr) {
|
|
120
|
+
g_function_invoker_destroy (&invoker);
|
|
121
|
+
delete[] call_parameters;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Initializes the parameters metadata (number, directionality, type) and caches it
|
|
127
|
+
*/
|
|
128
|
+
bool FunctionInfo::Init() {
|
|
129
|
+
|
|
130
|
+
if (call_parameters != nullptr)
|
|
131
|
+
return true;
|
|
132
|
+
|
|
133
|
+
g_function_info_prep_invoker (info, &invoker, NULL);
|
|
134
|
+
|
|
135
|
+
is_method = IsMethod(info);
|
|
136
|
+
can_throw = g_callable_info_can_throw_gerror (info);
|
|
137
|
+
|
|
138
|
+
n_callable_args = g_callable_info_get_n_args (info);
|
|
139
|
+
n_total_args = n_callable_args;
|
|
140
|
+
n_out_args = 0;
|
|
141
|
+
n_in_args = 0;
|
|
142
|
+
|
|
143
|
+
if (is_method)
|
|
144
|
+
n_total_args++;
|
|
145
|
+
|
|
146
|
+
if (can_throw)
|
|
147
|
+
n_total_args++;
|
|
148
|
+
|
|
149
|
+
call_parameters = new Parameter[n_callable_args]();
|
|
150
|
+
|
|
151
|
+
/*
|
|
152
|
+
* Examine load parameter types and count arguments
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
for (int i = 0; i < n_callable_args; i++) {
|
|
156
|
+
GIArgInfo arg_info;
|
|
157
|
+
GITypeInfo type_info;
|
|
158
|
+
g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
|
|
159
|
+
g_arg_info_load_type (&arg_info, &type_info);
|
|
160
|
+
|
|
161
|
+
bool may_be_null = g_arg_info_may_be_null (&arg_info);
|
|
162
|
+
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
163
|
+
GITypeTag tag = g_type_info_get_tag(&type_info);
|
|
164
|
+
|
|
165
|
+
call_parameters[i].direction = direction;
|
|
166
|
+
|
|
167
|
+
if (call_parameters[i].type == ParameterType::kSKIP)
|
|
168
|
+
continue;
|
|
169
|
+
|
|
170
|
+
// If there is an array length, this is an array
|
|
171
|
+
int length_i = g_type_info_get_array_length (&type_info);
|
|
172
|
+
if (tag == GI_TYPE_TAG_ARRAY && length_i >= 0) {
|
|
173
|
+
call_parameters[i].type = ParameterType::kARRAY;
|
|
174
|
+
call_parameters[length_i].type = ParameterType::kSKIP;
|
|
175
|
+
|
|
176
|
+
// If array length came before, we need to remove it from args count
|
|
177
|
+
|
|
178
|
+
if (IsDirectionIn(call_parameters[length_i].direction) && length_i < i)
|
|
179
|
+
n_in_args--;
|
|
180
|
+
|
|
181
|
+
if (IsDirectionOut(call_parameters[length_i].direction) && length_i < i)
|
|
182
|
+
n_out_args--;
|
|
183
|
+
|
|
184
|
+
} else if (tag == GI_TYPE_TAG_INTERFACE) {
|
|
185
|
+
|
|
186
|
+
GIBaseInfo* interface_info = g_type_info_get_interface(&type_info);
|
|
187
|
+
GIInfoType interface_type = g_base_info_get_type(interface_info);
|
|
188
|
+
|
|
189
|
+
if (interface_type == GI_INFO_TYPE_CALLBACK) {
|
|
190
|
+
if (IsDestroyNotify(interface_info)) {
|
|
191
|
+
/* Skip GDestroyNotify if they appear before the respective callback */
|
|
192
|
+
call_parameters[i].type = ParameterType::kSKIP;
|
|
193
|
+
} else {
|
|
194
|
+
call_parameters[i].type = ParameterType::kCALLBACK;
|
|
195
|
+
|
|
196
|
+
int destroy_i = g_arg_info_get_destroy(&arg_info);
|
|
197
|
+
int closure_i = g_arg_info_get_closure(&arg_info);
|
|
198
|
+
|
|
199
|
+
if (destroy_i >= 0 && closure_i < 0) {
|
|
200
|
+
Throw::UnsupportedCallback (info);
|
|
201
|
+
g_base_info_unref(interface_info);
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (destroy_i >= 0 && destroy_i < n_callable_args)
|
|
206
|
+
call_parameters[destroy_i].type = ParameterType::kSKIP;
|
|
207
|
+
|
|
208
|
+
if (closure_i >= 0 && closure_i < n_callable_args)
|
|
209
|
+
call_parameters[closure_i].type = ParameterType::kSKIP;
|
|
210
|
+
|
|
211
|
+
if (destroy_i < i) {
|
|
212
|
+
if (IsDirectionIn(call_parameters[destroy_i].direction))
|
|
213
|
+
n_in_args--;
|
|
214
|
+
if (IsDirectionOut(call_parameters[destroy_i].direction))
|
|
215
|
+
n_out_args--;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (closure_i < i) {
|
|
219
|
+
if (IsDirectionIn(call_parameters[closure_i].direction))
|
|
220
|
+
n_in_args--;
|
|
221
|
+
if (IsDirectionOut(call_parameters[closure_i].direction))
|
|
222
|
+
n_out_args--;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
g_base_info_unref(interface_info);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (IsDirectionIn(call_parameters[i].direction) && !may_be_null)
|
|
231
|
+
n_in_args++;
|
|
232
|
+
|
|
233
|
+
if (IsDirectionOut(call_parameters[i].direction))
|
|
234
|
+
n_out_args++;
|
|
235
|
+
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/*
|
|
239
|
+
* Examine return type
|
|
240
|
+
*/
|
|
241
|
+
|
|
242
|
+
GITypeInfo return_type;
|
|
243
|
+
g_callable_info_load_return_type(info, &return_type);
|
|
244
|
+
int return_length_i = g_type_info_get_array_length(&return_type);
|
|
245
|
+
|
|
246
|
+
if (return_length_i != -1)
|
|
247
|
+
n_out_args--;
|
|
248
|
+
|
|
249
|
+
if (!ShouldSkipReturn(info, &return_type))
|
|
250
|
+
n_out_args++;
|
|
251
|
+
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Type checks the JS arguments, throwing an error.
|
|
257
|
+
* @returns true if types match
|
|
258
|
+
*/
|
|
259
|
+
bool FunctionInfo::TypeCheck (const Nan::FunctionCallbackInfo<Value> &arguments) {
|
|
260
|
+
|
|
261
|
+
if (arguments.Length() < n_in_args) {
|
|
262
|
+
Throw::NotEnoughArguments(n_in_args, arguments.Length());
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/*
|
|
267
|
+
* Type check every IN-argument that is not skipped
|
|
268
|
+
*/
|
|
269
|
+
|
|
270
|
+
for (int in_arg = 0, i = 0; i < n_callable_args; i++) {
|
|
271
|
+
Parameter ¶m = call_parameters[i];
|
|
272
|
+
|
|
273
|
+
if (param.type == ParameterType::kSKIP)
|
|
274
|
+
continue;
|
|
275
|
+
|
|
276
|
+
GIArgInfo arg_info;
|
|
277
|
+
g_callable_info_load_arg (info, i, &arg_info);
|
|
278
|
+
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
279
|
+
|
|
280
|
+
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
|
|
281
|
+
GITypeInfo type_info;
|
|
282
|
+
g_arg_info_load_type (&arg_info, &type_info);
|
|
283
|
+
bool may_be_null = g_arg_info_may_be_null (&arg_info);
|
|
284
|
+
|
|
285
|
+
if (!CanConvertV8ToGIArgument(&type_info, arguments[in_arg], may_be_null)) {
|
|
286
|
+
Throw::InvalidType(&arg_info, &type_info, arguments[in_arg]);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
in_arg++;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Calls a C function from JS arguments
|
|
110
298
|
* @param func the function info
|
|
111
299
|
* @param info JS call informations
|
|
112
300
|
* @param return_value (out, nullable) the C return value
|
|
@@ -119,19 +307,12 @@ Local<Value> FunctionCall (
|
|
|
119
307
|
GIArgument *return_value,
|
|
120
308
|
GError **error
|
|
121
309
|
) {
|
|
122
|
-
/* FIXME(return_value is never use) */
|
|
123
310
|
|
|
124
311
|
Local<Value> jsReturnValue;
|
|
125
312
|
GIBaseInfo *gi_info = func->info; // do-not-free
|
|
126
313
|
bool use_return_value = return_value != NULL;
|
|
127
314
|
bool use_error = error != NULL;
|
|
128
315
|
|
|
129
|
-
// bool debug_mode = strcmp(g_base_info_get_name(gi_info), "parse") == 0;
|
|
130
|
-
bool debug_mode = false;
|
|
131
|
-
|
|
132
|
-
if (debug_mode)
|
|
133
|
-
print_callable_info(gi_info);
|
|
134
|
-
|
|
135
316
|
if (!func->Init())
|
|
136
317
|
return jsReturnValue;
|
|
137
318
|
|
|
@@ -143,7 +324,12 @@ Local<Value> FunctionCall (
|
|
|
143
324
|
* and for error, if it can throw
|
|
144
325
|
*/
|
|
145
326
|
|
|
146
|
-
|
|
327
|
+
#ifndef __linux__
|
|
328
|
+
GIArgument *total_arg_values = new GIArgument[func->n_total_args]();
|
|
329
|
+
#else
|
|
330
|
+
GIArgument total_arg_values[func->n_total_args];
|
|
331
|
+
#endif
|
|
332
|
+
|
|
147
333
|
GIArgument *callable_arg_values;
|
|
148
334
|
GError *error_stack = nullptr;
|
|
149
335
|
|
|
@@ -158,7 +344,6 @@ Local<Value> FunctionCall (
|
|
|
158
344
|
if (func->can_throw)
|
|
159
345
|
callable_arg_values[func->n_callable_args].v_pointer = error != NULL ? error : &error_stack;
|
|
160
346
|
|
|
161
|
-
|
|
162
347
|
/*
|
|
163
348
|
* Second, allocate OUT-arguments and fill IN-arguments
|
|
164
349
|
*/
|
|
@@ -166,7 +351,7 @@ Local<Value> FunctionCall (
|
|
|
166
351
|
for (int in_arg = 0, i = 0; i < func->n_callable_args; i++) {
|
|
167
352
|
Parameter& param = func->call_parameters[i];
|
|
168
353
|
|
|
169
|
-
if (param.type == ParameterType::
|
|
354
|
+
if (param.type == ParameterType::kSKIP)
|
|
170
355
|
continue;
|
|
171
356
|
|
|
172
357
|
GIArgInfo arg_info;
|
|
@@ -175,7 +360,7 @@ Local<Value> FunctionCall (
|
|
|
175
360
|
g_arg_info_load_type (&arg_info, &type_info);
|
|
176
361
|
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
177
362
|
|
|
178
|
-
if (param.type == ParameterType::
|
|
363
|
+
if (param.type == ParameterType::kARRAY) {
|
|
179
364
|
GIArgInfo array_length_arg;
|
|
180
365
|
GITypeInfo array_length_type;
|
|
181
366
|
|
|
@@ -201,8 +386,7 @@ Local<Value> FunctionCall (
|
|
|
201
386
|
callable_arg_values[length_i].v_pointer = &len_param.data;
|
|
202
387
|
}
|
|
203
388
|
}
|
|
204
|
-
else if (param.type == ParameterType::
|
|
205
|
-
// GIScopeType scope = g_arg_info_get_scope(&arg_info);
|
|
389
|
+
else if (param.type == ParameterType::kCALLBACK) {
|
|
206
390
|
Callback *callback;
|
|
207
391
|
ffi_closure *closure;
|
|
208
392
|
|
|
@@ -221,12 +405,12 @@ Local<Value> FunctionCall (
|
|
|
221
405
|
int closure_i = g_arg_info_get_closure(&arg_info);
|
|
222
406
|
|
|
223
407
|
if (destroy_i >= 0) {
|
|
224
|
-
g_assert (func->call_parameters[destroy_i].type == ParameterType::
|
|
408
|
+
g_assert (func->call_parameters[destroy_i].type == ParameterType::kSKIP);
|
|
225
409
|
callable_arg_values[destroy_i].v_pointer = callback ? (void*) Callback::DestroyNotify : NULL;
|
|
226
410
|
}
|
|
227
411
|
|
|
228
412
|
if (closure_i >= 0) {
|
|
229
|
-
g_assert (func->call_parameters[closure_i].type == ParameterType::
|
|
413
|
+
g_assert (func->call_parameters[closure_i].type == ParameterType::kSKIP);
|
|
230
414
|
callable_arg_values[closure_i].v_pointer = callback;
|
|
231
415
|
}
|
|
232
416
|
|
|
@@ -245,7 +429,7 @@ Local<Value> FunctionCall (
|
|
|
245
429
|
else /* (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) */ {
|
|
246
430
|
|
|
247
431
|
// Callback GIArgument is filled above, for the rest...
|
|
248
|
-
if (param.type != ParameterType::
|
|
432
|
+
if (param.type != ParameterType::kCALLBACK) {
|
|
249
433
|
|
|
250
434
|
// FIXME(handle failure here)
|
|
251
435
|
FillArgument(&arg_info, &callable_arg_values[i], info[in_arg]);
|
|
@@ -267,16 +451,24 @@ Local<Value> FunctionCall (
|
|
|
267
451
|
* Third, make the actual ffi_call
|
|
268
452
|
*/
|
|
269
453
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
454
|
+
#ifndef __linux__
|
|
455
|
+
void **ffi_args = new void*[func->n_total_args]();
|
|
456
|
+
#else
|
|
457
|
+
void *ffi_args[func->n_total_args];
|
|
458
|
+
#endif
|
|
273
459
|
|
|
460
|
+
for (int i = 0; i < func->n_total_args; i++)
|
|
461
|
+
ffi_args[i] = (void *)&total_arg_values[i];
|
|
274
462
|
|
|
275
|
-
GIArgument return_value_stack;
|
|
463
|
+
GIArgument return_value_stack = {0};
|
|
276
464
|
|
|
277
465
|
ffi_call (&func->invoker.cif, FFI_FN (func->invoker.native_address),
|
|
278
466
|
use_return_value ? return_value : &return_value_stack, ffi_args);
|
|
279
467
|
|
|
468
|
+
#ifndef __linux__
|
|
469
|
+
delete[] ffi_args;
|
|
470
|
+
#endif
|
|
471
|
+
|
|
280
472
|
|
|
281
473
|
/*
|
|
282
474
|
* Fourth, convert the return value & OUT-arguments back to JS
|
|
@@ -326,13 +518,13 @@ Local<Value> FunctionCall (
|
|
|
326
518
|
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
327
519
|
GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
|
|
328
520
|
|
|
329
|
-
if (param.type == ParameterType::
|
|
521
|
+
if (param.type == ParameterType::kARRAY) {
|
|
330
522
|
if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT)
|
|
331
523
|
FreeGIArgumentArray (&arg_type, (GIArgument*)arg_value.v_pointer, transfer, direction, param.length);
|
|
332
524
|
else
|
|
333
525
|
FreeGIArgumentArray (&arg_type, &arg_value, transfer, direction, param.length);
|
|
334
526
|
}
|
|
335
|
-
else if (param.type == ParameterType::
|
|
527
|
+
else if (param.type == ParameterType::kCALLBACK) {
|
|
336
528
|
Callback *callback = static_cast<Callback*>(func->call_parameters[i].data.v_pointer);
|
|
337
529
|
|
|
338
530
|
g_assert(direction == GI_DIRECTION_IN);
|
|
@@ -349,198 +541,13 @@ Local<Value> FunctionCall (
|
|
|
349
541
|
}
|
|
350
542
|
}
|
|
351
543
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* The constructor just stores the GIBaseInfo ref. The rest of the
|
|
358
|
-
* initialization is done in FunctionInfo::Init, lazily.
|
|
359
|
-
*/
|
|
360
|
-
FunctionInfo::FunctionInfo (GIBaseInfo* gi_info) {
|
|
361
|
-
info = g_base_info_ref (gi_info);
|
|
362
|
-
call_parameters = nullptr;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
FunctionInfo::~FunctionInfo () {
|
|
366
|
-
g_base_info_unref (info);
|
|
367
|
-
|
|
368
|
-
if (call_parameters != nullptr) {
|
|
369
|
-
g_function_invoker_destroy (&invoker);
|
|
370
|
-
delete[] call_parameters;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Initializes the function calling data.
|
|
376
|
-
*/
|
|
377
|
-
bool FunctionInfo::Init() {
|
|
378
|
-
|
|
379
|
-
if (call_parameters != nullptr)
|
|
380
|
-
return true;
|
|
381
|
-
|
|
382
|
-
g_function_info_prep_invoker (info, &invoker, NULL);
|
|
383
|
-
|
|
384
|
-
is_method = IsMethod(info);
|
|
385
|
-
can_throw = g_callable_info_can_throw_gerror (info);
|
|
386
|
-
|
|
387
|
-
n_callable_args = g_callable_info_get_n_args (info);
|
|
388
|
-
n_total_args = n_callable_args;
|
|
389
|
-
n_out_args = 0;
|
|
390
|
-
n_in_args = 0;
|
|
391
|
-
|
|
392
|
-
if (is_method)
|
|
393
|
-
n_total_args++;
|
|
394
|
-
|
|
395
|
-
if (can_throw)
|
|
396
|
-
n_total_args++;
|
|
397
|
-
|
|
398
|
-
call_parameters = new Parameter[n_callable_args]();
|
|
399
|
-
|
|
400
|
-
/*
|
|
401
|
-
* Examine load parameter types and count arguments
|
|
402
|
-
*/
|
|
403
|
-
|
|
404
|
-
for (int i = 0; i < n_callable_args; i++) {
|
|
405
|
-
GIArgInfo arg_info;
|
|
406
|
-
GITypeInfo type_info;
|
|
407
|
-
g_callable_info_load_arg ((GICallableInfo *) info, i, &arg_info);
|
|
408
|
-
g_arg_info_load_type (&arg_info, &type_info);
|
|
409
|
-
|
|
410
|
-
bool may_be_null = g_arg_info_may_be_null (&arg_info);
|
|
411
|
-
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
412
|
-
GITypeTag tag = g_type_info_get_tag(&type_info);
|
|
413
|
-
|
|
414
|
-
call_parameters[i].direction = direction;
|
|
415
|
-
|
|
416
|
-
if (call_parameters[i].type == ParameterType::SKIP)
|
|
417
|
-
continue;
|
|
418
|
-
|
|
419
|
-
// If there is an array length, this is an array
|
|
420
|
-
int length_i = g_type_info_get_array_length (&type_info);
|
|
421
|
-
if (tag == GI_TYPE_TAG_ARRAY && length_i >= 0) {
|
|
422
|
-
call_parameters[i].type = ParameterType::ARRAY;
|
|
423
|
-
call_parameters[length_i].type = ParameterType::SKIP;
|
|
424
|
-
|
|
425
|
-
// If array length came before, we need to remove it from args count
|
|
426
|
-
|
|
427
|
-
if (IsDirectionIn(call_parameters[length_i].direction) && length_i < i)
|
|
428
|
-
n_in_args--;
|
|
429
|
-
|
|
430
|
-
if (IsDirectionOut(call_parameters[length_i].direction) && length_i < i)
|
|
431
|
-
n_out_args--;
|
|
432
|
-
|
|
433
|
-
} else if (tag == GI_TYPE_TAG_INTERFACE) {
|
|
434
|
-
|
|
435
|
-
GIBaseInfo* interface_info = g_type_info_get_interface(&type_info);
|
|
436
|
-
GIInfoType interface_type = g_base_info_get_type(interface_info);
|
|
437
|
-
|
|
438
|
-
if (interface_type == GI_INFO_TYPE_CALLBACK) {
|
|
439
|
-
if (IsDestroyNotify(interface_info)) {
|
|
440
|
-
/* Skip GDestroyNotify if they appear before the respective callback */
|
|
441
|
-
call_parameters[i].type = ParameterType::SKIP;
|
|
442
|
-
} else {
|
|
443
|
-
call_parameters[i].type = ParameterType::CALLBACK;
|
|
444
|
-
|
|
445
|
-
int destroy_i = g_arg_info_get_destroy(&arg_info);
|
|
446
|
-
int closure_i = g_arg_info_get_closure(&arg_info);
|
|
447
|
-
|
|
448
|
-
if (destroy_i >= 0 && closure_i < 0) {
|
|
449
|
-
Throw::UnsupportedCallback (info);
|
|
450
|
-
g_base_info_unref(interface_info);
|
|
451
|
-
return false;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (destroy_i >= 0 && destroy_i < n_callable_args)
|
|
455
|
-
call_parameters[destroy_i].type = ParameterType::SKIP;
|
|
456
|
-
|
|
457
|
-
if (closure_i >= 0 && closure_i < n_callable_args)
|
|
458
|
-
call_parameters[closure_i].type = ParameterType::SKIP;
|
|
459
|
-
|
|
460
|
-
if (destroy_i < i) {
|
|
461
|
-
if (IsDirectionIn(call_parameters[destroy_i].direction))
|
|
462
|
-
n_in_args--;
|
|
463
|
-
if (IsDirectionOut(call_parameters[destroy_i].direction))
|
|
464
|
-
n_out_args--;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (closure_i < i) {
|
|
468
|
-
if (IsDirectionIn(call_parameters[closure_i].direction))
|
|
469
|
-
n_in_args--;
|
|
470
|
-
if (IsDirectionOut(call_parameters[closure_i].direction))
|
|
471
|
-
n_out_args--;
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
g_base_info_unref(interface_info);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (IsDirectionIn(call_parameters[i].direction) && !may_be_null)
|
|
480
|
-
n_in_args++;
|
|
481
|
-
|
|
482
|
-
if (IsDirectionOut(call_parameters[i].direction))
|
|
483
|
-
n_out_args++;
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
/*
|
|
488
|
-
* Examine return type
|
|
489
|
-
*/
|
|
490
|
-
|
|
491
|
-
GITypeInfo return_type;
|
|
492
|
-
g_callable_info_load_return_type(info, &return_type);
|
|
493
|
-
int return_length_i = g_type_info_get_array_length(&return_type);
|
|
494
|
-
|
|
495
|
-
if (return_length_i != -1)
|
|
496
|
-
n_out_args--;
|
|
544
|
+
#ifndef __linux__
|
|
545
|
+
delete[] total_arg_values;
|
|
546
|
+
#endif
|
|
497
547
|
|
|
498
|
-
|
|
499
|
-
n_out_args++;
|
|
500
|
-
|
|
501
|
-
return true;
|
|
548
|
+
return jsReturnValue;
|
|
502
549
|
}
|
|
503
550
|
|
|
504
|
-
/**
|
|
505
|
-
* Type checks the JS arguments, throwing an error.
|
|
506
|
-
* @returns true if types match
|
|
507
|
-
*/
|
|
508
|
-
bool FunctionInfo::TypeCheck (const Nan::FunctionCallbackInfo<Value> &arguments) {
|
|
509
|
-
|
|
510
|
-
if (arguments.Length() < n_in_args) {
|
|
511
|
-
Throw::NotEnoughArguments(n_in_args, arguments.Length());
|
|
512
|
-
return false;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
/*
|
|
516
|
-
* Type check every IN-argument that is not skipped
|
|
517
|
-
*/
|
|
518
|
-
|
|
519
|
-
for (int in_arg = 0, i = 0; i < n_callable_args; i++) {
|
|
520
|
-
Parameter ¶m = call_parameters[i];
|
|
521
|
-
|
|
522
|
-
if (param.type == ParameterType::SKIP)
|
|
523
|
-
continue;
|
|
524
|
-
|
|
525
|
-
GIArgInfo arg_info;
|
|
526
|
-
g_callable_info_load_arg (info, i, &arg_info);
|
|
527
|
-
GIDirection direction = g_arg_info_get_direction (&arg_info);
|
|
528
|
-
|
|
529
|
-
if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
|
|
530
|
-
GITypeInfo type_info;
|
|
531
|
-
g_arg_info_load_type (&arg_info, &type_info);
|
|
532
|
-
bool may_be_null = g_arg_info_may_be_null (&arg_info);
|
|
533
|
-
|
|
534
|
-
if (!CanConvertV8ToGIArgument(&type_info, arguments[in_arg], may_be_null)) {
|
|
535
|
-
Throw::InvalidType(&arg_info, &type_info, arguments[in_arg]);
|
|
536
|
-
return false;
|
|
537
|
-
}
|
|
538
|
-
in_arg++;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
return true;
|
|
543
|
-
}
|
|
544
551
|
|
|
545
552
|
/**
|
|
546
553
|
* Creates the JS return value from the C arguments list
|
|
@@ -603,7 +610,7 @@ Local<Value> FunctionInfo::GetReturnValue (
|
|
|
603
610
|
|
|
604
611
|
if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
|
|
605
612
|
|
|
606
|
-
if (param.type == ParameterType::
|
|
613
|
+
if (param.type == ParameterType::kARRAY) {
|
|
607
614
|
|
|
608
615
|
int length_i = g_type_info_get_array_length(&arg_type);
|
|
609
616
|
GIArgInfo length_arg;
|
|
@@ -622,7 +629,7 @@ Local<Value> FunctionInfo::GetReturnValue (
|
|
|
622
629
|
|
|
623
630
|
ADD_RETURN (result)
|
|
624
631
|
|
|
625
|
-
} else if (param.type == ParameterType::
|
|
632
|
+
} else if (param.type == ParameterType::kNORMAL) {
|
|
626
633
|
|
|
627
634
|
if (IsPointerType(&arg_type) && g_arg_info_is_caller_allocates(&arg_info)) {
|
|
628
635
|
void *pointer = &arg_value.v_pointer;
|
|
@@ -681,7 +688,6 @@ void FunctionInvoker(const Nan::FunctionCallbackInfo<Value> &info) {
|
|
|
681
688
|
RETURN (jsReturnValue);
|
|
682
689
|
}
|
|
683
690
|
|
|
684
|
-
// see src/callback.cc
|
|
685
691
|
Callback::AsyncFree();
|
|
686
692
|
}
|
|
687
693
|
|
|
@@ -690,118 +696,4 @@ void FunctionDestroyed(const v8::WeakCallbackInfo<FunctionInfo> &data) {
|
|
|
690
696
|
delete func;
|
|
691
697
|
}
|
|
692
698
|
|
|
693
|
-
|
|
694
|
-
bool PrepareVFuncInvoker (GIFunctionInfo *info, GIFunctionInvoker *invoker, GType implementor, GError **error) {
|
|
695
|
-
gpointer address;
|
|
696
|
-
ffi_type **atypes;
|
|
697
|
-
GITypeInfo *tinfo;
|
|
698
|
-
gint n_args, n_invoke_args, in_pos, out_pos;
|
|
699
|
-
bool success;
|
|
700
|
-
|
|
701
|
-
GITypeInfo *rinfo = g_callable_info_get_return_type ((GICallableInfo *)info);
|
|
702
|
-
ffi_type *rtype = g_type_info_get_ffi_type (rinfo);
|
|
703
|
-
|
|
704
|
-
in_pos = 0;
|
|
705
|
-
out_pos = 0;
|
|
706
|
-
|
|
707
|
-
n_args = g_callable_info_get_n_args ((GICallableInfo *)info);
|
|
708
|
-
|
|
709
|
-
n_invoke_args = n_args;
|
|
710
|
-
|
|
711
|
-
/* is_method */
|
|
712
|
-
n_invoke_args += 1;
|
|
713
|
-
in_pos++;
|
|
714
|
-
|
|
715
|
-
int n_in_args = 0;
|
|
716
|
-
int n_out_args = 0;
|
|
717
|
-
|
|
718
|
-
for (int i = 0; i < n_args; i++) {
|
|
719
|
-
GIArgInfo arg_info;
|
|
720
|
-
g_callable_info_load_arg(info, i, &arg_info);
|
|
721
|
-
auto direction = g_arg_info_get_direction(&arg_info);
|
|
722
|
-
|
|
723
|
-
if (IsDirectionIn(direction))
|
|
724
|
-
n_in_args++;
|
|
725
|
-
if (IsDirectionOut(direction))
|
|
726
|
-
n_out_args++;
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
atypes = (ffi_type**)g_alloca (sizeof (ffi_type*) * n_invoke_args);
|
|
730
|
-
|
|
731
|
-
/* is_method */
|
|
732
|
-
atypes[0] = &ffi_type_pointer;
|
|
733
|
-
|
|
734
|
-
for (int i = 0; i < n_args; i++) {
|
|
735
|
-
int offset = 1;
|
|
736
|
-
GIArgInfo *ainfo = g_callable_info_get_arg ((GICallableInfo *)info, i);
|
|
737
|
-
|
|
738
|
-
switch (g_arg_info_get_direction (ainfo)) {
|
|
739
|
-
case GI_DIRECTION_IN:
|
|
740
|
-
tinfo = g_arg_info_get_type (ainfo);
|
|
741
|
-
atypes[i+offset] = g_type_info_get_ffi_type (tinfo);
|
|
742
|
-
g_base_info_unref ((GIBaseInfo *)tinfo);
|
|
743
|
-
|
|
744
|
-
in_pos++;
|
|
745
|
-
|
|
746
|
-
break;
|
|
747
|
-
case GI_DIRECTION_OUT:
|
|
748
|
-
atypes[i+offset] = &ffi_type_pointer;
|
|
749
|
-
|
|
750
|
-
out_pos++;
|
|
751
|
-
break;
|
|
752
|
-
case GI_DIRECTION_INOUT:
|
|
753
|
-
atypes[i+offset] = &ffi_type_pointer;
|
|
754
|
-
|
|
755
|
-
in_pos++;
|
|
756
|
-
out_pos++;
|
|
757
|
-
break;
|
|
758
|
-
default:
|
|
759
|
-
g_assert_not_reached ();
|
|
760
|
-
}
|
|
761
|
-
g_base_info_unref ((GIBaseInfo *)ainfo);
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
success = ffi_prep_cif (&invoker->cif, FFI_DEFAULT_ABI, n_invoke_args, rtype, atypes) == FFI_OK;
|
|
765
|
-
|
|
766
|
-
address = g_vfunc_info_get_address (info, implementor, error);
|
|
767
|
-
invoker->native_address = address;
|
|
768
|
-
|
|
769
|
-
g_base_info_unref ((GIBaseInfo *)rinfo);
|
|
770
|
-
return success;
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
MaybeLocal<Function> MakeVirtualFunction(GIBaseInfo *info, GType implementor) {
|
|
774
|
-
GError* error = NULL;
|
|
775
|
-
|
|
776
|
-
FunctionInfo *func = g_new0 (FunctionInfo, 1);
|
|
777
|
-
func->info = g_base_info_ref (info);
|
|
778
|
-
PrepareVFuncInvoker(info, &func->invoker, implementor, &error);
|
|
779
|
-
|
|
780
|
-
if (error != NULL) {
|
|
781
|
-
char* message = g_strdup_printf("Couldn't create virtual function '%s': %s",
|
|
782
|
-
g_base_info_get_name(info), error->message);
|
|
783
|
-
Nan::ThrowError(message);
|
|
784
|
-
g_free (message);
|
|
785
|
-
g_base_info_unref (func->info);
|
|
786
|
-
g_function_invoker_destroy (&func->invoker);
|
|
787
|
-
g_free (func);
|
|
788
|
-
g_error_free (error);
|
|
789
|
-
return MaybeLocal<Function>();
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
auto external = New<External>(func);
|
|
793
|
-
auto name = UTF8(g_base_info_get_name (info));
|
|
794
|
-
|
|
795
|
-
auto tpl = New<FunctionTemplate>(FunctionInvoker, external);
|
|
796
|
-
tpl->SetLength(g_callable_info_get_n_args (info));
|
|
797
|
-
|
|
798
|
-
auto fn = Nan::GetFunction (tpl).ToLocalChecked();
|
|
799
|
-
fn->SetName(name);
|
|
800
|
-
|
|
801
|
-
Persistent<FunctionTemplate> persistent(Isolate::GetCurrent(), tpl);
|
|
802
|
-
persistent.SetWeak(func, FunctionDestroyed, WeakCallbackType::kParameter);
|
|
803
|
-
|
|
804
|
-
return MaybeLocal<Function>(fn);
|
|
805
|
-
}
|
|
806
|
-
|
|
807
699
|
};
|