Line data Source code
1 : // Copyright 2018 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_INTL_SUPPORT
6 : #error Internationalization is expected to be enabled.
7 : #endif // V8_INTL_SUPPORT
8 :
9 : #include "src/objects/js-break-iterator.h"
10 :
11 : #include "src/objects/intl-objects.h"
12 : #include "src/objects/js-break-iterator-inl.h"
13 : #include "unicode/brkiter.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 230 : MaybeHandle<JSV8BreakIterator> JSV8BreakIterator::Initialize(
19 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator_holder,
20 : Handle<Object> locales, Handle<Object> options_obj) {
21 : Factory* factory = isolate->factory();
22 :
23 : // 1. Let requestedLocales be ? CanonicalizeLocaleList(locales).
24 : Maybe<std::vector<std::string>> maybe_requested_locales =
25 230 : Intl::CanonicalizeLocaleList(isolate, locales);
26 230 : MAYBE_RETURN(maybe_requested_locales, MaybeHandle<JSV8BreakIterator>());
27 : std::vector<std::string> requested_locales =
28 230 : maybe_requested_locales.FromJust();
29 :
30 : Handle<JSReceiver> options;
31 230 : if (options_obj->IsUndefined(isolate)) {
32 158 : options = factory->NewJSObjectWithNullProto();
33 : } else {
34 144 : ASSIGN_RETURN_ON_EXCEPTION(
35 : isolate, options,
36 : Object::ToObject(isolate, options_obj, "Intl.JSV8BreakIterator"),
37 : JSV8BreakIterator);
38 : }
39 :
40 : // Extract locale string
41 : Maybe<Intl::MatcherOption> maybe_locale_matcher =
42 221 : Intl::GetLocaleMatcher(isolate, options, "Intl.JSV8BreakIterator");
43 221 : MAYBE_RETURN(maybe_locale_matcher, MaybeHandle<JSV8BreakIterator>());
44 : Intl::MatcherOption matcher = maybe_locale_matcher.FromJust();
45 :
46 : Intl::ResolvedLocale r =
47 : Intl::ResolveLocale(isolate, JSV8BreakIterator::GetAvailableLocales(),
48 663 : requested_locales, matcher, {});
49 :
50 : // Extract type from options
51 : Maybe<Type> maybe_type = Intl::GetStringOption<Type>(
52 : isolate, options, "type", "Intl.v8BreakIterator",
53 : {"word", "character", "sentence", "line"},
54 663 : {Type::WORD, Type::CHARACTER, Type::SENTENCE, Type::LINE}, Type::WORD);
55 221 : MAYBE_RETURN(maybe_type, MaybeHandle<JSV8BreakIterator>());
56 : Type type_enum = maybe_type.FromJust();
57 :
58 442 : icu::Locale icu_locale = r.icu_locale;
59 : DCHECK(!icu_locale.isBogus());
60 :
61 : // Construct break_iterator using icu_locale and type
62 221 : UErrorCode status = U_ZERO_ERROR;
63 : std::unique_ptr<icu::BreakIterator> break_iterator = nullptr;
64 221 : switch (type_enum) {
65 : case Type::CHARACTER:
66 0 : break_iterator.reset(
67 : icu::BreakIterator::createCharacterInstance(icu_locale, status));
68 : break;
69 : case Type::SENTENCE:
70 0 : break_iterator.reset(
71 : icu::BreakIterator::createSentenceInstance(icu_locale, status));
72 : break;
73 : case Type::LINE:
74 0 : break_iterator.reset(
75 : icu::BreakIterator::createLineInstance(icu_locale, status));
76 : break;
77 : default:
78 221 : break_iterator.reset(
79 : icu::BreakIterator::createWordInstance(icu_locale, status));
80 : break;
81 : }
82 :
83 : // Error handling for break_iterator
84 221 : if (U_FAILURE(status)) {
85 0 : FATAL("Failed to create ICU break iterator, are ICU data files missing?");
86 : }
87 221 : CHECK_NOT_NULL(break_iterator.get());
88 221 : isolate->CountUsage(v8::Isolate::UseCounterFeature::kBreakIterator);
89 :
90 : // Construct managed objects from pointers
91 : Handle<Managed<icu::BreakIterator>> managed_break_iterator =
92 : Managed<icu::BreakIterator>::FromUniquePtr(isolate, 0,
93 442 : std::move(break_iterator));
94 : Handle<Managed<icu::UnicodeString>> managed_unicode_string =
95 221 : Managed<icu::UnicodeString>::FromRawPtr(isolate, 0, nullptr);
96 :
97 : Handle<String> locale_str =
98 221 : isolate->factory()->NewStringFromAsciiChecked(r.locale.c_str());
99 221 : break_iterator_holder->set_locale(*locale_str);
100 :
101 : break_iterator_holder->set_type(type_enum);
102 221 : break_iterator_holder->set_break_iterator(*managed_break_iterator);
103 221 : break_iterator_holder->set_unicode_string(*managed_unicode_string);
104 :
105 : // Return break_iterator_holder
106 221 : return break_iterator_holder;
107 : }
108 :
109 72 : Handle<JSObject> JSV8BreakIterator::ResolvedOptions(
110 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
111 : Factory* factory = isolate->factory();
112 :
113 72 : Handle<JSObject> result = factory->NewJSObject(isolate->object_function());
114 : Handle<String> locale(break_iterator->locale(), isolate);
115 :
116 72 : JSObject::AddProperty(isolate, result, factory->locale_string(), locale,
117 72 : NONE);
118 144 : JSObject::AddProperty(isolate, result, factory->type_string(),
119 72 : break_iterator->TypeAsString(), NONE);
120 72 : return result;
121 : }
122 :
123 41 : void JSV8BreakIterator::AdoptText(
124 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator_holder,
125 : Handle<String> text) {
126 : icu::BreakIterator* break_iterator =
127 82 : break_iterator_holder->break_iterator()->raw();
128 41 : CHECK_NOT_NULL(break_iterator);
129 : Managed<icu::UnicodeString> unicode_string =
130 41 : Intl::SetTextToBreakIterator(isolate, text, break_iterator);
131 41 : break_iterator_holder->set_unicode_string(unicode_string);
132 41 : }
133 :
134 72 : Handle<String> JSV8BreakIterator::TypeAsString() const {
135 72 : switch (type()) {
136 : case Type::CHARACTER:
137 : return GetReadOnlyRoots().character_string_handle();
138 : case Type::WORD:
139 : return GetReadOnlyRoots().word_string_handle();
140 : case Type::SENTENCE:
141 : return GetReadOnlyRoots().sentence_string_handle();
142 : case Type::LINE:
143 : return GetReadOnlyRoots().line_string_handle();
144 : case Type::COUNT:
145 0 : UNREACHABLE();
146 : }
147 0 : }
148 :
149 0 : Handle<Object> JSV8BreakIterator::Current(
150 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
151 : return isolate->factory()->NewNumberFromInt(
152 0 : break_iterator->break_iterator()->raw()->current());
153 : }
154 :
155 36 : Handle<Object> JSV8BreakIterator::First(
156 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
157 : return isolate->factory()->NewNumberFromInt(
158 72 : break_iterator->break_iterator()->raw()->first());
159 : }
160 :
161 415 : Handle<Object> JSV8BreakIterator::Next(
162 : Isolate* isolate, Handle<JSV8BreakIterator> break_iterator) {
163 : return isolate->factory()->NewNumberFromInt(
164 830 : break_iterator->break_iterator()->raw()->next());
165 : }
166 :
167 279 : String JSV8BreakIterator::BreakType(Isolate* isolate,
168 : Handle<JSV8BreakIterator> break_iterator) {
169 558 : int32_t status = break_iterator->break_iterator()->raw()->getRuleStatus();
170 : // Keep return values in sync with JavaScript BreakType enum.
171 279 : if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
172 : return ReadOnlyRoots(isolate).none_string();
173 : }
174 144 : if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
175 : return ReadOnlyRoots(isolate).number_string();
176 : }
177 144 : if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
178 : return ReadOnlyRoots(isolate).letter_string();
179 : }
180 54 : if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
181 : return ReadOnlyRoots(isolate).kana_string();
182 : }
183 54 : if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
184 : return ReadOnlyRoots(isolate).ideo_string();
185 : }
186 : return ReadOnlyRoots(isolate).unknown_string();
187 : }
188 :
189 5 : const std::set<std::string>& JSV8BreakIterator::GetAvailableLocales() {
190 : static base::LazyInstance<Intl::AvailableLocales<icu::BreakIterator>>::type
191 : available_locales = LAZY_INSTANCE_INITIALIZER;
192 5 : return available_locales.Pointer()->Get();
193 : }
194 :
195 : } // namespace internal
196 120216 : } // namespace v8
|