|
@@ -78,54 +78,68 @@ namespace Jint.Native.Array
|
|
|
|
|
|
if (objectInstance.IsArrayLike)
|
|
if (objectInstance.IsArrayLike)
|
|
{
|
|
{
|
|
- var operations = ArrayPrototype.ArrayOperations.For(objectInstance);
|
|
|
|
|
|
+ return ConstructArrayFromArrayLike(objectInstance, callable, thisArg);
|
|
|
|
+ }
|
|
|
|
|
|
- var length = operations.GetLength();
|
|
|
|
|
|
+ if (objectInstance is ObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
|
|
|
|
+ {
|
|
|
|
+ return ConstructArrayFromIEnumerable(enumerable);
|
|
|
|
+ }
|
|
|
|
|
|
- var a = _engine.Array.ConstructFast(length);
|
|
|
|
- var args = !ReferenceEquals(callable, null)
|
|
|
|
- ? _engine._jsValueArrayPool.RentArray(2)
|
|
|
|
- : null;
|
|
|
|
|
|
+ var instance = _engine.Array.ConstructFast(0);
|
|
|
|
+ if (objectInstance.TryGetIterator(_engine, out var iterator))
|
|
|
|
+ {
|
|
|
|
+ var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
|
|
|
|
+ protocol.Execute();
|
|
|
|
+ }
|
|
|
|
|
|
- uint n = 0;
|
|
|
|
- for (uint i = 0; i < length; i++)
|
|
|
|
- {
|
|
|
|
- JsValue jsValue;
|
|
|
|
- operations.TryGetValue(i, out var value);
|
|
|
|
- if (!ReferenceEquals(callable, null))
|
|
|
|
- {
|
|
|
|
- args[0] = value;
|
|
|
|
- args[1] = i;
|
|
|
|
- jsValue = callable.Call(thisArg, args);
|
|
|
|
-
|
|
|
|
- // function can alter data
|
|
|
|
- length = operations.GetLength();
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- jsValue = value;
|
|
|
|
- }
|
|
|
|
- a.SetIndexValue(i, jsValue, updateLength: false);
|
|
|
|
- n++;
|
|
|
|
- }
|
|
|
|
|
|
+ return instance;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private ArrayInstance ConstructArrayFromArrayLike(
|
|
|
|
+ ObjectInstance objectInstance,
|
|
|
|
+ ICallable callable,
|
|
|
|
+ JsValue thisArg)
|
|
|
|
+ {
|
|
|
|
+ var operations = ArrayPrototype.ArrayOperations.For(objectInstance);
|
|
|
|
|
|
|
|
+ var length = operations.GetLength();
|
|
|
|
+
|
|
|
|
+ var a = _engine.Array.ConstructFast(length);
|
|
|
|
+ var args = !ReferenceEquals(callable, null)
|
|
|
|
+ ? _engine._jsValueArrayPool.RentArray(2)
|
|
|
|
+ : null;
|
|
|
|
+
|
|
|
|
+ uint n = 0;
|
|
|
|
+ for (uint i = 0; i < length; i++)
|
|
|
|
+ {
|
|
|
|
+ JsValue jsValue;
|
|
|
|
+ operations.TryGetValue(i, out var value);
|
|
if (!ReferenceEquals(callable, null))
|
|
if (!ReferenceEquals(callable, null))
|
|
{
|
|
{
|
|
- _engine._jsValueArrayPool.ReturnArray(args);
|
|
|
|
|
|
+ args[0] = value;
|
|
|
|
+ args[1] = i;
|
|
|
|
+ jsValue = callable.Call(thisArg, args);
|
|
|
|
+
|
|
|
|
+ // function can alter data
|
|
|
|
+ length = operations.GetLength();
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ jsValue = value;
|
|
}
|
|
}
|
|
|
|
|
|
- a.SetLength(length);
|
|
|
|
- return a;
|
|
|
|
|
|
+ a.SetIndexValue(i, jsValue, updateLength: false);
|
|
|
|
+ n++;
|
|
}
|
|
}
|
|
|
|
|
|
- var instance = _engine.Array.ConstructFast(0);
|
|
|
|
- if (objectInstance.TryGetIterator(_engine, out var iterator))
|
|
|
|
|
|
+ if (!ReferenceEquals(callable, null))
|
|
{
|
|
{
|
|
- var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
|
|
|
|
- protocol.Execute();
|
|
|
|
|
|
+ _engine._jsValueArrayPool.ReturnArray(args);
|
|
}
|
|
}
|
|
|
|
|
|
- return instance;
|
|
|
|
|
|
+ a.SetLength(length);
|
|
|
|
+ return a;
|
|
}
|
|
}
|
|
|
|
|
|
internal sealed class ArrayProtocol : IteratorProtocol
|
|
internal sealed class ArrayProtocol : IteratorProtocol
|
|
@@ -248,18 +262,14 @@ namespace Jint.Native.Array
|
|
{
|
|
{
|
|
if (objectWrapper.Target is IEnumerable enumerable)
|
|
if (objectWrapper.Target is IEnumerable enumerable)
|
|
{
|
|
{
|
|
- var jsArray = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
|
|
|
|
- var tempArray = _engine._jsValueArrayPool.RentArray(1);
|
|
|
|
- foreach (var item in enumerable)
|
|
|
|
- {
|
|
|
|
- var jsItem = FromObject(Engine, item);
|
|
|
|
- tempArray[0] = jsItem;
|
|
|
|
- Engine.Array.PrototypeObject.Push(jsArray, tempArray);
|
|
|
|
- }
|
|
|
|
- _engine._jsValueArrayPool.ReturnArray(tempArray);
|
|
|
|
- return jsArray;
|
|
|
|
|
|
+ return ConstructArrayFromIEnumerable(enumerable);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ else if (arguments.Length == 1 && arguments[0] is ArrayInstance arrayInstance)
|
|
|
|
+ {
|
|
|
|
+ // direct copy
|
|
|
|
+ return ConstructArrayFromArrayLike(arrayInstance, null, this);
|
|
|
|
+ }
|
|
else
|
|
else
|
|
{
|
|
{
|
|
instance._length = new PropertyDescriptor(0, PropertyFlag.OnlyWritable);
|
|
instance._length = new PropertyDescriptor(0, PropertyFlag.OnlyWritable);
|
|
@@ -272,6 +282,21 @@ namespace Jint.Native.Array
|
|
return instance;
|
|
return instance;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private ArrayInstance ConstructArrayFromIEnumerable(IEnumerable enumerable)
|
|
|
|
+ {
|
|
|
|
+ var jsArray = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
|
|
|
|
+ var tempArray = _engine._jsValueArrayPool.RentArray(1);
|
|
|
|
+ foreach (var item in enumerable)
|
|
|
|
+ {
|
|
|
|
+ var jsItem = FromObject(Engine, item);
|
|
|
|
+ tempArray[0] = jsItem;
|
|
|
|
+ Engine.Array.PrototypeObject.Push(jsArray, tempArray);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ _engine._jsValueArrayPool.ReturnArray(tempArray);
|
|
|
|
+ return jsArray;
|
|
|
|
+ }
|
|
|
|
+
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
internal ArrayInstance ConstructFast(uint length)
|
|
internal ArrayInstance ConstructFast(uint length)
|
|
{
|
|
{
|