| 1593 | |
| 1594 | |
| 1595 | ResultType VariadicCall(IObject *aObj, IObject_Invoke_PARAMS_DECL) |
| 1596 | { |
| 1597 | IObject *param_obj = nullptr; // Vararg object passed by caller. |
| 1598 | Array *param_array = nullptr; // Array of parameters, either the same as param_obj or the result of enumeration. |
| 1599 | ExprTokenType* token = nullptr; // Used for variadic calls. |
| 1600 | |
| 1601 | ExprTokenType *rvalue = IS_INVOKE_SET ? aParam[--aParamCount] : nullptr; |
| 1602 | |
| 1603 | --aParamCount; // Exclude param_obj from aParamCount, so it's the count of normal params. |
| 1604 | param_obj = TokenToObject(*aParam[aParamCount]); |
| 1605 | // It might be more correct to use the enumerator even for Array, but that could be slow. |
| 1606 | // Future changes might enable efficient detection of a custom __Enum method, allowing |
| 1607 | // us to take the more efficient path most times, but still support custom enumeration. |
| 1608 | if (param_array = dynamic_cast<Array *>(param_obj)) |
| 1609 | param_array->AddRef(); |
| 1610 | else |
| 1611 | if (!(param_array = Array::FromEnumerable(*aParam[aParamCount]))) |
| 1612 | return aResultToken.SetExitResult(FAIL); |
| 1613 | int extra_params = param_array->Length(); |
| 1614 | if (extra_params > 0) |
| 1615 | { |
| 1616 | // Calculate space required for ... |
| 1617 | size_t space_needed = extra_params * sizeof(ExprTokenType) // ... new param tokens |
| 1618 | + (aParamCount + extra_params) * sizeof(ExprTokenType *); // ... existing and new param pointers |
| 1619 | if (rvalue) |
| 1620 | space_needed += sizeof(rvalue); // ... extra slot for aRValue |
| 1621 | // Allocate new param list and tokens; tokens first for convenience. |
| 1622 | token = (ExprTokenType *)_malloca(space_needed); |
| 1623 | if (!token) |
| 1624 | return aResultToken.MemoryError(); |
| 1625 | ExprTokenType **param_list = (ExprTokenType **)(token + extra_params); |
| 1626 | // Since built-in functions don't have variables we can directly assign to, |
| 1627 | // we need to expand the param object's contents into an array of tokens: |
| 1628 | param_array->ToParams(token, param_list, aParam, aParamCount); |
| 1629 | aParam = param_list; |
| 1630 | aParamCount += extra_params; |
| 1631 | } |
| 1632 | if (rvalue) |
| 1633 | aParam[aParamCount++] = rvalue; // In place of the variadic param. |
| 1634 | |
| 1635 | #ifdef ENABLE_HALF_BAKED_NAMED_PARAMS |
| 1636 | aResultToken.named_params = param_obj; |
| 1637 | #endif |
| 1638 | |
| 1639 | auto result = aObj->Invoke(aResultToken, aFlags, aName, aThisToken, aParam, aParamCount); |
| 1640 | |
| 1641 | if (param_array) |
| 1642 | param_array->Release(); |
| 1643 | if (token) |
| 1644 | _freea(token); |
| 1645 | |
| 1646 | return result; |
| 1647 | } |
| 1648 | |
| 1649 | |
| 1650 |
no test coverage detected