5 #ifndef V8_INTL_SUPPORT 6 #error Internationalization is expected to be enabled. 7 #endif // V8_INTL_SUPPORT 9 #include "src/objects/js-segmenter.h" 15 #include "src/heap/factory.h" 16 #include "src/isolate.h" 17 #include "src/objects-inl.h" 18 #include "src/objects/intl-objects.h" 19 #include "src/objects/js-segmenter-inl.h" 20 #include "src/objects/managed.h" 21 #include "unicode/brkiter.h" 26 JSSegmenter::LineBreakStyle JSSegmenter::GetLineBreakStyle(
const char* str) {
27 if (strcmp(str,
"strict") == 0)
return JSSegmenter::LineBreakStyle::STRICT;
28 if (strcmp(str,
"normal") == 0)
return JSSegmenter::LineBreakStyle::NORMAL;
29 if (strcmp(str,
"loose") == 0)
return JSSegmenter::LineBreakStyle::LOOSE;
33 JSSegmenter::Granularity JSSegmenter::GetGranularity(
const char* str) {
34 if (strcmp(str,
"grapheme") == 0)
return JSSegmenter::Granularity::GRAPHEME;
35 if (strcmp(str,
"word") == 0)
return JSSegmenter::Granularity::WORD;
36 if (strcmp(str,
"sentence") == 0)
return JSSegmenter::Granularity::SENTENCE;
37 if (strcmp(str,
"line") == 0)
return JSSegmenter::Granularity::LINE;
41 MaybeHandle<JSSegmenter> JSSegmenter::Initialize(
42 Isolate* isolate, Handle<JSSegmenter> segmenter_holder,
43 Handle<Object> locales, Handle<Object> input_options) {
44 segmenter_holder->set_flags(0);
47 Maybe<std::vector<std::string>> maybe_requested_locales =
48 Intl::CanonicalizeLocaleList(isolate, locales);
49 MAYBE_RETURN(maybe_requested_locales, Handle<JSSegmenter>());
50 std::vector<std::string> requested_locales =
51 maybe_requested_locales.FromJust();
54 Handle<JSReceiver> options;
55 if (input_options->IsUndefined(isolate)) {
57 options = isolate->factory()->NewJSObjectWithNullProto();
61 ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
62 Object::ToObject(isolate, input_options),
70 Maybe<Intl::MatcherOption> maybe_locale_matcher =
71 Intl::GetLocaleMatcher(isolate, options,
"Intl.Segmenter");
72 MAYBE_RETURN(maybe_locale_matcher, MaybeHandle<JSSegmenter>());
73 Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();
79 Intl::ResolvedLocale r =
80 Intl::ResolveLocale(isolate, JSSegmenter::GetAvailableLocales(),
81 requested_locales, matcher, {});
85 Maybe<LineBreakStyle> maybe_line_break_style =
86 Intl::GetStringOption<LineBreakStyle>(
87 isolate, options,
"lineBreakStyle",
"Intl.Segmenter",
88 {
"strict",
"normal",
"loose"},
89 {LineBreakStyle::STRICT, LineBreakStyle::NORMAL,
90 LineBreakStyle::LOOSE},
91 LineBreakStyle::NORMAL);
92 MAYBE_RETURN(maybe_line_break_style, MaybeHandle<JSSegmenter>());
93 LineBreakStyle line_break_style_enum = maybe_line_break_style.FromJust();
96 Handle<String> locale_str =
97 isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
98 segmenter_holder->set_locale(*locale_str);
102 Maybe<Granularity> maybe_granularity = Intl::GetStringOption<Granularity>(
103 isolate, options,
"granularity",
"Intl.Segmenter",
104 {
"grapheme",
"word",
"sentence",
"line"},
105 {Granularity::GRAPHEME, Granularity::WORD, Granularity::SENTENCE,
107 Granularity::GRAPHEME);
108 MAYBE_RETURN(maybe_granularity, MaybeHandle<JSSegmenter>());
109 Granularity granularity_enum = maybe_granularity.FromJust();
112 segmenter_holder->set_granularity(granularity_enum);
115 if (granularity_enum == Granularity::LINE) {
117 segmenter_holder->set_line_break_style(line_break_style_enum);
119 segmenter_holder->set_line_break_style(LineBreakStyle::NOTSET);
122 icu::Locale icu_locale = r.icu_locale;
123 DCHECK(!icu_locale.isBogus());
125 UErrorCode status = U_ZERO_ERROR;
126 std::unique_ptr<icu::BreakIterator> icu_break_iterator;
128 switch (granularity_enum) {
129 case Granularity::GRAPHEME:
130 icu_break_iterator.reset(
131 icu::BreakIterator::createCharacterInstance(icu_locale, status));
133 case Granularity::WORD:
134 icu_break_iterator.reset(
135 icu::BreakIterator::createWordInstance(icu_locale, status));
137 case Granularity::SENTENCE:
138 icu_break_iterator.reset(
139 icu::BreakIterator::createSentenceInstance(icu_locale, status));
141 case Granularity::LINE: {
144 const char* key = uloc_toLegacyKey(
"lb");
147 uloc_toLegacyType(key, segmenter_holder->LineBreakStyleAsCString());
148 CHECK_NOT_NULL(value);
149 UErrorCode status = U_ZERO_ERROR;
150 icu_locale.setKeywordValue(key, value, status);
151 CHECK(U_SUCCESS(status));
152 icu_break_iterator.reset(
153 icu::BreakIterator::createLineInstance(icu_locale, status));
156 case Granularity::COUNT:
160 CHECK(U_SUCCESS(status));
161 CHECK_NOT_NULL(icu_break_iterator.get());
163 Handle<Managed<icu::BreakIterator>> managed_break_iterator =
164 Managed<icu::BreakIterator>::FromUniquePtr(isolate, 0,
165 std::move(icu_break_iterator));
167 segmenter_holder->set_icu_break_iterator(*managed_break_iterator);
168 return segmenter_holder;
172 Handle<JSObject> JSSegmenter::ResolvedOptions(
173 Isolate* isolate, Handle<JSSegmenter> segmenter_holder) {
174 Factory* factory = isolate->factory();
176 Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
190 Handle<String> locale(segmenter_holder->locale(), isolate);
191 JSObject::AddProperty(isolate, result, factory->locale_string(), locale,
193 JSObject::AddProperty(isolate, result, factory->granularity_string(),
194 segmenter_holder->GranularityAsString(), NONE);
195 if (segmenter_holder->line_break_style() != LineBreakStyle::NOTSET) {
196 JSObject::AddProperty(isolate, result, factory->lineBreakStyle_string(),
197 segmenter_holder->LineBreakStyleAsString(), NONE);
203 const char* JSSegmenter::LineBreakStyleAsCString()
const {
204 switch (line_break_style()) {
205 case LineBreakStyle::STRICT:
207 case LineBreakStyle::NORMAL:
209 case LineBreakStyle::LOOSE:
211 case LineBreakStyle::COUNT:
212 case LineBreakStyle::NOTSET:
217 Handle<String> JSSegmenter::LineBreakStyleAsString()
const {
218 switch (line_break_style()) {
219 case LineBreakStyle::STRICT:
220 return GetReadOnlyRoots().strict_string_handle();
221 case LineBreakStyle::NORMAL:
222 return GetReadOnlyRoots().normal_string_handle();
223 case LineBreakStyle::LOOSE:
224 return GetReadOnlyRoots().loose_string_handle();
225 case LineBreakStyle::COUNT:
226 case LineBreakStyle::NOTSET:
231 Handle<String> JSSegmenter::GranularityAsString()
const {
232 switch (granularity()) {
233 case Granularity::GRAPHEME:
234 return GetReadOnlyRoots().grapheme_string_handle();
235 case Granularity::WORD:
236 return GetReadOnlyRoots().word_string_handle();
237 case Granularity::SENTENCE:
238 return GetReadOnlyRoots().sentence_string_handle();
239 case Granularity::LINE:
240 return GetReadOnlyRoots().line_string_handle();
241 case Granularity::COUNT:
246 std::set<std::string> JSSegmenter::GetAvailableLocales() {
247 int32_t num_locales = 0;
248 const icu::Locale* icu_available_locales =
249 icu::BreakIterator::getAvailableLocales(num_locales);
250 return Intl::BuildLocaleSet(icu_available_locales, num_locales);