|
|
@@ -2918,7 +2918,8 @@ namespace Js
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (pDestArray && JavascriptArray::IsDirectAccessArray(aItem) && JavascriptArray::IsDirectAccessArray(pDestArray)) // Fast path
|
|
|
+ if (pDestArray && JavascriptArray::IsDirectAccessArray(aItem) && JavascriptArray::IsDirectAccessArray(pDestArray)
|
|
|
+ && BigIndex(idxDest + JavascriptArray::FromVar(aItem)->length).IsSmallIndex()) // Fast path
|
|
|
{
|
|
|
if (JavascriptNativeIntArray::Is(aItem))
|
|
|
{
|
|
|
@@ -5700,6 +5701,7 @@ Case0:
|
|
|
bool isIntArray = false;
|
|
|
bool isFloatArray = false;
|
|
|
bool isTypedArrayEntryPoint = typedArrayBase != nullptr;
|
|
|
+ bool isBuiltinArrayCtor = true;
|
|
|
T startT = 0;
|
|
|
T newLenT = length;
|
|
|
T endT = length;
|
|
|
@@ -5752,10 +5754,11 @@ Case0:
|
|
|
if (isTypedArrayEntryPoint)
|
|
|
{
|
|
|
Var constructor = JavascriptOperators::SpeciesConstructor(typedArrayBase, TypedArrayBase::GetDefaultConstructor(args[0], scriptContext), scriptContext);
|
|
|
+ isBuiltinArrayCtor = (constructor == library->GetArrayConstructor());
|
|
|
|
|
|
// If we have an array source object, we need to make sure to do the right thing if it's a native array.
|
|
|
// The helpers below which do the element copying require the source and destination arrays to have the same native type.
|
|
|
- if (pArr && constructor == library->GetArrayConstructor())
|
|
|
+ if (pArr && isBuiltinArrayCtor)
|
|
|
{
|
|
|
if (newLenT > JavascriptArray::MaxArrayLength)
|
|
|
{
|
|
|
@@ -5789,13 +5792,13 @@ Case0:
|
|
|
|
|
|
else if (pArr != nullptr)
|
|
|
{
|
|
|
- newObj = ArraySpeciesCreate(pArr, newLenT, scriptContext, &isIntArray, &isFloatArray);
|
|
|
+ newObj = ArraySpeciesCreate(pArr, newLenT, scriptContext, &isIntArray, &isFloatArray, &isBuiltinArrayCtor);
|
|
|
}
|
|
|
|
|
|
// skip the typed array and "pure" array case, we still need to handle special arrays like es5array, remote array, and proxy of array.
|
|
|
else
|
|
|
{
|
|
|
- newObj = ArraySpeciesCreate(obj, newLenT, scriptContext);
|
|
|
+ newObj = ArraySpeciesCreate(obj, newLenT, scriptContext, nullptr, nullptr, &isBuiltinArrayCtor);
|
|
|
}
|
|
|
|
|
|
// If we didn't create a new object above we will create a new array here.
|
|
|
@@ -5839,7 +5842,7 @@ Case0:
|
|
|
if (pArr)
|
|
|
{
|
|
|
// If we constructed a new Array object, we have some nice helpers here
|
|
|
- if (newArr)
|
|
|
+ if (newArr && isBuiltinArrayCtor)
|
|
|
{
|
|
|
if (JavascriptArray::IsDirectAccessArray(newArr))
|
|
|
{
|
|
|
@@ -5885,7 +5888,7 @@ Case0:
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- newArr->DirectSetItemAt(i, element);
|
|
|
+ newArr->SetItem(i, element, PropertyOperation_None);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -5951,7 +5954,7 @@ Case0:
|
|
|
Var element = JavascriptOperators::GetItem(obj, i + start, scriptContext);
|
|
|
if (newArr != nullptr)
|
|
|
{
|
|
|
- newArr->DirectSetItemAt(i, element);
|
|
|
+ newArr->SetItem(i, element, PropertyOperation_None);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -6238,21 +6241,22 @@ Case0:
|
|
|
{
|
|
|
countUndefined++;
|
|
|
}
|
|
|
- orig[i] = SparseArraySegment<Var>::GetMissingItem();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (count == 0)
|
|
|
+ if (count > 0)
|
|
|
{
|
|
|
- *len = 0; // set the length to zero
|
|
|
- return countUndefined;
|
|
|
- }
|
|
|
+ SortElements(elements, 0, count - 1);
|
|
|
|
|
|
- SortElements(elements, 0, count - 1);
|
|
|
+ for (uint32 i = 0; i < count; ++i)
|
|
|
+ {
|
|
|
+ orig[i] = elements[i].Value;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- for (uint32 i = 0; i < count; ++i)
|
|
|
+ for (uint32 i = count + countUndefined; i < *len; ++i)
|
|
|
{
|
|
|
- orig[i] = elements[i].Value;
|
|
|
+ orig[i] = SparseArraySegment<Var>::GetMissingItem();
|
|
|
}
|
|
|
|
|
|
*len = count; // set the correct length
|
|
|
@@ -6583,6 +6587,7 @@ Case0:
|
|
|
|
|
|
bool isIntArray = false;
|
|
|
bool isFloatArray = false;
|
|
|
+ bool isBuiltinArrayCtor = true;
|
|
|
JavascriptArray *newArr = nullptr;
|
|
|
|
|
|
// Just dump the segment map on splice (before any possible allocation and throw)
|
|
|
@@ -6590,7 +6595,7 @@ Case0:
|
|
|
|
|
|
// If the source object is an Array exotic object (Array.isArray) we should try to load the constructor property
|
|
|
// and use it to construct the return object.
|
|
|
- newObj = ArraySpeciesCreate(pArr, deleteLen, scriptContext);
|
|
|
+ newObj = ArraySpeciesCreate(pArr, deleteLen, scriptContext, nullptr, nullptr, &isBuiltinArrayCtor);
|
|
|
if (newObj != nullptr)
|
|
|
{
|
|
|
pArr = EnsureNonNativeArray(pArr);
|
|
|
@@ -6608,7 +6613,7 @@ Case0:
|
|
|
}
|
|
|
|
|
|
// If return object is a JavascriptArray, we can use all the array splice helpers
|
|
|
- if (newArr)
|
|
|
+ if (newArr && isBuiltinArrayCtor)
|
|
|
{
|
|
|
|
|
|
// Array has a single segment (need not start at 0) and splice start lies in the range
|
|
|
@@ -6687,6 +6692,15 @@ Case0:
|
|
|
pArr->length = newLen;
|
|
|
}
|
|
|
|
|
|
+ if (newArr->length != deleteLen)
|
|
|
+ {
|
|
|
+ newArr->SetLength(deleteLen);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ newArr->length = deleteLen;
|
|
|
+ }
|
|
|
+
|
|
|
newArr->InvalidateLastUsedSegment();
|
|
|
|
|
|
#ifdef VALIDATE_ARRAY
|
|
|
@@ -7103,7 +7117,7 @@ Case0:
|
|
|
Var element = JavascriptOperators::GetItem(pObj, start + i, scriptContext);
|
|
|
if (pnewArr)
|
|
|
{
|
|
|
- pnewArr->DirectSetItemAt(i, element);
|
|
|
+ pnewArr->SetItem(i, element, PropertyOperation_None);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -7164,6 +7178,7 @@ Case0:
|
|
|
// Set up new length
|
|
|
indexT newLen = indexT(len - deleteLen) + insertLen;
|
|
|
h.ThrowTypeErrorOnFailure(JavascriptOperators::SetProperty(pObj, pObj, PropertyIds::length, IndexTrace<indexT>::ToNumber(newLen, scriptContext), scriptContext, PropertyOperation_ThrowIfNotExtensible));
|
|
|
+ h.ThrowTypeErrorOnFailure(JavascriptOperators::SetProperty(pNewObj, pNewObj, PropertyIds::length, IndexTrace<indexT>::ToNumber(deleteLen, scriptContext), scriptContext, PropertyOperation_ThrowIfNotExtensible));
|
|
|
#ifdef VALIDATE_ARRAY
|
|
|
if (pnewArr)
|
|
|
{
|
|
|
@@ -8790,6 +8805,7 @@ Case0:
|
|
|
RecyclableObject* newObj = nullptr;
|
|
|
JavascriptArray* newArr = nullptr;
|
|
|
bool isTypedArrayEntryPoint = typedArrayBase != nullptr;
|
|
|
+ bool isBuiltinArrayCtor = true;
|
|
|
|
|
|
if (args.Info.Count < 2 || !JavascriptConversion::IsCallable(args[1]))
|
|
|
{
|
|
|
@@ -8827,6 +8843,7 @@ Case0:
|
|
|
{
|
|
|
Var constructor = JavascriptOperators::SpeciesConstructor(
|
|
|
typedArrayBase, TypedArrayBase::GetDefaultConstructor(args[0], scriptContext), scriptContext);
|
|
|
+ isBuiltinArrayCtor = (constructor == scriptContext->GetLibrary()->GetArrayConstructor());
|
|
|
|
|
|
if (JavascriptOperators::IsConstructor(constructor))
|
|
|
{
|
|
|
@@ -8843,7 +8860,7 @@ Case0:
|
|
|
// skip the typed array and "pure" array case, we still need to handle special arrays like es5array, remote array, and proxy of array.
|
|
|
else if (pArr == nullptr || scriptContext->GetConfig()->IsES6SpeciesEnabled())
|
|
|
{
|
|
|
- newObj = ArraySpeciesCreate(obj, length, scriptContext);
|
|
|
+ newObj = ArraySpeciesCreate(obj, length, scriptContext, nullptr, nullptr, &isBuiltinArrayCtor);
|
|
|
}
|
|
|
|
|
|
if (newObj == nullptr)
|
|
|
@@ -8891,7 +8908,7 @@ Case0:
|
|
|
pArr);
|
|
|
|
|
|
// If newArr is a valid pointer, then we constructed an array to return. Otherwise we need to do generic object operations
|
|
|
- if (newArr)
|
|
|
+ if (newArr && isBuiltinArrayCtor)
|
|
|
{
|
|
|
newArr->DirectSetItemAt(k, mappedValue);
|
|
|
}
|
|
|
@@ -9662,7 +9679,7 @@ Case0:
|
|
|
|
|
|
if (newArr)
|
|
|
{
|
|
|
- newArr->DirectSetItemAt(k, nextValue);
|
|
|
+ newArr->SetItem(k, nextValue, PropertyOperation_None);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -9731,7 +9748,7 @@ Case0:
|
|
|
|
|
|
if (newArr)
|
|
|
{
|
|
|
- newArr->DirectSetItemAt(k, kValue);
|
|
|
+ newArr->SetItem(k, kValue, PropertyOperation_None);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -9781,10 +9798,12 @@ Case0:
|
|
|
Var newObj = nullptr;
|
|
|
JavascriptArray* newArr = nullptr;
|
|
|
TypedArrayBase* newTypedArray = nullptr;
|
|
|
+ bool isBuiltinArrayCtor = true;
|
|
|
|
|
|
if (JavascriptOperators::IsConstructor(args[0]))
|
|
|
{
|
|
|
RecyclableObject* constructor = RecyclableObject::FromVar(args[0]);
|
|
|
+ isBuiltinArrayCtor = (constructor == scriptContext->GetLibrary()->GetArrayConstructor());
|
|
|
|
|
|
Js::Var constructorArgs[] = { constructor, JavascriptNumber::ToVar(len, scriptContext) };
|
|
|
Js::CallInfo constructorCallInfo(Js::CallFlags_New, _countof(constructorArgs));
|
|
|
@@ -9818,7 +9837,7 @@ Case0:
|
|
|
// At least we have a new object of some kind
|
|
|
Assert(newObj);
|
|
|
|
|
|
- if (newArr)
|
|
|
+ if (isBuiltinArrayCtor)
|
|
|
{
|
|
|
for (uint32 k = 0; k < len; k++)
|
|
|
{
|
|
|
@@ -9999,11 +10018,11 @@ Case0:
|
|
|
if (index < startIndex) continue;
|
|
|
else if (index >= limitIndex) break;
|
|
|
|
|
|
- Var value;
|
|
|
- BOOL success = JavascriptOperators::GetOwnItem(es5Array, index, &value, scriptContext);
|
|
|
- Assert(success);
|
|
|
-
|
|
|
- fn(index, value);
|
|
|
+ Var value = nullptr;
|
|
|
+ if (JavascriptOperators::GetOwnItem(es5Array, index, &value, scriptContext))
|
|
|
+ {
|
|
|
+ fn(index, value);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -10066,11 +10085,11 @@ Case0:
|
|
|
T n = destIndex + (index - startIndex);
|
|
|
if (destArray == nullptr || !destArray->DirectGetItemAt(n, &oldValue))
|
|
|
{
|
|
|
- Var value;
|
|
|
- BOOL success = JavascriptOperators::GetOwnItem(es5Array, index, &value, scriptContext);
|
|
|
- Assert(success);
|
|
|
-
|
|
|
- fn(index, value);
|
|
|
+ Var value = nullptr;
|
|
|
+ if (JavascriptOperators::GetOwnItem(es5Array, index, &value, scriptContext))
|
|
|
+ {
|
|
|
+ fn(index, value);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -11353,7 +11372,7 @@ Case0:
|
|
|
|
|
|
template<typename T>
|
|
|
RecyclableObject*
|
|
|
- JavascriptArray::ArraySpeciesCreate(Var originalArray, T length, ScriptContext* scriptContext, bool* pIsIntArray, bool* pIsFloatArray)
|
|
|
+ JavascriptArray::ArraySpeciesCreate(Var originalArray, T length, ScriptContext* scriptContext, bool *pIsIntArray, bool *pIsFloatArray, bool *pIsBuiltinArrayCtor)
|
|
|
{
|
|
|
if (originalArray == nullptr || !scriptContext->GetConfig()->IsES6SpeciesEnabled())
|
|
|
{
|
|
|
@@ -11427,6 +11446,11 @@ Case0:
|
|
|
JavascriptError::ThrowTypeError(scriptContext, JSERR_NotAConstructor, _u("constructor[Symbol.species]"));
|
|
|
}
|
|
|
|
|
|
+ if (pIsBuiltinArrayCtor != nullptr)
|
|
|
+ {
|
|
|
+ *pIsBuiltinArrayCtor = false;
|
|
|
+ }
|
|
|
+
|
|
|
Js::Var constructorArgs[] = { constructor, JavascriptNumber::ToVar(length, scriptContext) };
|
|
|
Js::CallInfo constructorCallInfo(Js::CallFlags_New, _countof(constructorArgs));
|
|
|
|