• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-segment-iterator.h"
10 
11 #include <map>
12 #include <memory>
13 #include <string>
14 
15 #include "src/execution/isolate.h"
16 #include "src/heap/factory.h"
17 #include "src/objects/intl-objects.h"
18 #include "src/objects/js-segment-iterator-inl.h"
19 #include "src/objects/js-segments.h"
20 #include "src/objects/managed.h"
21 #include "src/objects/objects-inl.h"
22 #include "unicode/brkiter.h"
23 
24 namespace v8 {
25 namespace internal {
26 
GranularityAsString(Isolate * isolate) const27 Handle<String> JSSegmentIterator::GranularityAsString(Isolate* isolate) const {
28   return JSSegmenter::GetGranularityString(isolate, granularity());
29 }
30 
31 // ecma402 #sec-createsegmentiterator
Create(Isolate * isolate,icu::BreakIterator * break_iterator,JSSegmenter::Granularity granularity)32 MaybeHandle<JSSegmentIterator> JSSegmentIterator::Create(
33     Isolate* isolate, icu::BreakIterator* break_iterator,
34     JSSegmenter::Granularity granularity) {
35   // Clone a copy for both the ownership and not sharing with containing and
36   // other calls to the iterator because icu::BreakIterator keep the iteration
37   // position internally and cannot be shared across multiple calls to
38   // JSSegmentIterator::Create and JSSegments::Containing.
39   break_iterator = break_iterator->clone();
40   DCHECK_NOT_NULL(break_iterator);
41   Handle<Map> map = Handle<Map>(
42       isolate->native_context()->intl_segment_iterator_map(), isolate);
43 
44   // 5. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to 0.
45   break_iterator->first();
46   Handle<Managed<icu::BreakIterator>> managed_break_iterator =
47       Managed<icu::BreakIterator>::FromRawPtr(isolate, 0, break_iterator);
48 
49   icu::UnicodeString* string = new icu::UnicodeString();
50   break_iterator->getText().getText(*string);
51   Handle<Managed<icu::UnicodeString>> unicode_string =
52       Managed<icu::UnicodeString>::FromRawPtr(isolate, 0, string);
53 
54   break_iterator->setText(*string);
55 
56   // Now all properties are ready, so we can allocate the result object.
57   Handle<JSObject> result = isolate->factory()->NewJSObjectFromMap(map);
58   DisallowHeapAllocation no_gc;
59   Handle<JSSegmentIterator> segment_iterator =
60       Handle<JSSegmentIterator>::cast(result);
61 
62   segment_iterator->set_flags(0);
63   segment_iterator->set_granularity(granularity);
64   segment_iterator->set_icu_break_iterator(*managed_break_iterator);
65   segment_iterator->set_unicode_string(*unicode_string);
66 
67   return segment_iterator;
68 }
69 
70 // ecma402 #sec-%segmentiteratorprototype%.next
Next(Isolate * isolate,Handle<JSSegmentIterator> segment_iterator)71 MaybeHandle<JSReceiver> JSSegmentIterator::Next(
72     Isolate* isolate, Handle<JSSegmentIterator> segment_iterator) {
73   Factory* factory = isolate->factory();
74   icu::BreakIterator* icu_break_iterator =
75       segment_iterator->icu_break_iterator().raw();
76   // 5. Let startIndex be iterator.[[IteratedStringNextSegmentCodeUnitIndex]].
77   int32_t start_index = icu_break_iterator->current();
78   // 6. Let endIndex be ! FindBoundary(segmenter, string, startIndex, after).
79   int32_t end_index = icu_break_iterator->next();
80 
81   // 7. If endIndex is not finite, then
82   if (end_index == icu::BreakIterator::DONE) {
83     // a. Return ! CreateIterResultObject(undefined, true).
84     return factory->NewJSIteratorResult(isolate->factory()->undefined_value(),
85                                         true);
86   }
87 
88   // 8. Set iterator.[[IteratedStringNextSegmentCodeUnitIndex]] to endIndex.
89 
90   // 9. Let segmentData be ! CreateSegmentDataObject(segmenter, string,
91   // startIndex, endIndex).
92 
93   icu::UnicodeString string;
94   icu_break_iterator->getText().getText(string);
95 
96   Handle<Object> segment_data;
97   ASSIGN_RETURN_ON_EXCEPTION(
98       isolate, segment_data,
99       JSSegments::CreateSegmentDataObject(
100           isolate, segment_iterator->granularity(), icu_break_iterator, string,
101           start_index, end_index),
102       JSReceiver);
103 
104   // 10. Return ! CreateIterResultObject(segmentData, false).
105   return factory->NewJSIteratorResult(segment_data, false);
106 }
107 
108 }  // namespace internal
109 }  // namespace v8
110