ES5ArrayIndexEnumerator.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. #pragma once
  6. namespace Js
  7. {
  8. //
  9. // An enumerator to enumerate ES5Array index property names as uint32 indices.
  10. //
  11. template <bool enumNonEnumerable = false>
  12. class ES5ArrayIndexEnumerator
  13. {
  14. public:
  15. typedef ES5Array ArrayType;
  16. private:
  17. ES5Array* m_array; // The ES5Array to enumerate on
  18. uint32 m_initialLength; // Initial length of the array, for snapshot
  19. uint32 m_index; // Current index
  20. uint32 m_dataIndex; // Current data item index
  21. uint32 m_descriptorIndex; // Current descriptor item index
  22. IndexPropertyDescriptor* m_descriptor; // Current descriptor associated with m_descriptorIndex
  23. void * m_descriptorValidationToken;
  24. public:
  25. ES5ArrayIndexEnumerator(ES5Array* array)
  26. : m_array(array)
  27. {
  28. Reset();
  29. }
  30. //
  31. // Reset to enumerate from beginning.
  32. //
  33. void Reset()
  34. {
  35. m_initialLength = m_array->GetLength();
  36. m_index = JavascriptArray::InvalidIndex;
  37. m_dataIndex = JavascriptArray::InvalidIndex;
  38. m_descriptorIndex = JavascriptArray::InvalidIndex;
  39. m_descriptor = NULL;
  40. m_descriptorValidationToken = nullptr;
  41. }
  42. //
  43. // Get the current index. Valid only when MoveNext() returns true.
  44. //
  45. uint32 GetIndex() const
  46. {
  47. return m_index;
  48. }
  49. //
  50. // Move to next index. If successful, use GetIndex() to get the index.
  51. //
  52. bool MoveNext(PropertyAttributes* attributes = nullptr)
  53. {
  54. while (true)
  55. {
  56. Assert(m_index == min(m_dataIndex, m_descriptorIndex));
  57. if (m_index == m_dataIndex)
  58. {
  59. m_dataIndex = m_array->GetNextIndex(m_dataIndex);
  60. }
  61. if (m_index == m_descriptorIndex || !m_array->IsValidDescriptorToken(m_descriptorValidationToken))
  62. {
  63. m_descriptorIndex = m_array->GetNextDescriptor(m_index, &m_descriptor, &m_descriptorValidationToken);
  64. }
  65. m_index = min(m_dataIndex, m_descriptorIndex);
  66. if (m_index >= m_initialLength) // End of array
  67. {
  68. break;
  69. }
  70. if (enumNonEnumerable
  71. || m_index < m_descriptorIndex
  72. || (m_descriptor->Attributes & PropertyEnumerable))
  73. {
  74. if (attributes != nullptr)
  75. {
  76. if (m_index < m_descriptorIndex)
  77. {
  78. *attributes = PropertyEnumerable;
  79. }
  80. else
  81. {
  82. *attributes = m_descriptor->Attributes;
  83. }
  84. }
  85. return true;
  86. }
  87. }
  88. return false;
  89. }
  90. };
  91. }