| 1102 | } |
| 1103 | |
| 1104 | bool Function::finish_invoke(JSContext* cx, const JS::CallArgs& args, |
| 1105 | GjsFunctionCallState* state, |
| 1106 | GIArgument* r_value /* = nullptr */) { |
| 1107 | // In this loop we use ffi_arg_pos just to ensure we don't release stuff |
| 1108 | // we haven't allocated yet, if we failed in type conversion above. |
| 1109 | // If we start from -1 (the return value), we need to process 1 more than |
| 1110 | // state.processed_c_args. |
| 1111 | // If we start from -2 (the instance parameter), we need to process 2 more |
| 1112 | unsigned ffi_arg_pos = state->first_arg_offset() - 1; |
| 1113 | unsigned ffi_arg_max = state->last_processed_index(); |
| 1114 | bool postinvoke_release_failed = false; |
| 1115 | for (int gi_arg_pos = -(state->first_arg_offset()); |
| 1116 | gi_arg_pos < state->gi_argc && ffi_arg_pos < ffi_arg_max; |
| 1117 | gi_arg_pos++, ffi_arg_pos++) { |
| 1118 | Maybe<Argument*> gjs_arg; |
| 1119 | GIArgument* in_value = nullptr; |
| 1120 | GIArgument* out_value = nullptr; |
| 1121 | |
| 1122 | if (gi_arg_pos == -2) { |
| 1123 | in_value = state->instance(); |
| 1124 | gjs_arg = m_arguments.instance(); |
| 1125 | } else if (gi_arg_pos == -1) { |
| 1126 | out_value = state->return_value(); |
| 1127 | gjs_arg = m_arguments.return_value(); |
| 1128 | } else { |
| 1129 | in_value = &state->in_cvalue(gi_arg_pos); |
| 1130 | out_value = &state->out_cvalue(gi_arg_pos); |
| 1131 | gjs_arg = Some(m_arguments.argument(gi_arg_pos)); |
| 1132 | } |
| 1133 | |
| 1134 | if (!gjs_arg) |
| 1135 | continue; |
| 1136 | |
| 1137 | gjs_debug_marshal( |
| 1138 | GJS_DEBUG_GFUNCTION, |
| 1139 | "Releasing argument '%s', %d/%d GI args, %u/%u C args", |
| 1140 | (*gjs_arg)->arg_name(), gi_arg_pos, state->gi_argc, ffi_arg_pos, |
| 1141 | state->processed_c_args); |
| 1142 | |
| 1143 | // Only process in or inout arguments if we failed, the rest is garbage |
| 1144 | if (state->failed && (*gjs_arg)->skip_in()) |
| 1145 | continue; |
| 1146 | |
| 1147 | // Save the return GIArgument if it was requested |
| 1148 | if (r_value && gi_arg_pos == -1) { |
| 1149 | *r_value = *out_value; |
| 1150 | continue; |
| 1151 | } |
| 1152 | |
| 1153 | if (!(*gjs_arg)->release(cx, state, in_value, out_value)) { |
| 1154 | postinvoke_release_failed = true; |
| 1155 | // continue with the release even if we fail, to avoid leaks |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | if (postinvoke_release_failed || state->failed) |
| 1160 | return false; |
| 1161 | if (state->did_throw_gerror()) |
nothing calls this directly
no test coverage detected