Skip to content

Commit 6e9b254

Browse files
committed
Share types with deleted properties
1 parent 090b258 commit 6e9b254

12 files changed

+185
-65
lines changed

lib/Common/ConfigFlagsList.h

+1
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ PHASE(All)
384384
PHASE(TypePathDynamicSize)
385385
PHASE(ObjectCopy)
386386
PHASE(ShareTypesWithAttributes)
387+
PHASE(ShareTypesWithDeleted)
387388
PHASE(ShareAccessorTypes)
388389
PHASE(ShareFuncTypes)
389390
PHASE(ConditionalCompilation)

lib/Runtime/Language/JavascriptOperators.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,10 @@ using namespace Js;
16991699
template <bool unscopables>
17001700
BOOL JavascriptOperators::GetProperty_Internal(Var instance, RecyclableObject* propertyObject, const bool isRoot, PropertyId propertyId, Var* value, ScriptContext* requestContext, PropertyValueInfo* info)
17011701
{
1702+
#if ENABLE_FIXED_FIELDS && DBG
1703+
DynamicTypeHandler *dynamicTypeHandler = nullptr;
1704+
#endif
1705+
17021706
if (TaggedNumber::Is(instance))
17031707
{
17041708
PropertyValueInfo::ClearCacheInfo(info);
@@ -1721,6 +1725,9 @@ using namespace Js;
17211725
}
17221726
else
17231727
{
1728+
#if ENABLE_FIXED_FIELDS && DBG
1729+
dynamicTypeHandler = VarIs<DynamicObject>(object) ? VarTo<DynamicObject>(object)->GetTypeHandler() : nullptr;
1730+
#endif
17241731
PropertyQueryFlags result = object->GetPropertyQuery(instance, propertyId, value, info, requestContext);
17251732
if (result != PropertyQueryFlags::Property_NotFound)
17261733
{
@@ -1740,10 +1747,10 @@ using namespace Js;
17401747
if (foundProperty)
17411748
{
17421749
#if ENABLE_FIXED_FIELDS && DBG
1743-
if (DynamicObject::IsBaseDynamicObject(object))
1750+
// Note: It's valid to check this for the original type handler but not for a new type handler that may have been installed
1751+
// by a getter that, for instance, deleted and re-added the property.
1752+
if (dynamicTypeHandler)
17441753
{
1745-
DynamicObject* dynamicObject = (DynamicObject*)object;
1746-
DynamicTypeHandler* dynamicTypeHandler = dynamicObject->GetDynamicType()->GetTypeHandler();
17471754
Var property;
17481755
if (dynamicTypeHandler->CheckFixedProperty(requestContext->GetPropertyName(propertyId), &property, requestContext))
17491756
{
@@ -8846,23 +8853,18 @@ using namespace Js;
88468853
// ES5 8.12.9.9.c: Convert the property named P of object O from an accessor property to a data property.
88478854
// Preserve the existing values of the converted property's [[Configurable]] and [[Enumerable]] attributes
88488855
// and set the rest of the property's attributes to their default values.
8849-
// Note: avoid using SetProperty/SetPropertyWithAttributes here because they has undesired side-effects:
8850-
// it calls previous setter and in some cases of attribute values throws.
8851-
// To walk around, call DeleteProperty and then AddProperty.
88528856
PropertyAttributes preserveFromObject = currentDescriptor->GetAttributes() & (PropertyConfigurable | PropertyEnumerable);
88538857

88548858
tempDescriptor.SetAttributes(preserveFromObject, PropertyConfigurable | PropertyEnumerable);
88558859
tempDescriptor.MergeFrom(descriptor); // Update only fields specified in 'descriptor'.
88568860
Var descriptorValue = descriptor.ValueSpecified() ? descriptor.GetValue() : defaultDataValue;
88578861

8858-
// Note: HostDispath'es implementation of DeleteProperty currently throws E_NOTIMPL.
8859-
obj->DeleteProperty(propId, PropertyOperation_None);
8860-
BOOL tempResult = obj->SetPropertyWithAttributes(propId, descriptorValue, tempDescriptor.GetAttributes(), NULL, PropertyOperation_Force);
8861-
Assert(tempResult);
8862+
BOOL result = VarTo<DynamicObject>(obj)->ConvertAccessorToData(propId, descriptorValue, tempDescriptor.GetAttributes());
88628863

88638864
// At this time we already set value and attributes to desired values,
88648865
// thus we can skip step ES5 8.12.9.12 and simply return true.
8865-
return TRUE;
8866+
Assert(result);
8867+
return result;
88668868
}
88678869
}
88688870
}

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
@@ -383,6 +383,19 @@ namespace Js
383383
this->type = predecessorType;
384384
}
385385

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

lib/Runtime/Types/DynamicObject.h

+2
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ namespace Js
317317

318318
void ChangeTypeIf(const Type* oldType);
319319

320+
BOOL ConvertAccessorToData(PropertyId propId, Var value, PropertyAttributes attributes);
321+
320322
BOOL FindNextProperty(BigPropertyIndex& index, JavascriptString** propertyString, PropertyId* propertyId, PropertyAttributes* attributes,
321323
DynamicType *typeToEnumerate, EnumeratorFlags flags, ScriptContext * requestContext, PropertyValueInfo * info);
322324

0 commit comments

Comments
 (0)