| 502 | LPTSTR Object::sMetaFuncName[] = { _T("__Get"), _T("__Set"), _T("__Call") }; |
| 503 | |
| 504 | ResultType Object::Invoke(IObject_Invoke_PARAMS_DECL) |
| 505 | { |
| 506 | // In debug mode, verify aResultToken has been initialized correctly. |
| 507 | ASSERT(aResultToken.symbol == SYM_STRING && aResultToken.marker && !*aResultToken.marker); |
| 508 | ASSERT(aResultToken.Result() == OK); |
| 509 | |
| 510 | name_t name; |
| 511 | if (!aName) |
| 512 | { |
| 513 | name = IS_INVOKE_CALL ? _T("Call") : _T("__Item"); |
| 514 | aFlags |= IF_BYPASS_METAFUNC; |
| 515 | } |
| 516 | else |
| 517 | name = aName; |
| 518 | |
| 519 | auto actual_param = aParam; // Actual first parameter between [] or (). |
| 520 | int actual_param_count = aParamCount; // Actual number of parameters between [] or (). |
| 521 | |
| 522 | bool hasprop = false; // Whether any kind of property was found. |
| 523 | bool setting = IS_INVOKE_SET; |
| 524 | bool calling = IS_INVOKE_CALL; |
| 525 | bool handle_params_recursively = calling; |
| 526 | ResultToken token_for_recursion; |
| 527 | IObject *etter = nullptr, *method = nullptr; |
| 528 | Variant *field = nullptr; |
| 529 | index_t insert_pos, other_pos; |
| 530 | Object *that; |
| 531 | |
| 532 | if (setting) |
| 533 | { |
| 534 | // Due to the way expression parsing works, the result should never be negative |
| 535 | // (and any direct callers of Invoke must always pass aParamCount >= 1): |
| 536 | ASSERT(actual_param_count > 0); |
| 537 | --actual_param_count; |
| 538 | } |
| 539 | |
| 540 | for (that = this; that; that = that->mBase) |
| 541 | { |
| 542 | // Search each object from this to its most distance base, but set insert_pos only when |
| 543 | // searching this object, since it needs to be the position we can insert a new field at. |
| 544 | field = that->FindField(name, that == this ? insert_pos : other_pos); |
| 545 | if (!field) // 'that' has no own property. |
| 546 | continue; |
| 547 | if (field->symbol != SYM_DYNAMIC) // 'that' has a value property. |
| 548 | { |
| 549 | if (hasprop && setting) |
| 550 | // This value property has been overridden with a getter, but no setter. |
| 551 | // Treat it as read-only rather than allowing the getter to implicitly be overridden. |
| 552 | field = nullptr; |
| 553 | hasprop = true; |
| 554 | // This value property takes precedence over any getter, setter or method defined in a base. |
| 555 | break; |
| 556 | } |
| 557 | hasprop = true; |
| 558 | // Since above did not break or continue, 'that' has a dynamic property. |
| 559 | if (calling) |
| 560 | { |
| 561 | if (method = field->prop->Method()) |
no test coverage detected