summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/string-iterator.tq
blob: b0bbb8d4a35dc29f7504e7c6a6ebd1105d569812 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 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_iterator {

  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: Context, 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: Context, receiver: JSAny)(): JSObject {
    const iterator = Cast<JSStringIterator>(receiver) otherwise ThrowTypeError(
        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 = 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);
  }
}