PrimitiveString.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/CharacterTypes.h>
  7. #include <AK/Utf16View.h>
  8. #include <LibJS/Runtime/AbstractOperations.h>
  9. #include <LibJS/Runtime/GlobalObject.h>
  10. #include <LibJS/Runtime/PrimitiveString.h>
  11. #include <LibJS/Runtime/PropertyKey.h>
  12. #include <LibJS/Runtime/VM.h>
  13. #include <LibJS/Runtime/Value.h>
  14. namespace JS {
  15. PrimitiveString::PrimitiveString(String string)
  16. : m_utf8_string(move(string))
  17. , m_has_utf8_string(true)
  18. {
  19. }
  20. PrimitiveString::PrimitiveString(Utf16String string)
  21. : m_utf16_string(move(string))
  22. , m_has_utf16_string(true)
  23. {
  24. }
  25. PrimitiveString::~PrimitiveString()
  26. {
  27. vm().string_cache().remove(m_utf8_string);
  28. }
  29. String const& PrimitiveString::string() const
  30. {
  31. if (!m_has_utf8_string) {
  32. m_utf8_string = m_utf16_string.to_utf8();
  33. m_has_utf8_string = true;
  34. }
  35. return m_utf8_string;
  36. }
  37. Utf16String const& PrimitiveString::utf16_string() const
  38. {
  39. if (!m_has_utf16_string) {
  40. m_utf16_string = Utf16String(m_utf8_string);
  41. m_has_utf16_string = true;
  42. }
  43. return m_utf16_string;
  44. }
  45. Utf16View PrimitiveString::utf16_string_view() const
  46. {
  47. return utf16_string().view();
  48. }
  49. Optional<Value> PrimitiveString::get(GlobalObject& global_object, PropertyKey const& property_key) const
  50. {
  51. if (property_key.is_symbol())
  52. return {};
  53. if (property_key.is_string()) {
  54. if (property_key.as_string() == global_object.vm().names.length.as_string()) {
  55. auto length = utf16_string().length_in_code_units();
  56. return Value(static_cast<double>(length));
  57. }
  58. }
  59. auto index = canonical_numeric_index_string(property_key, CanonicalIndexMode::IgnoreNumericRoundtrip);
  60. if (!index.is_index())
  61. return {};
  62. auto str = utf16_string_view();
  63. auto length = str.length_in_code_units();
  64. if (length <= index.as_index())
  65. return {};
  66. return js_string(vm(), str.substring_view(index.as_index(), 1));
  67. }
  68. PrimitiveString* js_string(Heap& heap, Utf16View const& view)
  69. {
  70. return js_string(heap, Utf16String(view));
  71. }
  72. PrimitiveString* js_string(VM& vm, Utf16View const& view)
  73. {
  74. return js_string(vm.heap(), view);
  75. }
  76. PrimitiveString* js_string(Heap& heap, Utf16String string)
  77. {
  78. if (string.is_empty())
  79. return &heap.vm().empty_string();
  80. if (string.length_in_code_units() == 1) {
  81. u16 code_unit = string.code_unit_at(0);
  82. if (is_ascii(code_unit))
  83. return &heap.vm().single_ascii_character_string(static_cast<u8>(code_unit));
  84. }
  85. return heap.allocate_without_global_object<PrimitiveString>(move(string));
  86. }
  87. PrimitiveString* js_string(VM& vm, Utf16String string)
  88. {
  89. return js_string(vm.heap(), move(string));
  90. }
  91. PrimitiveString* js_string(Heap& heap, String string)
  92. {
  93. if (string.is_empty())
  94. return &heap.vm().empty_string();
  95. if (string.length() == 1) {
  96. auto ch = static_cast<u8>(string.characters()[0]);
  97. if (is_ascii(ch))
  98. return &heap.vm().single_ascii_character_string(ch);
  99. }
  100. auto& string_cache = heap.vm().string_cache();
  101. auto it = string_cache.find(string);
  102. if (it == string_cache.end()) {
  103. auto* new_string = heap.allocate_without_global_object<PrimitiveString>(string);
  104. string_cache.set(move(string), new_string);
  105. return new_string;
  106. }
  107. return it->value;
  108. }
  109. PrimitiveString* js_string(VM& vm, String string)
  110. {
  111. return js_string(vm.heap(), move(string));
  112. }
  113. }