| 111 | |
| 112 | |
| 113 | void Var::UpdateAlias(Var *aTargetVar) |
| 114 | // Caller must ensure that aTargetVar isn't NULL. |
| 115 | // When this function actually converts a normal variable into an alias , the variable's old |
| 116 | // attributes (especially mContents and mCapacity) are hidden/suppressed by virtue of all Var:: |
| 117 | // methods obeying VAR_ALIAS and resolving it to be the target variable. This prevents a memory |
| 118 | // leak in a case where a UDF is defined to provide a default value for a ByRef parameter, and is |
| 119 | // called both with and without that parameter. |
| 120 | { |
| 121 | IObject *ref = aTargetVar->mType == VAR_ALIAS && aTargetVar->IsObject() |
| 122 | ? aTargetVar->mObject : nullptr; |
| 123 | |
| 124 | // BELOW IS THE MEANS BY WHICH ALIASES AREN'T ALLOWED TO POINT TO OTHER ALIASES, ONLY DIRECTLY TO |
| 125 | // THE TARGET VAR. |
| 126 | // Resolve aliases-to-aliases for performance. A caller may ask to create an alias |
| 127 | // to an alias when a function calls another function and passes to it one of its own |
| 128 | // byref-params, or if the target var has had its reference taken with GetRef(). |
| 129 | while (aTargetVar->mType == VAR_ALIAS) |
| 130 | aTargetVar = aTargetVar->mAliasFor; |
| 131 | |
| 132 | // The following is done only after the above in case there's ever a way for the above |
| 133 | // to circle back to become this variable. |
| 134 | // Prevent potential infinite loops in other methods by refusing to change an alias |
| 135 | // to point to itself. |
| 136 | if (aTargetVar == this) |
| 137 | return; |
| 138 | |
| 139 | SetAliasDirect(aTargetVar); |
| 140 | |
| 141 | // Done last in case it causes interruption: |
| 142 | ASSERT(!IsObject()); |
| 143 | //if (IsObject()) |
| 144 | // ReleaseObject(); |
| 145 | if (ref) |
| 146 | { |
| 147 | _SetObject(ref); |
| 148 | ref->AddRef(); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | |
| 153 | |