| // Copyright 2019 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| namespace string { |
| |
| macro NewJSStringIterator(implicit context: Context)( |
| string: String, nextIndex: Smi): JSStringIterator { |
| return new JSStringIterator{ |
| map: GetInitialStringIteratorMap(), |
| properties_or_hash: kEmptyFixedArray, |
| elements: kEmptyFixedArray, |
| string: string, |
| index: nextIndex |
| }; |
| } |
| |
| // ES6 #sec-string.prototype-@@iterator |
| transitioning javascript builtin StringPrototypeIterator( |
| js-implicit context: NativeContext, receiver: JSAny)(): JSStringIterator { |
| const name: String = |
| ToThisString(receiver, 'String.prototype[Symbol.iterator]'); |
| const index: Smi = 0; |
| return NewJSStringIterator(name, index); |
| } |
| |
| // ES6 #sec-%stringiteratorprototype%.next |
| transitioning javascript builtin StringIteratorPrototypeNext( |
| js-implicit context: NativeContext, receiver: JSAny)(): JSObject { |
| const iterator = Cast<JSStringIterator>(receiver) otherwise ThrowTypeError( |
| MessageTemplate::kIncompatibleMethodReceiver, |
| 'String Iterator.prototype.next', receiver); |
| const string = iterator.string; |
| const position: intptr = SmiUntag(iterator.index); |
| const length: intptr = string.length_intptr; |
| if (position >= length) { |
| return AllocateJSIteratorResult(Undefined, True); |
| } |
| // Move to next codepoint. |
| const encoding = UnicodeEncoding::UTF16; |
| const ch = string::LoadSurrogatePairAt(string, length, position, encoding); |
| const value: String = string::StringFromSingleUTF16EncodedCodePoint(ch); |
| iterator.index = SmiTag(position + value.length_intptr); |
| return AllocateJSIteratorResult(value, False); |
| } |
| } |