Home | History | Annotate | Download | only in src
      1 // Copyright 2014 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 'use strict';
      6 
      7 // This file relies on the fact that the following declaration has been made
      8 // in runtime.js:
      9 // var $String = global.String;
     10 // var $Array = global.Array;
     11 
     12 // -------------------------------------------------------------------
     13 
     14 // ES6 draft 01-20-14, section 21.1.3.13
     15 function StringRepeat(count) {
     16   CHECK_OBJECT_COERCIBLE(this, "String.prototype.repeat");
     17 
     18   var s = TO_STRING_INLINE(this);
     19   var n = ToInteger(count);
     20   if (n < 0 || !NUMBER_IS_FINITE(n)) {
     21     throw MakeRangeError("invalid_count_value", []);
     22   }
     23 
     24   var elements = new InternalArray(n);
     25   for (var i = 0; i < n; i++) {
     26     elements[i] = s;
     27   }
     28 
     29   return %StringBuilderConcat(elements, n, "");
     30 }
     31 
     32 
     33 // ES6 draft 04-05-14, section 21.1.3.18
     34 function StringStartsWith(searchString /* position */) {  // length == 1
     35   CHECK_OBJECT_COERCIBLE(this, "String.prototype.startsWith");
     36 
     37   var s = TO_STRING_INLINE(this);
     38 
     39   if (IS_REGEXP(searchString)) {
     40     throw MakeTypeError("first_argument_not_regexp",
     41                         ["String.prototype.startsWith"]);
     42   }
     43 
     44   var ss = TO_STRING_INLINE(searchString);
     45   var pos = 0;
     46   if (%_ArgumentsLength() > 1) {
     47     pos = %_Arguments(1);  // position
     48     pos = ToInteger(pos);
     49   }
     50 
     51   var s_len = s.length;
     52   var start = MathMin(MathMax(pos, 0), s_len);
     53   var ss_len = ss.length;
     54   if (ss_len + start > s_len) {
     55     return false;
     56   }
     57 
     58   return %StringIndexOf(s, ss, start) === start;
     59 }
     60 
     61 
     62 // ES6 draft 04-05-14, section 21.1.3.7
     63 function StringEndsWith(searchString /* position */) {  // length == 1
     64   CHECK_OBJECT_COERCIBLE(this, "String.prototype.endsWith");
     65 
     66   var s = TO_STRING_INLINE(this);
     67 
     68   if (IS_REGEXP(searchString)) {
     69     throw MakeTypeError("first_argument_not_regexp",
     70                         ["String.prototype.endsWith"]);
     71   }
     72 
     73   var ss = TO_STRING_INLINE(searchString);
     74   var s_len = s.length;
     75   var pos = s_len;
     76   if (%_ArgumentsLength() > 1) {
     77     var arg = %_Arguments(1);  // position
     78     if (!IS_UNDEFINED(arg)) {
     79       pos = ToInteger(arg);
     80     }
     81   }
     82 
     83   var end = MathMin(MathMax(pos, 0), s_len);
     84   var ss_len = ss.length;
     85   var start = end - ss_len;
     86   if (start < 0) {
     87     return false;
     88   }
     89 
     90   return %StringLastIndexOf(s, ss, start) === start;
     91 }
     92 
     93 
     94 // ES6 draft 04-05-14, section 21.1.3.6
     95 function StringContains(searchString /* position */) {  // length == 1
     96   CHECK_OBJECT_COERCIBLE(this, "String.prototype.contains");
     97 
     98   var s = TO_STRING_INLINE(this);
     99 
    100   if (IS_REGEXP(searchString)) {
    101     throw MakeTypeError("first_argument_not_regexp",
    102                         ["String.prototype.contains"]);
    103   }
    104 
    105   var ss = TO_STRING_INLINE(searchString);
    106   var pos = 0;
    107   if (%_ArgumentsLength() > 1) {
    108     pos = %_Arguments(1);  // position
    109     pos = ToInteger(pos);
    110   }
    111 
    112   var s_len = s.length;
    113   var start = MathMin(MathMax(pos, 0), s_len);
    114   var ss_len = ss.length;
    115   if (ss_len + start > s_len) {
    116     return false;
    117   }
    118 
    119   return %StringIndexOf(s, ss, start) !== -1;
    120 }
    121 
    122 
    123 // -------------------------------------------------------------------
    124 
    125 function ExtendStringPrototype() {
    126   %CheckIsBootstrapping();
    127 
    128   // Set up the non-enumerable functions on the String prototype object.
    129   InstallFunctions($String.prototype, DONT_ENUM, $Array(
    130     "repeat", StringRepeat,
    131     "startsWith", StringStartsWith,
    132     "endsWith", StringEndsWith,
    133     "contains", StringContains
    134   ));
    135 }
    136 
    137 ExtendStringPrototype();
    138