Skip to content

Commit

Permalink
lookup properties by numeric index for typed arrays during stringify
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeHolman committed Mar 16, 2018
1 parent 39c310f commit 45caec1
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 28 deletions.
84 changes: 58 additions & 26 deletions lib/Runtime/Library/JSONStringifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ JSONStringifier::Stringify(_In_ ScriptContext* scriptContext, _In_ Var value, _I
wrapper,
prop,
value,
scriptContext->GetThreadContext()->GetEmptyStringPropertyRecord(),
&objStack);

if (prop->type == JSONContentType::Undefined)
Expand Down Expand Up @@ -340,7 +339,7 @@ JSONStringifier::ReadArrayElement(uint32 index, _In_ RecyclableObject* arr, _Out
JavascriptOperators::GetItem(arr, index, &value, this->scriptContext);
}
JavascriptString* indexString = this->scriptContext->GetIntegerString(index);
this->ReadProperty(indexString, arr, prop, value, nullptr, objectStack);
this->ReadProperty(indexString, arr, prop, value, objectStack);
}

JSONArray*
Expand Down Expand Up @@ -386,19 +385,13 @@ JSONStringifier::ReadArray(_In_ RecyclableObject* arr, _In_ JSONObjectStack* obj
}

void
JSONStringifier::ReadObjectElement(
JSONStringifier::AppendObjectElement(
_In_ JavascriptString* propertyName,
_In_opt_ PropertyRecord const* propertyRecord,
_In_ RecyclableObject* obj,
_In_ JSONObject* jsonObject,
_In_ JSONObjectStack* objectStack)
_In_ JSONObjectProperty* prop)
{
JSONObjectProperty prop;
prop.propertyName = propertyName;
this->ReadProperty(propertyName, obj, &prop.propertyValue, nullptr, propertyRecord, objectStack);

// Undefined result is not concatenated
if (prop.propertyValue.type != JSONContentType::Undefined)
if (prop->propertyValue.type != JSONContentType::Undefined)
{
// Increase length for the name of the property
this->totalStringLength = UInt32Math::Add(this->totalStringLength, CalculateStringElementLength(propertyName));
Expand All @@ -409,10 +402,49 @@ JSONStringifier::ReadObjectElement(
// If gap is specified, a space is appended
UInt32Math::Inc(this->totalStringLength);
}
jsonObject->Push(prop);
}
}

void
JSONStringifier::ReadObjectElement(
_In_ JavascriptString* propertyName,
_In_ uint32 numericIndex,
_In_ RecyclableObject* obj,
_In_ JSONObject* jsonObject,
_In_ JSONObjectStack* objectStack)
{
JSONObjectProperty prop;
prop.propertyName = propertyName;

Var value = JavascriptOperators::GetItem(obj, numericIndex, this->scriptContext);

this->ReadProperty(propertyName, obj, &prop.propertyValue, value, objectStack);

this->AppendObjectElement(propertyName, jsonObject, &prop);

jsonObject->Push(prop);
}

void
JSONStringifier::ReadObjectElement(
_In_ JavascriptString* propertyName,
_In_opt_ PropertyRecord const* propertyRecord,
_In_ RecyclableObject* obj,
_In_ JSONObject* jsonObject,
_In_ JSONObjectStack* objectStack)
{
JSONObjectProperty prop;
prop.propertyName = propertyName;

Var value = this->ReadValue(propertyName, propertyRecord, obj);

this->ReadProperty(propertyName, obj, &prop.propertyValue, value, objectStack);

this->AppendObjectElement(propertyName, jsonObject, &prop);

jsonObject->Push(prop);
}

// Calculates how many additional characters are needed for printing the Object/Array structure
// This includes commas, brackets, and gap (if any)
void
Expand Down Expand Up @@ -520,18 +552,25 @@ JSONStringifier::ReadObject(_In_ RecyclableObject* obj, _In_ JSONObjectStack* ob
JavascriptStaticEnumerator enumerator;
if (obj->GetEnumerator(&enumerator, EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::EphemeralReference, this->scriptContext))
{
enumerator.GetInitialPropertyCount();
JavascriptString* propertyName = nullptr;
PropertyId nextKey = Constants::NoProperty;
while ((propertyName = enumerator.MoveAndGetNext(nextKey)) != nullptr)
{
PropertyRecord const * propertyRecord = nullptr;
if (nextKey == Constants::NoProperty)
const uint32 numericIndex = enumerator.GetCurrentItemIndex();
if (numericIndex != Constants::InvalidSourceIndex)
{
this->scriptContext->GetOrAddPropertyRecord(propertyName, &propertyRecord);
nextKey = propertyRecord->GetPropertyId();
this->ReadObjectElement(propertyName, numericIndex, obj, jsonObject, &stack);
}
else
{
PropertyRecord const * propertyRecord = nullptr;
if (nextKey == Constants::NoProperty)
{
this->scriptContext->GetOrAddPropertyRecord(propertyName, &propertyRecord);
nextKey = propertyRecord->GetPropertyId();
}
this->ReadObjectElement(propertyName, propertyRecord, obj, jsonObject, &stack);
}
this->ReadObjectElement(propertyName, propertyRecord, obj, jsonObject, &stack);
}
}
}
Expand Down Expand Up @@ -728,17 +767,10 @@ JSONStringifier::ReadProperty(
_In_ JavascriptString* key,
_In_opt_ RecyclableObject* holder,
_Out_ JSONProperty* prop,
_In_opt_ Var value,
_In_opt_ const PropertyRecord* propertyRecord,
_In_ Var value,
_In_ JSONObjectStack* objectStack)
{
PROBE_STACK(this->scriptContext, Constants::MinStackDefault);
if (value == nullptr)
{
// If we don't have a value, we must have an object from which we can read it
AnalysisAssert(holder != nullptr);
value = this->ReadValue(key, propertyRecord, holder);
}

// Save these to avoid having to recheck conditions unless value is modified by ToJSON or a replacer function
RecyclableObject* valueObj = JavascriptOperators::TryFromVar<RecyclableObject>(value);
Expand Down
15 changes: 13 additions & 2 deletions lib/Runtime/Library/JSONStringifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ class JSONStringifier
uint32 ReadArrayLength(_In_ RecyclableObject* value);
JSONArray* ReadArray(_In_ RecyclableObject* arr, _In_ JSONObjectStack* objectStack);

void AppendObjectElement(
_In_ JavascriptString* propertyName,
_In_ JSONObject* jsonObject,
_In_ JSONObjectProperty* prop);

void ReadObjectElement(
_In_ JavascriptString* propertyName,
_In_ uint32 numericIndex,
_In_ RecyclableObject* obj,
_In_ JSONObject* jsonObject,
_In_ JSONObjectStack* objectStack);

void ReadObjectElement(
_In_ JavascriptString* propertyName,
_In_opt_ PropertyRecord const* propertyRecord,
Expand Down Expand Up @@ -95,8 +107,7 @@ class JSONStringifier
_In_ JavascriptString* key,
_In_opt_ RecyclableObject* holder,
_Out_ JSONProperty* prop,
_In_opt_ Var value,
_In_opt_ const PropertyRecord* propertyRecord,
_In_ Var value,
_In_ JSONObjectStack* objectStack);

const char16* GetGap() const { return this->gap; };
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Library/JavascriptStringEnumerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ namespace Js
JavascriptStringEnumerator(JavascriptString* stringObject, ScriptContext * requestContext);
virtual void Reset() override;
virtual JavascriptString * MoveAndGetNext(PropertyId& propertyId, PropertyAttributes* attributes = nullptr) override;
virtual uint32 GetCurrentItemIndex() override { return index; }
};
}
1 change: 1 addition & 0 deletions lib/Runtime/Library/TypedArrayIndexEnumerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ namespace Js
TypedArrayIndexEnumerator(TypedArrayBase* typeArrayBase, EnumeratorFlags flags, ScriptContext* scriptContext);
virtual JavascriptString * MoveAndGetNext(PropertyId& propertyId, PropertyAttributes* attributes = nullptr) override;
virtual void Reset() override;
virtual uint32 GetCurrentItemIndex() override { return index; }
};
}

0 comments on commit 45caec1

Please sign in to comment.