| 98 | } |
| 99 | |
| 100 | void GDScriptLambdaCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const { |
| 101 | int captures_amount = captures.size(); |
| 102 | |
| 103 | if (function == nullptr) { |
| 104 | r_return_value = Variant(); |
| 105 | r_call_error.error = Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL; |
| 106 | return; |
| 107 | } |
| 108 | |
| 109 | if (captures_amount > 0) { |
| 110 | const int total_argcount = p_argcount + captures_amount; |
| 111 | const Variant **args = (const Variant **)alloca(sizeof(Variant *) * total_argcount); |
| 112 | for (int i = 0; i < captures_amount; i++) { |
| 113 | args[i] = &captures[i]; |
| 114 | if (captures[i].get_type() == Variant::OBJECT) { |
| 115 | bool was_freed = false; |
| 116 | captures[i].get_validated_object_with_check(was_freed); |
| 117 | if (was_freed) { |
| 118 | ERR_PRINT(vformat(R"(Lambda capture at index %d was freed. Passed "null" instead.)", i)); |
| 119 | static Variant nil; |
| 120 | args[i] = &nil; |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | for (int i = 0; i < p_argcount; i++) { |
| 125 | args[i + captures_amount] = p_arguments[i]; |
| 126 | } |
| 127 | |
| 128 | r_return_value = function->call(nullptr, args, total_argcount, r_call_error); |
| 129 | switch (r_call_error.error) { |
| 130 | case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: |
| 131 | r_call_error.argument -= captures_amount; |
| 132 | #ifdef DEBUG_ENABLED |
| 133 | if (r_call_error.argument < 0) { |
| 134 | ERR_PRINT(vformat("GDScript bug (please report): Invalid value of lambda capture at index %d.", captures_amount + r_call_error.argument)); |
| 135 | r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; /// @todo Add a more suitable error code. |
| 136 | r_call_error.argument = 0; |
| 137 | r_call_error.expected = 0; |
| 138 | } |
| 139 | #endif |
| 140 | break; |
| 141 | case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS: |
| 142 | case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS: |
| 143 | r_call_error.expected -= captures_amount; |
| 144 | #ifdef DEBUG_ENABLED |
| 145 | if (r_call_error.expected < 0) { |
| 146 | ERR_PRINT("GDScript bug (please report): Invalid lambda captures count."); |
| 147 | r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; /// @todo Add a more suitable error code. |
| 148 | r_call_error.argument = 0; |
| 149 | r_call_error.expected = 0; |
| 150 | } |
| 151 | #endif |
| 152 | break; |
| 153 | default: |
| 154 | break; |
| 155 | } |
| 156 | } else { |
| 157 | r_return_value = function->call(nullptr, p_arguments, p_argcount, r_call_error); |
nothing calls this directly
no test coverage detected