@@ -752,6 +752,40 @@ namespace Js
752
752
return IsMissingHeadSegmentItemImpl<double >(index);
753
753
}
754
754
755
+ template <typename T>
756
+ void JavascriptArray::InternalFillFromPrototype (JavascriptArray *dstArray, const T& dstIndex, JavascriptArray *srcArray, uint32 start, uint32 end, uint32 count)
757
+ {
758
+ RecyclableObject* prototype = srcArray->GetPrototype ();
759
+ while (start + count != end && JavascriptOperators::GetTypeId (prototype) != TypeIds_Null)
760
+ {
761
+ ForEachOwnMissingArrayIndexOfObject (srcArray, dstArray, prototype, start, end, dstIndex, [&](uint32 index, Var value) {
762
+ T n = dstIndex + (index - start);
763
+ dstArray->DirectSetItemAt (n, value);
764
+
765
+ count++;
766
+ });
767
+
768
+ prototype = prototype->GetPrototype ();
769
+ }
770
+ }
771
+
772
+ template <>
773
+ void JavascriptArray::InternalFillFromPrototype<uint32>(JavascriptArray *dstArray, const uint32& dstIndex, JavascriptArray *srcArray, uint32 start, uint32 end, uint32 count)
774
+ {
775
+ RecyclableObject* prototype = srcArray->GetPrototype ();
776
+ while (start + count != end && JavascriptOperators::GetTypeId (prototype) != TypeIds_Null)
777
+ {
778
+ ForEachOwnMissingArrayIndexOfObject (srcArray, dstArray, prototype, start, end, dstIndex, [&](uint32 index, Var value) {
779
+ uint32 n = dstIndex + (index - start);
780
+ dstArray->SetItem (n, value, PropertyOperation_None);
781
+
782
+ count++;
783
+ });
784
+
785
+ prototype = prototype->GetPrototype ();
786
+ }
787
+ }
788
+
755
789
/* static */
756
790
bool JavascriptArray::HasInlineHeadSegment (uint32 length)
757
791
{
@@ -3380,6 +3414,9 @@ namespace Js
3380
3414
pDestObj = ArraySpeciesCreate (args[0 ], 0 , scriptContext);
3381
3415
if (pDestObj)
3382
3416
{
3417
+ #if ENABLE_COPYONACCESS_ARRAY
3418
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(pDestObj);
3419
+ #endif
3383
3420
// Check the thing that species create made. If it's a native array that can't handle the source
3384
3421
// data, convert it. If it's a more conservative kind of array than the source data, indicate that
3385
3422
// so that the data will be converted on copy.
@@ -5958,13 +5995,19 @@ namespace Js
5958
5995
}
5959
5996
5960
5997
newArr = CreateNewArrayHelper (static_cast <uint32>(newLenT), isIntArray, isFloatArray, pArr, scriptContext);
5998
+ #if ENABLE_COPYONACCESS_ARRAY
5999
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newArr);
6000
+ #endif
5961
6001
newObj = newArr;
5962
6002
}
5963
6003
else
5964
6004
{
5965
6005
// If the new object we created is an array, remember that as it will save us time setting properties in the object below
5966
6006
if (JavascriptArray::Is (newObj))
5967
6007
{
6008
+ #if ENABLE_COPYONACCESS_ARRAY
6009
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
6010
+ #endif
5968
6011
newArr = JavascriptArray::FromVar (newObj);
5969
6012
}
5970
6013
}
@@ -6744,6 +6787,9 @@ namespace Js
6744
6787
// If the new object we created is an array, remember that as it will save us time setting properties in the object below
6745
6788
if (JavascriptArray::Is (newObj))
6746
6789
{
6790
+ #if ENABLE_COPYONACCESS_ARRAY
6791
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
6792
+ #endif
6747
6793
newArr = JavascriptArray::FromVar (newObj);
6748
6794
}
6749
6795
}
@@ -6752,10 +6798,13 @@ namespace Js
6752
6798
{
6753
6799
pArr->GetArrayTypeAndConvert (&isIntArray, &isFloatArray);
6754
6800
newArr = CreateNewArrayHelper (deleteLen, isIntArray, isFloatArray, pArr, scriptContext);
6801
+ #if ENABLE_COPYONACCESS_ARRAY
6802
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newArr);
6803
+ #endif
6755
6804
}
6756
6805
6757
6806
// If return object is a JavascriptArray, we can use all the array splice helpers
6758
- if (newArr && isBuiltinArrayCtor)
6807
+ if (newArr && isBuiltinArrayCtor && len == pArr-> length )
6759
6808
{
6760
6809
6761
6810
// Array has a single segment (need not start at 0) and splice start lies in the range
@@ -7246,6 +7295,9 @@ namespace Js
7246
7295
7247
7296
if (JavascriptArray::Is (pNewObj))
7248
7297
{
7298
+ #if ENABLE_COPYONACCESS_ARRAY
7299
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(pNewObj);
7300
+ #endif
7249
7301
pnewArr = JavascriptArray::FromVar (pNewObj);
7250
7302
}
7251
7303
@@ -8993,6 +9045,9 @@ namespace Js
8993
9045
// If the new object we created is an array, remember that as it will save us time setting properties in the object below
8994
9046
if (JavascriptArray::Is (newObj))
8995
9047
{
9048
+ #if ENABLE_COPYONACCESS_ARRAY
9049
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
9050
+ #endif
8996
9051
newArr = JavascriptArray::FromVar (newObj);
8997
9052
}
8998
9053
}
@@ -9182,7 +9237,8 @@ namespace Js
9182
9237
}
9183
9238
9184
9239
// If the source object is an Array exotic object we should try to load the constructor property and use it to construct the return object.
9185
- RecyclableObject* newObj = ArraySpeciesCreate (obj, 0 , scriptContext);
9240
+ bool isBuiltinArrayCtor = true ;
9241
+ RecyclableObject* newObj = ArraySpeciesCreate (obj, 0 , scriptContext, nullptr , nullptr , &isBuiltinArrayCtor);
9186
9242
JavascriptArray* newArr = nullptr ;
9187
9243
9188
9244
if (newObj == nullptr )
@@ -9196,6 +9252,9 @@ namespace Js
9196
9252
// If the new object we created is an array, remember that as it will save us time setting properties in the object below
9197
9253
if (JavascriptArray::Is (newObj))
9198
9254
{
9255
+ #if ENABLE_COPYONACCESS_ARRAY
9256
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(newObj);
9257
+ #endif
9199
9258
newArr = JavascriptArray::FromVar (newObj);
9200
9259
}
9201
9260
}
@@ -9224,7 +9283,7 @@ namespace Js
9224
9283
if (JavascriptConversion::ToBoolean (selected, scriptContext))
9225
9284
{
9226
9285
// Try to fast path if the return object is an array
9227
- if (newArr)
9286
+ if (newArr && isBuiltinArrayCtor )
9228
9287
{
9229
9288
newArr->DirectSetItemAt (i, element);
9230
9289
}
@@ -10071,6 +10130,60 @@ namespace Js
10071
10130
}
10072
10131
#endif
10073
10132
10133
+ template <typename Fn>
10134
+ void JavascriptArray::ForEachOwnArrayIndexOfObject (RecyclableObject* obj, uint32 startIndex, uint32 limitIndex, Fn fn)
10135
+ {
10136
+ Assert (DynamicObject::IsAnyArray (obj) || JavascriptOperators::IsObject (obj));
10137
+
10138
+ JavascriptArray* arr = nullptr ;
10139
+ if (DynamicObject::IsAnyArray (obj))
10140
+ {
10141
+ arr = JavascriptArray::FromAnyArray (obj);
10142
+ }
10143
+ else if (DynamicType::Is (obj->GetTypeId ()))
10144
+ {
10145
+ DynamicObject* dynobj = DynamicObject::FromVar (obj);
10146
+ arr = dynobj->GetObjectArray ();
10147
+ }
10148
+
10149
+ if (arr != nullptr )
10150
+ {
10151
+ if (JavascriptArray::Is (arr))
10152
+ {
10153
+ arr = EnsureNonNativeArray (arr);
10154
+ ArrayElementEnumerator e (arr, startIndex, limitIndex);
10155
+
10156
+ while (e.MoveNext <Var>())
10157
+ {
10158
+ fn (e.GetIndex (), e.GetItem <Var>());
10159
+ }
10160
+ }
10161
+ else
10162
+ {
10163
+ ScriptContext* scriptContext = obj->GetScriptContext ();
10164
+
10165
+ Assert (ES5Array::Is (arr));
10166
+
10167
+ ES5Array* es5Array = ES5Array::FromVar (arr);
10168
+ ES5ArrayIndexEnumerator<true > e (es5Array);
10169
+
10170
+ while (e.MoveNext ())
10171
+ {
10172
+ uint32 index = e.GetIndex ();
10173
+
10174
+ if (index < startIndex) continue ;
10175
+ else if (index >= limitIndex) break ;
10176
+
10177
+ Var value = nullptr ;
10178
+ if (JavascriptOperators::GetOwnItem (es5Array, index, &value, scriptContext))
10179
+ {
10180
+ fn (index, value);
10181
+ }
10182
+ }
10183
+ }
10184
+ }
10185
+ }
10186
+
10074
10187
template <typename T, typename Fn>
10075
10188
void JavascriptArray::ForEachOwnMissingArrayIndexOfObject (JavascriptArray *baseArray, JavascriptArray *destArray, RecyclableObject* obj, uint32 startIndex, uint32 limitIndex, T destIndex, Fn fn)
10076
10189
{
@@ -10093,6 +10206,7 @@ namespace Js
10093
10206
{
10094
10207
if (JavascriptArray::Is (arr))
10095
10208
{
10209
+ arr = EnsureNonNativeArray (arr);
10096
10210
ArrayElementEnumerator e (arr, startIndex, limitIndex);
10097
10211
10098
10212
while (e.MoveNext <Var>())
@@ -10846,6 +10960,9 @@ namespace Js
10846
10960
10847
10961
JavascriptArray *JavascriptArray::EnsureNonNativeArray (JavascriptArray *arr)
10848
10962
{
10963
+ #if ENABLE_COPYONACCESS_ARRAY
10964
+ JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray<Var>(arr);
10965
+ #endif
10849
10966
if (JavascriptNativeIntArray::Is (arr))
10850
10967
{
10851
10968
arr = JavascriptNativeIntArray::ToVarArray ((JavascriptNativeIntArray*)arr);
@@ -10928,23 +11045,6 @@ namespace Js
10928
11045
}
10929
11046
}
10930
11047
10931
- template <typename T>
10932
- void JavascriptArray::InternalFillFromPrototype (JavascriptArray *dstArray, const T& dstIndex, JavascriptArray *srcArray, uint32 start, uint32 end, uint32 count)
10933
- {
10934
- RecyclableObject* prototype = srcArray->GetPrototype ();
10935
- while (start + count != end && JavascriptOperators::GetTypeId (prototype) != TypeIds_Null)
10936
- {
10937
- ForEachOwnMissingArrayIndexOfObject (srcArray, dstArray, prototype, start, end, dstIndex, [&](uint32 index, Var value) {
10938
- T n = dstIndex + (index - start);
10939
- dstArray->DirectSetItemAt (n, value);
10940
-
10941
- count++;
10942
- });
10943
-
10944
- prototype = prototype->GetPrototype ();
10945
- }
10946
- }
10947
-
10948
11048
Var JavascriptArray::SpreadArrayArgs (Var arrayToSpread, const Js::AuxArray<uint32> *spreadIndices, ScriptContext *scriptContext)
10949
11049
{
10950
11050
// At this stage we have an array literal with some arguments to be spread.
@@ -11559,6 +11659,11 @@ namespace Js
11559
11659
{
11560
11660
if (!JavascriptOperators::GetProperty ((RecyclableObject*)constructor, PropertyIds::_symbolSpecies, &constructor, scriptContext))
11561
11661
{
11662
+ if (pIsBuiltinArrayCtor != nullptr )
11663
+ {
11664
+ *pIsBuiltinArrayCtor = false ;
11665
+ }
11666
+
11562
11667
return nullptr ;
11563
11668
}
11564
11669
if (constructor == scriptContext->GetLibrary ()->GetNull ())
0 commit comments