ArrayData* StructArray::LvalStr( ArrayData* ad, StringData* property, Variant*& ret, bool copy ) { auto structArray = asStructArray(ad); auto shape = structArray->shape(); auto offset = shape->offsetFor(property); if (offset != PropertyTable::kInvalidOffset) { auto const result = asStructArray( copy ? Copy(structArray) : structArray); ret = &tvAsVariant(&result->data()[offset]); return result; } auto convertToMixedAndAdd = [&]() { auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray); return mixed->addLvalImpl(property, ret); }; // We don't support adding non-static strings yet. StringData* staticKey; if (property->isStatic()) { staticKey = property; } else { staticKey = lookupStaticString(property); if (!staticKey) return convertToMixedAndAdd(); } auto newShape = shape->transition(staticKey); if (!newShape) return convertToMixedAndAdd(); auto result = copy ? CopyAndResizeIfNeeded(structArray, newShape) : ResizeIfNeeded(structArray, newShape); assert(newShape->hasOffsetFor(staticKey)); offset = newShape->offsetFor(staticKey); tvWriteNull(&result->data()[offset]); ret = &tvAsVariant(&result->data()[offset]); return result; }
ArrayData* StructArray::SetStr( ArrayData* ad, StringData* k, Cell v, bool copy ) { auto structArray = asStructArray(ad); auto shape = structArray->shape(); auto result = structArray; auto offset = shape->offsetFor(k); bool isNewProperty = offset == PropertyTable::kInvalidOffset; auto convertToMixedAndAdd = [&]() { auto mixed = copy ? ToMixedCopy(structArray) : ToMixed(structArray); return mixed->addValNoAsserts(k, v); }; if (isNewProperty) { StringData* staticKey; // We don't support adding non-static strings yet. if (k->isStatic()) { staticKey = k; } else { staticKey = lookupStaticString(k); if (!staticKey) return convertToMixedAndAdd(); } auto newShape = shape->transition(staticKey); if (!newShape) return convertToMixedAndAdd(); result = copy ? CopyAndResizeIfNeeded(structArray, newShape) : ResizeIfNeeded(structArray, newShape); offset = result->shape()->offsetFor(staticKey); assert(offset != PropertyTable::kInvalidOffset); TypedValue* dst = &result->data()[offset]; // TODO(#3888164): we should restructure things so we don't have to // check KindOfUninit here. if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>(); cellDup(v, *dst); return result; } if (copy) { result = asStructArray(Copy(structArray)); } assert(offset != PropertyTable::kInvalidOffset); TypedValue* dst = &result->data()[offset]; if (UNLIKELY(v.m_type == KindOfUninit)) v = make_tv<KindOfNull>(); cellSet(v, *tvToCell(dst)); return result; }