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-inl.h" 21#include "src/objects/objects-inl.h" 22#include "unicode/brkiter.h" 23 24namespace v8 { 25namespace internal { 26 27Handle<String> JSSegmentIterator::GranularityAsString(Isolate* isolate) const { 28 return JSSegmenter::GetGranularityString(isolate, granularity()); 29} 30 31// ecma402 #sec-createsegmentiterator 32MaybeHandle<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 DisallowGarbageCollection 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 71MaybeHandle<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