Skip to content

Commit 4056962

Browse files
committed
Share types with deleted properties
1 parent 831e6b2 commit 4056962

12 files changed

+186
-65
lines changed

lib/Common/ConfigFlagsList.h

+1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ PHASE(All)
383383
PHASE(TypePathDynamicSize)
384384
PHASE(ObjectCopy)
385385
PHASE(ShareTypesWithAttributes)
386+
PHASE(ShareTypesWithDeleted)
386387
PHASE(ShareAccessorTypes)
387388
PHASE(ShareFuncTypes)
388389
PHASE(ConditionalCompilation)

lib/Runtime/Language/JavascriptOperators.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,10 @@ using namespace Js;
16961696
template <bool unscopables>
16971697
BOOL JavascriptOperators::GetProperty_Internal(Var instance, RecyclableObject* propertyObject, const bool isRoot, PropertyId propertyId, Var* value, ScriptContext* requestContext, PropertyValueInfo* info)
16981698
{
1699+
#if ENABLE_FIXED_FIELDS && DBG
1700+
DynamicTypeHandler *dynamicTypeHandler = nullptr;
1701+
#endif
1702+
16991703
if (TaggedNumber::Is(instance))
17001704
{
17011705
PropertyValueInfo::ClearCacheInfo(info);
@@ -1718,6 +1722,9 @@ using namespace Js;
17181722
}
17191723
else
17201724
{
1725+
#if ENABLE_FIXED_FIELDS && DBG
1726+
dynamicTypeHandler = DynamicObject::Is(object) ? DynamicObject::FromVar(object)->GetTypeHandler() : nullptr;
1727+
#endif
17211728
PropertyQueryFlags result = object->GetPropertyQuery(instance, propertyId, value, info, requestContext);
17221729
if (result != PropertyQueryFlags::Property_NotFound)
17231730
{
@@ -1737,10 +1744,10 @@ using namespace Js;
17371744
if (foundProperty)
17381745
{
17391746
#if ENABLE_FIXED_FIELDS && DBG
1740-
if (DynamicObject::Is(object))
1747+
// Note: It's valid to check this for the original type handler but not for a new type handler that may have been installed
1748+
// by a getter that, for instance, deleted and re-added the property.
1749+
if (dynamicTypeHandler)
17411750
{
1742-
DynamicObject* dynamicObject = (DynamicObject*)object;
1743-
DynamicTypeHandler* dynamicTypeHandler = dynamicObject->GetDynamicType()->GetTypeHandler();
17441751
Var property;
17451752
if (dynamicTypeHandler->CheckFixedProperty(requestContext->GetPropertyName(propertyId), &property, requestContext))
17461753
{
@@ -8828,23 +8835,18 @@ using namespace Js;
88288835
// ES5 8.12.9.9.c: Convert the property named P of object O from an accessor property to a data property.
88298836
// Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes
88308837
// and set the rest of the property's attributes to their default values.
8831-
// Note: avoid using SetProperty/SetPropertyWithAttributes here because they has undesired side-effects:
8832-
// it calls previous setter and in some cases of attribute values throws.
8833-
// To walk around, call DeleteProperty and then AddProperty.
88348838
PropertyAttributes preserveFromObject = currentDescriptor->GetAttributes() & (PropertyConfigurable | PropertyEnumerable);
88358839

88368840
tempDescriptor.SetAttributes(preserveFromObject, PropertyConfigurable | PropertyEnumerable);
88378841
tempDescriptor.MergeFrom(descriptor); // Update only fields specified in 'descriptor'.
88388842
Var descriptorValue = descriptor.ValueSpecified() ? descriptor.GetValue() : defaultDataValue;
88398843

8840-
// Note: HostDispath'es implementation of DeleteProperty currently throws E_NOTIMPL.
8841-
obj->DeleteProperty(propId, PropertyOperation_None);
8842-
BOOL tempResult = obj->SetPropertyWithAttributes(propId, descriptorValue, tempDescriptor.GetAttributes(), NULL, PropertyOperation_Force);
8843-
Assert(tempResult);
8844+
BOOL result = DynamicObject::FromVar(obj)->ConvertAccessorToData(propId, descriptorValue, tempDescriptor.GetAttributes());
88448845

88458846
// At this time we already set value and attributes to desired values,
88468847
// thus we can skip step ES5 8.12.9.12 and simply return true.
8847-
return TRUE;
8848+
Assert(result);
8849+
return result;
88488850
}
88498851
}
88508852
}

lib/Runtime/RuntimeCommon.h

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ namespace Js
8484
ObjectSlotAttr_Int = 0x20,
8585
ObjectSlotAttr_Double = 0x40,
8686
ObjectSlotAttr_Default = (ObjectSlotAttr_Writable|ObjectSlotAttr_Enumerable|ObjectSlotAttr_Configurable),
87+
ObjectSlotAttr_DeletedDefault = (ObjectSlotAttr_Deleted|ObjectSlotAttr_Writable|ObjectSlotAttr_Configurable),
8788
ObjectSlotAttr_PropertyAttributesMask = (ObjectSlotAttr_Default|ObjectSlotAttr_Deleted),
8889
ObjectSlotAttr_All = 0xFF,
8990
ObjectSlotAttr_Setter = ObjectSlotAttr_All ^ ObjectSlotAttr_Deleted, // an impossible value indicating "setter"

lib/Runtime/Types/DynamicObject.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,19 @@ namespace Js
382382
this->type = predecessorType;
383383
}
384384

385+
BOOL DynamicObject::ConvertAccessorToData(PropertyId propId, Var value, PropertyAttributes attributes)
386+
{
387+
uint32 indexVal;
388+
if (GetScriptContext()->IsNumericPropertyId(propId, &indexVal))
389+
{
390+
DeleteItem(indexVal, PropertyOperation_None);
391+
}
392+
GetTypeHandler()->InitProperty(this, propId, value, PropertyOperation_Force, nullptr);
393+
BOOL result = SetPropertyWithAttributes(propId, value, attributes, NULL, PropertyOperation_Force);
394+
Assert(result);
395+
return result;
396+
}
397+
385398
DWORD DynamicObject::GetOffsetOfAuxSlots()
386399
{
387400
return offsetof(DynamicObject, auxSlots);

lib/Runtime/Types/DynamicObject.h

+2
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ namespace Js
314314

315315
void ChangeTypeIf(const Type* oldType);
316316

317+
BOOL ConvertAccessorToData(PropertyId propId, Var value, PropertyAttributes attributes);
318+
317319
BOOL FindNextProperty(BigPropertyIndex& index, JavascriptString** propertyString, PropertyId* propertyId, PropertyAttributes* attributes,
318320
DynamicType *typeToEnumerate, EnumeratorFlags flags, ScriptContext * requestContext, PropertyValueInfo * info);
319321

0 commit comments

Comments
 (0)