summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/string-substring.tq
blob: c97b294a34fedda9c755d0791d4c8ae379b90d7a (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
47
48
49
50
// 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_substring {

  extern macro SubString(String, intptr, intptr): String;

  transitioning macro ToSmiBetweenZeroAnd(implicit context: Context)(
      value: JSAny, limit: Smi): Smi {
    const valueInt: Number =
        ToInteger_Inline(context, value, kTruncateMinusZero);
    typeswitch (valueInt) {
      case (valueSmi: Smi): {
        if (SmiAbove(valueSmi, limit)) {
          return valueSmi < 0 ? 0 : limit;
        }
        return valueSmi;
      }
      // {value} is a heap number - in this case, it is definitely out of
      // bounds.
      case (hn: HeapNumber): {
        const valueFloat: float64 = LoadHeapNumberValue(hn);
        return valueFloat < 0. ? 0 : limit;
      }
    }
  }

  // ES6 #sec-string.prototype.substring
  transitioning javascript builtin StringPrototypeSubstring(
      js-implicit context: Context, receiver: JSAny)(...arguments): String {
    // Check that {receiver} is coercible to Object and convert it to a String.
    const string: String = ToThisString(receiver, 'String.prototype.substring');
    const length = string.length_smi;

    // Conversion and bounds-checks for {start}.
    let start: Smi = ToSmiBetweenZeroAnd(arguments[0], length);

    // Conversion and bounds-checks for {end}.
    let end: Smi = arguments[1] == Undefined ?
        length :
        ToSmiBetweenZeroAnd(arguments[1], length);
    if (end < start) {
      const tmp: Smi = end;
      end = start;
      start = tmp;
    }
    return SubString(string, SmiUntag(start), SmiUntag(end));
  }
}