| 17110 | |
| 17111 | |
| 17112 | ResultType ValidateFunctor(IObject *aFunc, int aParamCount, ResultToken &aResultToken, int *aUseMinParams, bool aShowError) |
| 17113 | { |
| 17114 | ASSERT(aFunc); |
| 17115 | __int64 min_params = 0, max_params = INT_MAX; |
| 17116 | auto min_result = aParamCount == -1 ? INVOKE_NOT_HANDLED |
| 17117 | : GetObjectIntProperty(aFunc, _T("MinParams"), min_params, aResultToken, true); |
| 17118 | if (!min_result) |
| 17119 | return FAIL; |
| 17120 | bool has_minparams = min_result != INVOKE_NOT_HANDLED; // For readability. |
| 17121 | if (aUseMinParams) // CallbackCreate's signal to default to MinParams. |
| 17122 | { |
| 17123 | if (!has_minparams) |
| 17124 | return aShowError ? aResultToken.UnknownMemberError(ExprTokenType(aFunc), IT_GET, _T("MinParams")) : CONDITION_FALSE; |
| 17125 | *aUseMinParams = aParamCount = (int)min_params; |
| 17126 | } |
| 17127 | else if (has_minparams && aParamCount < (int)min_params) |
| 17128 | return aShowError ? aResultToken.ValueError(ERR_INVALID_FUNCTOR) : CONDITION_FALSE; |
| 17129 | auto max_result = (aParamCount <= 0 || has_minparams && min_params == aParamCount) |
| 17130 | ? INVOKE_NOT_HANDLED // No need to check MaxParams in the above cases. |
| 17131 | : GetObjectIntProperty(aFunc, _T("MaxParams"), max_params, aResultToken, true); |
| 17132 | if (!max_result) |
| 17133 | return FAIL; |
| 17134 | if (max_result != INVOKE_NOT_HANDLED && aParamCount > (int)max_params) |
| 17135 | { |
| 17136 | __int64 is_variadic = 0; |
| 17137 | auto result = GetObjectIntProperty(aFunc, _T("IsVariadic"), is_variadic, aResultToken, true); |
| 17138 | if (!result) |
| 17139 | return FAIL; |
| 17140 | if (!is_variadic) // or not defined. |
| 17141 | return aShowError ? aResultToken.ValueError(ERR_INVALID_FUNCTOR) : CONDITION_FALSE; |
| 17142 | } |
| 17143 | // If either MinParams or MaxParams was confirmed to exist, this is likely a valid |
| 17144 | // function object, so skip the following check for performance. Otherwise, catch |
| 17145 | // likely errors by checking that the object is callable. |
| 17146 | if (min_result == INVOKE_NOT_HANDLED && max_result == INVOKE_NOT_HANDLED) |
| 17147 | if (Object *obj = dynamic_cast<Object *>(aFunc)) |
| 17148 | if (!obj->HasMethod(_T("Call"))) |
| 17149 | return aShowError ? aResultToken.UnknownMemberError(ExprTokenType(aFunc), IT_CALL, _T("Call")) : CONDITION_FALSE; |
| 17150 | // Otherwise: COM objects can be callable via DISPID_VALUE. There's probably |
| 17151 | // no way to determine whether the object supports that without invoking it. |
| 17152 | return OK; |
| 17153 | } |
| 17154 | |
| 17155 | |
| 17156 |
no test coverage detected