2
0

JavascriptArrayIterator.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLibraryPch.h"
  6. namespace Js
  7. {
  8. JavascriptArrayIterator::JavascriptArrayIterator(DynamicType* type, Var iterable, JavascriptArrayIteratorKind kind):
  9. DynamicObject(type),
  10. m_iterableObject(iterable),
  11. m_nextIndex(0),
  12. m_kind(kind)
  13. {
  14. Assert(type->GetTypeId() == TypeIds_ArrayIterator);
  15. if (m_iterableObject == this->GetLibrary()->GetUndefined())
  16. {
  17. m_iterableObject = nullptr;
  18. }
  19. }
  20. Var JavascriptArrayIterator::EntryNext(RecyclableObject* function, CallInfo callInfo, ...)
  21. {
  22. PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
  23. ARGUMENTS(args, callInfo);
  24. ScriptContext* scriptContext = function->GetScriptContext();
  25. #ifdef ENABLE_JS_BUILTINS
  26. Assert(!scriptContext->IsJsBuiltInEnabled());
  27. #endif
  28. JavascriptLibrary* library = scriptContext->GetLibrary();
  29. Assert(!(callInfo.Flags & CallFlags_New));
  30. Var thisObj = args[0];
  31. if (!VarIs<JavascriptArrayIterator>(thisObj))
  32. {
  33. JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NeedArrayIterator, _u("Array Iterator.prototype.next"));
  34. }
  35. JavascriptArrayIterator* iterator = VarTo<JavascriptArrayIterator>(thisObj);
  36. Var iterable = iterator->m_iterableObject;
  37. if (iterable == nullptr)
  38. {
  39. return library->CreateIteratorResultObjectDone();
  40. }
  41. int64 length;
  42. JavascriptArray* pArr = nullptr;
  43. TypedArrayBase *typedArrayBase = nullptr;
  44. if (JavascriptArray::IsNonES5Array(iterable) && !VarTo<JavascriptArray>(iterable)->IsCrossSiteObject())
  45. {
  46. #if ENABLE_COPYONACCESS_ARRAY
  47. Assert(!VarIs<JavascriptCopyOnAccessNativeIntArray>(iterable));
  48. #endif
  49. pArr = JavascriptArray::FromAnyArray(iterable);
  50. length = pArr->GetLength();
  51. }
  52. else if (VarIs<TypedArrayBase>(iterable))
  53. {
  54. typedArrayBase = UnsafeVarTo<TypedArrayBase>(iterable);
  55. if (typedArrayBase->IsDetachedBuffer())
  56. {
  57. JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
  58. }
  59. length = typedArrayBase->GetLength();
  60. }
  61. else
  62. {
  63. length = JavascriptConversion::ToLength(JavascriptOperators::OP_GetLength(iterable, scriptContext), scriptContext);
  64. }
  65. int64 index = iterator->m_nextIndex;
  66. if (index >= length)
  67. {
  68. // Nulling out the m_iterableObject field is important so that the iterator
  69. // does not keep the iterable object alive after iteration is completed.
  70. iterator->m_iterableObject = nullptr;
  71. return library->CreateIteratorResultObjectDone();
  72. }
  73. iterator->m_nextIndex += 1;
  74. if (iterator->m_kind == JavascriptArrayIteratorKind::Key)
  75. {
  76. return library->CreateIteratorResultObject(JavascriptNumber::ToVar(index, scriptContext));
  77. }
  78. Var value;
  79. if (pArr != nullptr)
  80. {
  81. Assert(index <= UINT_MAX);
  82. value = pArr->DirectGetItem((uint32)index);
  83. }
  84. else if (typedArrayBase != nullptr)
  85. {
  86. Assert(index <= UINT_MAX);
  87. value = typedArrayBase->DirectGetItem((uint32)index);
  88. }
  89. else
  90. {
  91. value = JavascriptOperators::OP_GetElementI(iterable, JavascriptNumber::ToVar(index, scriptContext), scriptContext);
  92. }
  93. if (iterator->m_kind == JavascriptArrayIteratorKind::Value)
  94. {
  95. return library->CreateIteratorResultObject(value);
  96. }
  97. Assert(iterator->m_kind == JavascriptArrayIteratorKind::KeyAndValue);
  98. JavascriptArray* keyValueTuple = library->CreateArray(2);
  99. keyValueTuple->SetItem(0, JavascriptNumber::ToVar(index, scriptContext), PropertyOperation_None);
  100. keyValueTuple->SetItem(1, value, PropertyOperation_None);
  101. return library->CreateIteratorResultObject(keyValueTuple);
  102. }
  103. } //namespace Js