string-substring.tq 1.67 KB
Newer Older
1 2 3 4 5 6 7 8 9
// 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)(
10
      value: JSAny, limit: Smi): Smi {
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
    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(
31
      js-implicit context: Context, receiver: JSAny)(...arguments): String {
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
    // 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));
  }
}