1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 19:37:36 +00:00

LibJS: Make Utf16String & related APIs infallible

Work towards #20449.
This commit is contained in:
Andreas Kling 2023-08-08 18:54:20 +02:00
parent 9708b86d65
commit 7849950383
15 changed files with 82 additions and 88 deletions

View file

@ -847,13 +847,11 @@ ErrorOr<void> print_intl_segmenter(JS::PrintContext& print_context, JS::Intl::Se
ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, HashTable<JS::Object*>& seen_objects) ErrorOr<void> print_intl_segments(JS::PrintContext& print_context, JS::Intl::Segments const& segments, HashTable<JS::Object*>& seen_objects)
{ {
auto segments_string = JS::Utf16String::create(segments.vm(), segments.segments_string()); auto segments_string = JS::Utf16String::create(segments.segments_string());
if (segments_string.is_error())
return Error::from_errno(ENOMEM);
TRY(print_type(print_context, "Segments"sv)); TRY(print_type(print_context, "Segments"sv));
out("\n string: "); out("\n string: ");
TRY(print_value(print_context, JS::PrimitiveString::create(segments.vm(), segments_string.release_value()), seen_objects)); TRY(print_value(print_context, JS::PrimitiveString::create(segments.vm(), move(segments_string)), seen_objects));
out("\n segmenter: "); out("\n segmenter: ");
TRY(print_value(print_context, &segments.segments_segmenter(), seen_objects)); TRY(print_value(print_context, &segments.segments_segmenter(), seen_objects));
return {}; return {};

View file

@ -388,7 +388,7 @@ JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_int)
// 19.2.6.5 Encode ( string, extraUnescaped ), https://tc39.es/ecma262/#sec-encode // 19.2.6.5 Encode ( string, extraUnescaped ), https://tc39.es/ecma262/#sec-encode
static ThrowCompletionOr<DeprecatedString> encode(VM& vm, DeprecatedString const& string, StringView unescaped_set) static ThrowCompletionOr<DeprecatedString> encode(VM& vm, DeprecatedString const& string, StringView unescaped_set)
{ {
auto utf16_string = TRY(Utf16String::create(vm, string)); auto utf16_string = Utf16String::create(string);
// 1. Let strLen be the length of string. // 1. Let strLen be the length of string.
auto string_length = utf16_string.length_in_code_units(); auto string_length = utf16_string.length_in_code_units();

View file

@ -633,7 +633,7 @@ ThrowCompletionOr<Vector<PatternPartition>> format_date_time_pattern(VM& vm, Dat
// 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters. // 2. If the "length" property of fv is greater than 2, let fv be the substring of fv containing the last two characters.
// NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII. // NOTE: The first length check here isn't enough, but lets us avoid UTF-16 transcoding when the formatted value is ASCII.
if (formatted_value.bytes_as_string_view().length() > 2) { if (formatted_value.bytes_as_string_view().length() > 2) {
auto utf16_formatted_value = TRY(Utf16String::create(vm, formatted_value)); auto utf16_formatted_value = Utf16String::create(formatted_value);
if (utf16_formatted_value.length_in_code_units() > 2) if (utf16_formatted_value.length_in_code_units() > 2)
formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8()); formatted_value = TRY_OR_THROW_OOM(vm, utf16_formatted_value.substring_view(utf16_formatted_value.length_in_code_units() - 2).to_utf8());
} }

View file

@ -68,13 +68,13 @@ ThrowCompletionOr<NonnullGCPtr<Object>> create_segment_data_object(VM& vm, Segme
auto segment = string.substring_view(start_index, end_index - start_index); auto segment = string.substring_view(start_index, end_index - start_index);
// 7. Perform ! CreateDataPropertyOrThrow(result, "segment", segment). // 7. Perform ! CreateDataPropertyOrThrow(result, "segment", segment).
MUST(result->create_data_property_or_throw(vm.names.segment, PrimitiveString::create(vm, TRY(Utf16String::create(vm, segment))))); MUST(result->create_data_property_or_throw(vm.names.segment, PrimitiveString::create(vm, Utf16String::create(segment))));
// 8. Perform ! CreateDataPropertyOrThrow(result, "index", 𝔽(startIndex)). // 8. Perform ! CreateDataPropertyOrThrow(result, "index", 𝔽(startIndex)).
MUST(result->create_data_property_or_throw(vm.names.index, Value(start_index))); MUST(result->create_data_property_or_throw(vm.names.index, Value(start_index)));
// 9. Perform ! CreateDataPropertyOrThrow(result, "input", string). // 9. Perform ! CreateDataPropertyOrThrow(result, "input", string).
MUST(result->create_data_property_or_throw(vm.names.input, PrimitiveString::create(vm, TRY(Utf16String::create(vm, string))))); MUST(result->create_data_property_or_throw(vm.names.input, PrimitiveString::create(vm, Utf16String::create(string))));
// 10. Let granularity be segmenter.[[SegmenterGranularity]]. // 10. Let granularity be segmenter.[[SegmenterGranularity]].
auto granularity = segmenter.segmenter_granularity(); auto granularity = segmenter.segmenter_granularity();

View file

@ -83,7 +83,7 @@ ThrowCompletionOr<String> PrimitiveString::utf8_string() const
if (has_deprecated_string()) if (has_deprecated_string())
m_utf8_string = TRY_OR_THROW_OOM(vm, String::from_deprecated_string(*m_deprecated_string)); m_utf8_string = TRY_OR_THROW_OOM(vm, String::from_deprecated_string(*m_deprecated_string));
else if (has_utf16_string()) else if (has_utf16_string())
m_utf8_string = TRY(m_utf16_string->to_utf8(vm)); m_utf8_string = m_utf16_string->to_utf8();
else else
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -105,7 +105,7 @@ ThrowCompletionOr<DeprecatedString> PrimitiveString::deprecated_string() const
if (has_utf8_string()) if (has_utf8_string())
m_deprecated_string = m_utf8_string->to_deprecated_string(); m_deprecated_string = m_utf8_string->to_deprecated_string();
else if (has_utf16_string()) else if (has_utf16_string())
m_deprecated_string = TRY(m_utf16_string->to_deprecated_string(vm())); m_deprecated_string = m_utf16_string->to_deprecated_string();
else else
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -113,25 +113,25 @@ ThrowCompletionOr<DeprecatedString> PrimitiveString::deprecated_string() const
return *m_deprecated_string; return *m_deprecated_string;
} }
ThrowCompletionOr<Utf16String> PrimitiveString::utf16_string() const Utf16String PrimitiveString::utf16_string() const
{ {
resolve_rope_if_needed(EncodingPreference::UTF16); resolve_rope_if_needed(EncodingPreference::UTF16);
if (!has_utf16_string()) { if (!has_utf16_string()) {
if (has_utf8_string()) { if (has_utf8_string()) {
m_utf16_string = TRY(Utf16String::create(vm(), m_utf8_string->bytes_as_string_view())); m_utf16_string = Utf16String::create(m_utf8_string->bytes_as_string_view());
} else { } else {
VERIFY(has_deprecated_string()); VERIFY(has_deprecated_string());
m_utf16_string = TRY(Utf16String::create(vm(), *m_deprecated_string)); m_utf16_string = Utf16String::create(*m_deprecated_string);
} }
} }
return *m_utf16_string; return *m_utf16_string;
} }
ThrowCompletionOr<Utf16View> PrimitiveString::utf16_string_view() const Utf16View PrimitiveString::utf16_string_view() const
{ {
(void)TRY(utf16_string()); (void)utf16_string();
return m_utf16_string->view(); return m_utf16_string->view();
} }
@ -141,18 +141,18 @@ ThrowCompletionOr<Optional<Value>> PrimitiveString::get(VM& vm, PropertyKey cons
return Optional<Value> {}; return Optional<Value> {};
if (property_key.is_string()) { if (property_key.is_string()) {
if (property_key.as_string() == vm.names.length.as_string()) { if (property_key.as_string() == vm.names.length.as_string()) {
auto length = TRY(utf16_string()).length_in_code_units(); auto length = utf16_string().length_in_code_units();
return Value(static_cast<double>(length)); return Value(static_cast<double>(length));
} }
} }
auto index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm, property_key, CanonicalIndexMode::IgnoreNumericRoundtrip)); auto index = MUST_OR_THROW_OOM(canonical_numeric_index_string(vm, property_key, CanonicalIndexMode::IgnoreNumericRoundtrip));
if (!index.is_index()) if (!index.is_index())
return Optional<Value> {}; return Optional<Value> {};
auto str = TRY(utf16_string_view()); auto str = utf16_string_view();
auto length = str.length_in_code_units(); auto length = str.length_in_code_units();
if (length <= index.as_index()) if (length <= index.as_index())
return Optional<Value> {}; return Optional<Value> {};
return create(vm, TRY(Utf16String::create(vm, str.substring_view(index.as_index(), 1)))); return create(vm, Utf16String::create(str.substring_view(index.as_index(), 1)));
} }
NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16String string) NonnullGCPtr<PrimitiveString> PrimitiveString::create(VM& vm, Utf16String string)
@ -250,8 +250,6 @@ void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) cons
if (!m_is_rope) if (!m_is_rope)
return; return;
auto& vm = this->vm();
// This vector will hold all the pieces of the rope that need to be assembled // This vector will hold all the pieces of the rope that need to be assembled
// into the resolved string. // into the resolved string.
Vector<PrimitiveString const*> pieces; Vector<PrimitiveString const*> pieces;
@ -277,9 +275,9 @@ void PrimitiveString::resolve_rope_if_needed(EncodingPreference preference) cons
Utf16Data code_units; Utf16Data code_units;
for (auto const* current : pieces) for (auto const* current : pieces)
code_units.extend(MUST(current->utf16_string()).string()); code_units.extend(current->utf16_string().string());
m_utf16_string = MUST(Utf16String::create(vm, move(code_units))); m_utf16_string = Utf16String::create(move(code_units));
m_is_rope = false; m_is_rope = false;
m_lhs = nullptr; m_lhs = nullptr;
m_rhs = nullptr; m_rhs = nullptr;

View file

@ -45,8 +45,8 @@ public:
ThrowCompletionOr<DeprecatedString> deprecated_string() const; ThrowCompletionOr<DeprecatedString> deprecated_string() const;
bool has_deprecated_string() const { return m_deprecated_string.has_value(); } bool has_deprecated_string() const { return m_deprecated_string.has_value(); }
ThrowCompletionOr<Utf16String> utf16_string() const; [[nodiscard]] Utf16String utf16_string() const;
ThrowCompletionOr<Utf16View> utf16_string_view() const; [[nodiscard]] Utf16View utf16_string_view() const;
bool has_utf16_string() const { return m_utf16_string.has_value(); } bool has_utf16_string() const { return m_utf16_string.has_value(); }
ThrowCompletionOr<Optional<Value>> get(VM&, PropertyKey const&) const; ThrowCompletionOr<Optional<Value>> get(VM&, PropertyKey const&) const;

View file

@ -68,7 +68,7 @@ ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstruc
} }
// UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues- // UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues-
ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values) void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values)
{ {
auto& legacy_static_properties = constructor.legacy_static_properties(); auto& legacy_static_properties = constructor.legacy_static_properties();
@ -92,7 +92,7 @@ ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpCon
// 8. Set the value of Cs [[RegExpLastMatch]] internal slot to a String whose length is endIndex - startIndex and containing the code units from S with indices startIndex through endIndex - 1, in ascending order. // 8. Set the value of Cs [[RegExpLastMatch]] internal slot to a String whose length is endIndex - startIndex and containing the code units from S with indices startIndex through endIndex - 1, in ascending order.
auto last_match = string.view().substring_view(start_index, end_index - start_index); auto last_match = string.view().substring_view(start_index, end_index - start_index);
legacy_static_properties.set_last_match(TRY(Utf16String::create(vm, last_match))); legacy_static_properties.set_last_match(Utf16String::create(last_match));
// 9. If n > 0, set the value of Cs [[RegExpLastParen]] internal slot to the last element of capturedValues. // 9. If n > 0, set the value of Cs [[RegExpLastParen]] internal slot to the last element of capturedValues.
if (group_count > 0) { if (group_count > 0) {
@ -101,22 +101,22 @@ ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpCon
} }
// 10. Else, set the value of Cs [[RegExpLastParen]] internal slot to the empty String. // 10. Else, set the value of Cs [[RegExpLastParen]] internal slot to the empty String.
else { else {
legacy_static_properties.set_last_paren(TRY(Utf16String::create(vm))); legacy_static_properties.set_last_paren(Utf16String::create());
} }
// 11. Set the value of Cs [[RegExpLeftContext]] internal slot to a String whose length is startIndex and containing the code units from S with indices 0 through startIndex - 1, in ascending order. // 11. Set the value of Cs [[RegExpLeftContext]] internal slot to a String whose length is startIndex and containing the code units from S with indices 0 through startIndex - 1, in ascending order.
auto left_context = string.view().substring_view(0, start_index); auto left_context = string.view().substring_view(0, start_index);
legacy_static_properties.set_left_context(TRY(Utf16String::create(vm, left_context))); legacy_static_properties.set_left_context(Utf16String::create(left_context));
// 12. Set the value of Cs [[RegExpRightContext]] internal slot to a String whose length is len - endIndex and containing the code units from S with indices endIndex through len - 1, in ascending order. // 12. Set the value of Cs [[RegExpRightContext]] internal slot to a String whose length is len - endIndex and containing the code units from S with indices endIndex through len - 1, in ascending order.
auto right_context = string.view().substring_view(end_index, len - end_index); auto right_context = string.view().substring_view(end_index, len - end_index);
legacy_static_properties.set_right_context(TRY(Utf16String::create(vm, right_context))); legacy_static_properties.set_right_context(Utf16String::create(right_context));
// 13. For each integer i such that 1 ≤ i ≤ 9 // 13. For each integer i such that 1 ≤ i ≤ 9
for (size_t i = 1; i <= 9; i++) { for (size_t i = 1; i <= 9; i++) {
// i. If i ≤ n, set the value of Cs [[RegExpPareni]] internal slot to the ith element of capturedValues. // i. If i ≤ n, set the value of Cs [[RegExpPareni]] internal slot to the ith element of capturedValues.
// ii. Else, set the value of Cs [[RegExpPareni]] internal slot to the empty String. // ii. Else, set the value of Cs [[RegExpPareni]] internal slot to the empty String.
auto value = (i <= group_count) ? captured_values[i - 1] : TRY(Utf16String::create(vm)); auto value = (i <= group_count) ? captured_values[i - 1] : Utf16String::create();
if (i == 1) { if (i == 1) {
legacy_static_properties.set_$1(move(value)); legacy_static_properties.set_$1(move(value));
@ -138,8 +138,6 @@ ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpCon
legacy_static_properties.set_$9(move(value)); legacy_static_properties.set_$9(move(value));
} }
} }
return {};
} }
// InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c // InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c

View file

@ -72,7 +72,7 @@ private:
ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value); ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value);
ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const); ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const);
ThrowCompletionOr<void> update_legacy_regexp_static_properties(VM& vm, RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values); void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values);
void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor); void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor);
} }

View file

@ -277,7 +277,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 28. Let matchedValue be ! GetMatchString(S, match). // 28. Let matchedValue be ! GetMatchString(S, match).
// 29. Perform ! CreateDataPropertyOrThrow(A, "0", matchedValue). // 29. Perform ! CreateDataPropertyOrThrow(A, "0", matchedValue).
MUST(array->create_data_property_or_throw(0, PrimitiveString::create(vm, TRY(Utf16String::create(vm, match.view.u16_view()))))); MUST(array->create_data_property_or_throw(0, PrimitiveString::create(vm, Utf16String::create(match.view.u16_view()))));
// 30. If R contains any GroupName, then // 30. If R contains any GroupName, then
// a. Let groups be OrdinaryObjectCreate(null). // a. Let groups be OrdinaryObjectCreate(null).
@ -302,7 +302,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// ii. Append undefined to indices. // ii. Append undefined to indices.
indices.append({}); indices.append({});
// iii. Append capture to indices. // iii. Append capture to indices.
captured_values.append(TRY(Utf16String::create(vm))); captured_values.append(Utf16String::create());
} }
// c. Else, // c. Else,
else { else {
@ -313,7 +313,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// 2. Set captureEnd to ! GetStringIndex(S, Input, captureEnd). // 2. Set captureEnd to ! GetStringIndex(S, Input, captureEnd).
// iv. Let capture be the Match { [[StartIndex]]: captureStart, [[EndIndex]: captureEnd }. // iv. Let capture be the Match { [[StartIndex]]: captureStart, [[EndIndex]: captureEnd }.
// v. Let capturedValue be ! GetMatchString(S, capture). // v. Let capturedValue be ! GetMatchString(S, capture).
auto capture_as_utf16_string = TRY(Utf16String::create(vm, capture.view.u16_view())); auto capture_as_utf16_string = Utf16String::create(capture.view.u16_view());
captured_value = PrimitiveString::create(vm, capture_as_utf16_string); captured_value = PrimitiveString::create(vm, capture_as_utf16_string);
// vi. Append capture to indices. // vi. Append capture to indices.
indices.append(Match::create(capture)); indices.append(Match::create(capture));
@ -352,7 +352,7 @@ static ThrowCompletionOr<Value> regexp_builtin_exec(VM& vm, RegExpObject& regexp
// i. If the value of Rs [[LegacyFeaturesEnabled]] internal slot is true, then // i. If the value of Rs [[LegacyFeaturesEnabled]] internal slot is true, then
if (regexp_object.legacy_features_enabled()) { if (regexp_object.legacy_features_enabled()) {
// a. Perform UpdateLegacyRegExpStaticProperties(%RegExp%, S, lastIndex, e, capturedValues). // a. Perform UpdateLegacyRegExpStaticProperties(%RegExp%, S, lastIndex, e, capturedValues).
TRY(update_legacy_regexp_static_properties(vm, realm.intrinsics().regexp_constructor(), string, match_indices.start_index, match_indices.end_index, captured_values)); update_legacy_regexp_static_properties(realm.intrinsics().regexp_constructor(), string, match_indices.start_index, match_indices.end_index, captured_values);
} }
// ii. Else, // ii. Else,
else { else {
@ -985,7 +985,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto substring = string.substring_view(last_match_end, next_search_from - last_match_end); auto substring = string.substring_view(last_match_end, next_search_from - last_match_end);
// 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). // 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, substring))))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, Utf16String::create(substring))));
// 3. Set lengthA to lengthA + 1. // 3. Set lengthA to lengthA + 1.
++array_length; ++array_length;
@ -1031,7 +1031,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
auto substring = string.substring_view(last_match_end); auto substring = string.substring_view(last_match_end);
// 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T). // 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, substring))))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, Utf16String::create(substring))));
// 22. Return A. // 22. Return A.
return array; return array;

View file

@ -99,7 +99,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_char_code)
} }
// 3. Return result. // 3. Return result.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, move(string)))); return PrimitiveString::create(vm, Utf16String::create(move(string)));
} }
// 22.1.2.2 String.fromCodePoint ( ...codePoints ), https://tc39.es/ecma262/#sec-string.fromcodepoint // 22.1.2.2 String.fromCodePoint ( ...codePoints ), https://tc39.es/ecma262/#sec-string.fromcodepoint
@ -134,7 +134,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_code_point)
VERIFY(string.is_empty()); VERIFY(string.is_empty());
// 4. Return result. // 4. Return result.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, move(string)))); return PrimitiveString::create(vm, Utf16String::create(move(string)));
} }
// 22.1.2.4 String.raw ( template, ...substitutions ), https://tc39.es/ecma262/#sec-string.raw // 22.1.2.4 String.raw ( template, ...substitutions ), https://tc39.es/ecma262/#sec-string.raw

View file

@ -40,7 +40,7 @@ void StringObject::initialize(Realm& realm)
auto& vm = this->vm(); auto& vm = this->vm();
Base::initialize(realm); Base::initialize(realm);
define_direct_property(vm.names.length, Value(MUST(m_string->utf16_string_view()).length_in_code_units()), 0); define_direct_property(vm.names.length, Value(m_string->utf16_string_view().length_in_code_units()), 0);
} }
void StringObject::visit_edges(Cell::Visitor& visitor) void StringObject::visit_edges(Cell::Visitor& visitor)
@ -73,7 +73,7 @@ static ThrowCompletionOr<Optional<PropertyDescriptor>> string_get_own_property(S
// 6. Let str be S.[[StringData]]. // 6. Let str be S.[[StringData]].
// 7. Assert: Type(str) is String. // 7. Assert: Type(str) is String.
auto str = TRY(string.primitive_string().utf16_string_view()); auto str = string.primitive_string().utf16_string_view();
// 8. Let len be the length of str. // 8. Let len be the length of str.
auto length = str.length_in_code_units(); auto length = str.length_in_code_units();
@ -83,7 +83,7 @@ static ThrowCompletionOr<Optional<PropertyDescriptor>> string_get_own_property(S
return Optional<PropertyDescriptor> {}; return Optional<PropertyDescriptor> {};
// 10. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index (index). // 10. Let resultStr be the String value of length 1, containing one code unit from str, specifically the code unit at index (index).
auto result_str = PrimitiveString::create(vm, TRY(Utf16String::create(vm, str.substring_view(index.as_index(), 1)))); auto result_str = PrimitiveString::create(vm, Utf16String::create(str.substring_view(index.as_index(), 1)));
// 11. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }. // 11. Return the PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.
return PropertyDescriptor { return PropertyDescriptor {
@ -140,7 +140,7 @@ ThrowCompletionOr<MarkedVector<Value>> StringObject::internal_own_property_keys(
auto keys = MarkedVector<Value> { heap() }; auto keys = MarkedVector<Value> { heap() };
// 2. Let str be O.[[StringData]]. // 2. Let str be O.[[StringData]].
auto str = TRY(m_string->utf16_string_view()); auto str = m_string->utf16_string_view();
// 3. Assert: Type(str) is String. // 3. Assert: Type(str) is String.

View file

@ -274,7 +274,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::at)
return js_undefined(); return js_undefined();
// 7. Return ? Get(O, ! ToString(𝔽(k))). // 7. Return ? Get(O, ! ToString(𝔽(k))).
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(index.value(), 1)))); return PrimitiveString::create(vm, Utf16String::create(string.substring_view(index.value(), 1)));
} }
// 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat // 22.1.3.2 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat
@ -293,7 +293,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at)
return PrimitiveString::create(vm, String {}); return PrimitiveString::create(vm, String {});
// 6. Return the substring of S from position to position + 1. // 6. Return the substring of S from position to position + 1.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(position, 1)))); return PrimitiveString::create(vm, Utf16String::create(string.substring_view(position, 1)));
} }
// 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat // 22.1.3.3 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat
@ -693,7 +693,7 @@ static ThrowCompletionOr<Value> pad_string(VM& vm, Utf16String string, Value max
return PrimitiveString::create(vm, move(string)); return PrimitiveString::create(vm, move(string));
// 5. If fillString is undefined, let filler be the String value consisting solely of the code unit 0x0020 (SPACE). // 5. If fillString is undefined, let filler be the String value consisting solely of the code unit 0x0020 (SPACE).
auto filler = TRY(Utf16String::create(vm, Utf16Data { 0x20 })); auto filler = Utf16String::create(Utf16Data { 0x20 });
if (!fill_string.is_undefined()) { if (!fill_string.is_undefined()) {
// 6. Else, let filler be ? ToString(fillString). // 6. Else, let filler be ? ToString(fillString).
filler = TRY(fill_string.to_utf16_string(vm)); filler = TRY(fill_string.to_utf16_string(vm));
@ -1052,7 +1052,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
return PrimitiveString::create(vm, String {}); return PrimitiveString::create(vm, String {});
// 13. Return the substring of S from from to to. // 13. Return the substring of S from from to to.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(int_start, int_end - int_start)))); return PrimitiveString::create(vm, Utf16String::create(string.substring_view(int_start, int_end - int_start)));
} }
// 22.1.3.23 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split // 22.1.3.23 String.prototype.split ( separator, limit ), https://tc39.es/ecma262/#sec-string.prototype.split
@ -1133,7 +1133,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
auto segment = string.substring_view(start, position - start); auto segment = string.substring_view(start, position - start);
// b. Append T to substrings. // b. Append T to substrings.
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, segment))))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, Utf16String::create(segment))));
++array_length; ++array_length;
// c. If the number of elements in substrings is lim, return CreateArrayFromList(substrings). // c. If the number of elements in substrings is lim, return CreateArrayFromList(substrings).
@ -1151,7 +1151,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::split)
auto rest = string.substring_view(start); auto rest = string.substring_view(start);
// 16. Append T to substrings. // 16. Append T to substrings.
MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, TRY(Utf16String::create(vm, rest))))); MUST(array->create_data_property_or_throw(array_length, PrimitiveString::create(vm, Utf16String::create(rest))));
// 17. Return CreateArrayFromList(substrings). // 17. Return CreateArrayFromList(substrings).
return array; return array;
@ -1243,7 +1243,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
size_t to = max(final_start, final_end); size_t to = max(final_start, final_end);
// 10. Return the substring of S from from to to. // 10. Return the substring of S from from to to.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(from, to - from)))); return PrimitiveString::create(vm, Utf16String::create(string.substring_view(from, to - from)));
} }
enum class TargetCase { enum class TargetCase {
@ -1512,7 +1512,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substr)
return PrimitiveString::create(vm, String {}); return PrimitiveString::create(vm, String {});
// 11. Return the substring of S from intStart to intEnd. // 11. Return the substring of S from intStart to intEnd.
return PrimitiveString::create(vm, TRY(Utf16String::create(vm, string.substring_view(int_start, int_end - int_start)))); return PrimitiveString::create(vm, Utf16String::create(string.substring_view(int_start, int_end - int_start)));
} }
// B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml // B.2.2.2.1 CreateHTML ( string, tag, attribute, value ), https://tc39.es/ecma262/#sec-createhtml

View file

@ -11,9 +11,9 @@
namespace JS { namespace JS {
namespace Detail { namespace Detail {
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> the_empty_utf16_string(VM& vm) static NonnullRefPtr<Utf16StringImpl> the_empty_utf16_string()
{ {
static NonnullRefPtr<Utf16StringImpl> empty_string = TRY(Utf16StringImpl::create(vm)); static NonnullRefPtr<Utf16StringImpl> empty_string = Utf16StringImpl::create();
return empty_string; return empty_string;
} }
@ -22,27 +22,27 @@ Utf16StringImpl::Utf16StringImpl(Utf16Data string)
{ {
} }
ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm) NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create()
{ {
return TRY_OR_THROW_OOM(vm, adopt_nonnull_ref_or_enomem(new (nothrow) Utf16StringImpl())); return adopt_ref(*new Utf16StringImpl);
} }
ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, Utf16Data string) NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(Utf16Data string)
{ {
return TRY_OR_THROW_OOM(vm, adopt_nonnull_ref_or_enomem(new (nothrow) Utf16StringImpl(move(string)))); return adopt_ref(*new Utf16StringImpl(move(string)));
} }
ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, StringView string) NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(StringView string)
{ {
return create(vm, TRY_OR_THROW_OOM(vm, utf8_to_utf16(string))); return create(MUST(utf8_to_utf16(string)));
} }
ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> Utf16StringImpl::create(VM& vm, Utf16View const& view) NonnullRefPtr<Utf16StringImpl> Utf16StringImpl::create(Utf16View const& view)
{ {
Utf16Data string; Utf16Data string;
TRY_OR_THROW_OOM(vm, string.try_ensure_capacity(view.length_in_code_units())); string.ensure_capacity(view.length_in_code_units());
string.unchecked_append(view.data(), view.length_in_code_units()); string.unchecked_append(view.data(), view.length_in_code_units());
return create(vm, move(string)); return create(move(string));
} }
Utf16Data const& Utf16StringImpl::string() const Utf16Data const& Utf16StringImpl::string() const
@ -57,24 +57,24 @@ Utf16View Utf16StringImpl::view() const
} }
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm) Utf16String Utf16String::create()
{ {
return Utf16String { TRY(Detail::the_empty_utf16_string(vm)) }; return Utf16String { Detail::the_empty_utf16_string() };
} }
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16Data string) Utf16String Utf16String::create(Utf16Data string)
{ {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, move(string))) }; return Utf16String { Detail::Utf16StringImpl::create(move(string)) };
} }
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, StringView string) Utf16String Utf16String::create(StringView string)
{ {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, string)) }; return Utf16String { Detail::Utf16StringImpl::create(string) };
} }
ThrowCompletionOr<Utf16String> Utf16String::create(VM& vm, Utf16View const& string) Utf16String Utf16String::create(Utf16View const& string)
{ {
return Utf16String { TRY(Detail::Utf16StringImpl::create(vm, string)) }; return Utf16String { Detail::Utf16StringImpl::create(string) };
} }
Utf16String::Utf16String(NonnullRefPtr<Detail::Utf16StringImpl> string) Utf16String::Utf16String(NonnullRefPtr<Detail::Utf16StringImpl> string)
@ -102,14 +102,14 @@ Utf16View Utf16String::substring_view(size_t code_unit_offset) const
return view().substring_view(code_unit_offset); return view().substring_view(code_unit_offset);
} }
ThrowCompletionOr<String> Utf16String::to_utf8(VM& vm) const String Utf16String::to_utf8() const
{ {
return TRY_OR_THROW_OOM(vm, view().to_utf8(Utf16View::AllowInvalidCodeUnits::Yes)); return MUST(view().to_utf8(Utf16View::AllowInvalidCodeUnits::Yes));
} }
ThrowCompletionOr<DeprecatedString> Utf16String::to_deprecated_string(VM& vm) const DeprecatedString Utf16String::to_deprecated_string() const
{ {
return TRY_OR_THROW_OOM(vm, view().to_deprecated_string(Utf16View::AllowInvalidCodeUnits::Yes)); return MUST(view().to_deprecated_string(Utf16View::AllowInvalidCodeUnits::Yes));
} }
u16 Utf16String::code_unit_at(size_t index) const u16 Utf16String::code_unit_at(size_t index) const

View file

@ -21,10 +21,10 @@ class Utf16StringImpl : public RefCounted<Utf16StringImpl> {
public: public:
~Utf16StringImpl() = default; ~Utf16StringImpl() = default;
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&); [[nodiscard]] static NonnullRefPtr<Utf16StringImpl> create();
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16Data); [[nodiscard]] static NonnullRefPtr<Utf16StringImpl> create(Utf16Data);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, StringView); [[nodiscard]] static NonnullRefPtr<Utf16StringImpl> create(StringView);
static ThrowCompletionOr<NonnullRefPtr<Utf16StringImpl>> create(VM&, Utf16View const&); [[nodiscard]] static NonnullRefPtr<Utf16StringImpl> create(Utf16View const&);
Utf16Data const& string() const; Utf16Data const& string() const;
Utf16View view() const; Utf16View view() const;
@ -40,18 +40,18 @@ private:
class Utf16String { class Utf16String {
public: public:
static ThrowCompletionOr<Utf16String> create(VM&); [[nodiscard]] static Utf16String create();
static ThrowCompletionOr<Utf16String> create(VM&, Utf16Data); [[nodiscard]] static Utf16String create(Utf16Data);
static ThrowCompletionOr<Utf16String> create(VM&, StringView); [[nodiscard]] static Utf16String create(StringView);
static ThrowCompletionOr<Utf16String> create(VM&, Utf16View const&); [[nodiscard]] static Utf16String create(Utf16View const&);
Utf16Data const& string() const; Utf16Data const& string() const;
Utf16View view() const; Utf16View view() const;
Utf16View substring_view(size_t code_unit_offset, size_t code_unit_length) const; Utf16View substring_view(size_t code_unit_offset, size_t code_unit_length) const;
Utf16View substring_view(size_t code_unit_offset) const; Utf16View substring_view(size_t code_unit_offset) const;
ThrowCompletionOr<String> to_utf8(VM&) const; [[nodiscard]] String to_utf8() const;
ThrowCompletionOr<DeprecatedString> to_deprecated_string(VM&) const; [[nodiscard]] DeprecatedString to_deprecated_string() const;
u16 code_unit_at(size_t index) const; u16 code_unit_at(size_t index) const;
size_t length_in_code_units() const; size_t length_in_code_units() const;

View file

@ -459,10 +459,10 @@ ThrowCompletionOr<DeprecatedString> Value::to_deprecated_string(VM& vm) const
ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const ThrowCompletionOr<Utf16String> Value::to_utf16_string(VM& vm) const
{ {
if (is_string()) if (is_string())
return TRY(as_string().utf16_string()); return as_string().utf16_string();
auto utf8_string = TRY(to_string(vm)); auto utf8_string = TRY(to_string(vm));
return Utf16String::create(vm, utf8_string.bytes_as_string_view()); return Utf16String::create(utf8_string.bytes_as_string_view());
} }
// 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean // 7.1.2 ToBoolean ( argument ), https://tc39.es/ecma262/#sec-toboolean