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 // ES6 Draft 05-22-2014, section 21.1.3.3
    124 function StringCodePointAt(pos) {
    125   CHECK_OBJECT_COERCIBLE(this, "String.prototype.codePointAt");
    126 
    127   var string = TO_STRING_INLINE(this);
    128   var size = string.length;
    129   pos = TO_INTEGER(pos);
    130   if (pos < 0 || pos >= size) {
    131     return UNDEFINED;
    132   }
    133   var first = %_StringCharCodeAt(string, pos);
    134   if (first < 0xD800 || first > 0xDBFF || pos + 1 == size) {
    135     return first;
    136   }
    137   var second = %_StringCharCodeAt(string, pos + 1);
    138   if (second < 0xDC00 || second > 0xDFFF) {
    139     return first;
    140   }
    141   return (first - 0xD800) * 0x400 + second + 0x2400;
    142 }
    143 
    144 
    145 // ES6 Draft 05-22-2014, section 21.1.2.2
    146 function StringFromCodePoint(_) {  // length = 1
    147   var code;
    148   var length = %_ArgumentsLength();
    149   var index;
    150   var result = "";
    151   for (index = 0; index < length; index++) {
    152     code = %_Arguments(index);
    153     if (!%_IsSmi(code)) {
    154       code = ToNumber(code);
    155     }
    156     if (code < 0 || code > 0x10FFFF || code !== TO_INTEGER(code)) {
    157       throw MakeRangeError("invalid_code_point", [code]);
    158     }
    159     if (code <= 0xFFFF) {
    160       result += %_StringCharFromCode(code);
    161     } else {
    162       code -= 0x10000;
    163       result += %_StringCharFromCode((code >>> 10) & 0x3FF | 0xD800);
    164       result += %_StringCharFromCode(code & 0x3FF | 0xDC00);
    165     }
    166   }
    167   return result;
    168 }
    169 
    170 
    171 // -------------------------------------------------------------------
    172 
    173 function ExtendStringPrototype() {
    174   %CheckIsBootstrapping();
    175 
    176   // Set up the non-enumerable functions on the String object.
    177   InstallFunctions($String, DONT_ENUM, $Array(
    178     "fromCodePoint", StringFromCodePoint
    179   ));
    180 
    181   // Set up the non-enumerable functions on the String prototype object.
    182   InstallFunctions($String.prototype, DONT_ENUM, $Array(
    183     "codePointAt", StringCodePointAt,
    184     "contains", StringContains,
    185     "endsWith", StringEndsWith,
    186     "repeat", StringRepeat,
    187     "startsWith", StringStartsWith
    188   ));
    189 }
    190 
    191 ExtendStringPrototype();
    192